diff --git a/icons/creatures/chamule.svg b/icons/creatures/chamule.svg index 6ddaf4c4..c2342281 100644 --- a/icons/creatures/chamule.svg +++ b/icons/creatures/chamule.svg @@ -37,16 +37,16 @@ guidetolerance="10" inkscape:pageopacity="0" inkscape:pageshadow="2" - inkscape:window-width="3840" - inkscape:window-height="2066" + inkscape:window-width="2056" + inkscape:window-height="997" id="namedview57" showgrid="false" - inkscape:zoom="1.6310818" - inkscape:cx="764.55266" - inkscape:cy="395.59228" - inkscape:window-x="-11" - inkscape:window-y="-11" - inkscape:window-maximized="1" + inkscape:zoom="1.153349" + inkscape:cx="470.48408" + inkscape:cy="229.26543" + inkscape:window-x="668" + inkscape:window-y="872" + inkscape:window-maximized="0" inkscape:current-layer="svg55" inkscape:document-rotation="0" fit-margin-top="0" @@ -59,5 +59,5 @@ stroke="#000000" stroke-width="1.5" d="m 437.17618,99.433481 c 0.36,-3.21 0.51,-7.515 1.68,-10.44 1.14,-2.865 3.735,-5.28 3.21,-7.77 -1.005,-4.725 -8.97,-3.48 -11.49,-9.135 -3.525,-7.86 3.45,-27.09 7.62,-34.155 2.205,-3.735 4.86,-7.65 9.48,-8.445001 12.69,-2.19 17.55,25.950001 23.13,29.355001 2.55,1.575 6.87,0.84 9.87,1.05 3.945,0.105 11.265,1.56 14.745,0 10.575,-4.38 12.09,-19.86 21.255,-24.96 -1.515,18.45 -8.19,26.625 -8.595,31.44 -0.765,8.895 14.31,10.095 14.865,19.575 0.195,3.27 -7.5,21.974999 -10.035,24.224999 0,0 -10.98,6.585 -10.98,6.585 -3.57,2.85 -5.94,6.75 -10.77,7.56 -5.445,0.93 -10.755,-2.505 -14.985,-5.385 -2.025,5.58 -3.945,8.22 1.5,12 0,0 -3,6 -3,6 0,0 10.5,3 10.5,3 0,0 0,3 0,3 0,0 -10.5,1.5 -10.5,1.5 5.745,4.815 12.63,7.755 15,15 0,0 -7.5,-4.5 -7.5,-4.5 0,0 6,7.5 6,7.5 -3.195,11.41503 0.18,22.90503 0,34.50003 -0.285,17.22 -7.095,8.22 -4.5,25.5 -7.185,2.925 -7.77,3.06 -6,10.5 0,0 -4.5,-1.5 -4.5,-1.5 0,0 4.5,12 4.5,12 0,0 -7.5,-1.5 -7.5,-1.5 0,0 6,6 6,6 0,0 -4.5,6 -4.5,6 0,0 -1.185,33 -1.185,33 1.05,7.38 7.05,14.475 6.465,21 -0.48,5.37 -3.51,8.715 -8.28,10.5 0,0 1.5,7.5 1.5,7.5 0,0 -7.5,-4.5 -7.5,-4.5 0,0 -1.5,9 -1.5,9 0,0 -5.61,1.35 -5.61,1.35 0,0 -19.89,18.51 -19.89,18.51 0,0 -16.5,9.45 -16.5,9.45 0,0 -10.485,5.64 -10.485,5.64 0,0 -2.865,10.05 -2.865,10.05 0,0 -5.16,25.5 -5.16,25.5 0,0 7.545,13.5 7.545,13.5 0,0 4.305,18 4.305,18 0,0 -1.65,25.5 -1.65,25.5 0,0 3.48,19.5 3.48,19.5 0,0 4.365,16.5 4.365,16.5 0,0 -4.275,16.5 -4.275,16.5 0,0 -1.515,13.245 -1.515,13.245 0,0 -22.245,21.255 -22.245,21.255 -1.905,-0.405 -3.885,-0.675 -5.685,-1.485 -4.47,-2.025 -8.055,-8.355 -5.145,-12.945 3.45,-5.445 11.085,-5.025 16.83,-17.07 0,0 -6,-1.5 -6,-1.5 0,0 10.5,-16.5 10.5,-16.5 -13.335,-4.56 -12.405,-11.475 -17.205,-22.5 -4.23,-9.72 -8.985,-10.545 -11.745,-16.635 -4.755,-10.455 1.14,-13.98 -8.55,-26.865 -2.385,10.425 -3.72,10.695 -7.425,19.5 0,0 -12.945,40.5 -12.945,40.5 -0.6,6.93 4.26,15 5.085,22.5 0.96,8.535 -1.29,13.485 3.555,22.365 5.16,9.48 14.385,8.085 19.02,11.535 3.84,2.865 4.815,6.795 6.21,11.1 -12.555,6.51 -13.83,6.87 -27,2.82 -3,-0.915 -7.62,-2.1 -10.035,-4.08 -3.9,-3.195 -3.105,-7.23 -6.195,-13.74 -7.155,-15.015 -12.18,-15.21 -12.405,-34.5 0,0 0,-12 0,-12 -1.17,-8.655 -4.05,-11.085 -2.415,-22.5 0,0 5.1,-24.855 5.1,-24.855 0,0 5.505,-11.4 5.505,-11.4 2.715,-10.89 -6.18,-12.66 -3.555,-25.245 0,0 -4.5,-3 -4.5,-3 0,0 10.5,-1.5 10.5,-1.5 0,0 -9,-6 -9,-6 0,0 10.5,0 10.5,0 0,0 -6,-4.5 -6,-4.5 0,0 0,-4.5 0,-4.5 0,0 6,-1.5 6,-1.5 0,0 -1.5,-4.5 -1.5,-4.5 0,0 -6,3 -6,3 0,0 10.5,-13.5 10.5,-13.5 0,0 -7.5,1.5 -7.5,1.5 0,0 3,-9 3,-9 -13.245,-0.84 -10.365,2.97 -21,6 0,0 0,-7.5 0,-7.5 0,0 -3,3 -3,3 0,0 -1.5,0 -1.5,0 0,0 -4.5,-4.5 -4.5,-4.5 0,0 0,6 0,6 4.02,1.38 5.37,1.485 4.5,6 0,0 -4.5,-4.5 -4.5,-4.5 0,0 -1.5,19.5 -1.5,19.5 -6.285,-2.58 -5.715,-8.91 -6,-15 0,0 -10.5,12 -10.5,12 0,0 -7.5,-3 -7.5,-3 0,0 1.5,6 1.5,6 -4.86,-3.255 -4.305,-4.92 -4.5,-10.5 0,0 -3,0 -3,0 0,7.89 2.625,17.985 -6,21 0,0 1.5,-10.5 1.5,-10.5 0,0 -6,0 -6,0 0,0 4.5,-18 4.5,-18 0,0 -3,0 -3,0 0,0 -4.5,19.5 -4.5,19.5 0,0 -9,1.5 -9,1.5 0,0 -1.5,4.5 -1.5,4.5 -11.535,-4.035 -0.855,-9.99 -9,-19.5 0,0 -3,21 -3,21 -5.595,-3.75 -4.47,-7.275 -4.5,-13.5 0,0 -4.5,-3 -4.5,-3 -8.475,3.135 -10.26,-1.245 -9,-9 -9.78,8.325 -4.5,13.185 -11.145,20.67 -3.75,4.23 -7.86,4.53 -12.435,8.445 -5.925,5.1 -21.075,23.925 -25.89,30.885 -2.865,4.155 -8.97,11.91 -8.895,16.92 0,0 4.125,22.08 4.125,22.08 1.53,11.655 1.215,32.685 7.935,41.79 4.92,6.66 11.28,5.025 17.49,10.185 4.035,3.345 7.86,10.305 1.575,13.635 -2.28,1.2 -4.8,0.915 -7.26,0.75 -3.45,-0.24 -7.335,-0.585 -10.485,-2.07 -5.58,-2.61 -17.745,-15.15 -19.905,-20.79 -1.98,-5.16 -0.015,-9.87 -4.11,-18 -2.805,-5.595 -5.715,-8.19 -10.2,-12 1.185,-6.12 1.875,-11.79 0,-18 -3.21,-13.665 -15.72,-26.595 1.2,-36 0,0 -1.5,-4.5 -1.5,-4.5 0,0 6,-1.5 6,-1.5 0,0 -3,-6 -3,-6 0,0 4.5,-3 4.5,-3 0,0 -4.5,-1.5 -4.5,-1.5 0,0 0,-3 0,-3 0,0 7.5,-1.5 7.5,-1.5 -8.97,-11.46 -0.75,-8.925 -1.5,-22.5 0,0 -31.5,22.5 -31.5,22.5 -7.2,5.19 -9.075,8.61 -17.999998,10.5 8.519998,11.805 25.454998,28.215 23.999998,43.5 -10.185,-6.21 -16.755,-9.165 -25.034998,-18.255 -2.505,-2.745 -6.614996,-9.72 -10.799996,-9.105 -4.89,0.72 -6.87,14.13 -7.83,18.36 -0.87,3.795 -1.29,8.565 -2.715,12 0,0 -5.595,10.5 -5.595,10.5 -3.705,8.265 -5.145,21.57 -1.485,30 8.715,20.025 26.654996,1.335 29.459996,25.5 -5.46,1.725 -11.144996,5.685 -16.499996,5.355 -17.7,-1.08 -25.215,-15.015 -31.5,-29.355 -2.01,-4.56 -5.4,-10.125 -5.67,-15 0,0 9.045,-43.5 9.045,-43.5 2.445,-15.06 -1.815,-24.12 7.125,-37.5 -2.82,-3.15 -3.96,-5.49 -6.165,-9 -6.9,-11.01 -7.29,-9.15 -7.335,-22.5 0,0 -6,0 -6,0 0,0 3,-9 3,-9 -7.185,-2.985 -3.57,-13.425 -2.04,-19.5 0,0 9.3,-24.735 9.3,-24.735 0,0 6.345,-7.035 6.345,-7.035 0,0 4.155,-7.995 4.155,-7.995 3.9,-4.83 5.295,-2.31 7.74,-9.735 0,0 16.5,-7.5 16.5,-7.5 0,0 -1.5,-7.5 -1.5,-7.5 0,0 1.5,-1.5 1.5,-1.5 17.099994,1.725 14.834996,-19.8 28.499994,-13.5 0,0 4.5,-7.5 4.5,-7.5 18.855,0.33 10.545,-16.575 30,-26.43 17.955,-9.12 39,-9.3 58.5,-10.995 0,0 18,-1.35 18,-1.35 0,0 18,0 18,0 0,0 13.5,2.64 13.5,2.64 0,0 27,2.04 27,2.04 9.435,1.83 13.575,8.565 37.5,8.595 10.83,0.015 24.48,0.495 34.5,-4.14 11.64,-5.385 18.345,-16.62 39,-17.085 3.735,0.18 13.65,0.87 16.47,0 10.77,-4.47 13.155,-23.01 16.11,-32.775 0,0 7.275,-19.50003 7.275,-19.50003 0,0 -3.6,-33 -3.6,-33 -0.72,-7.695 0.495,-9.765 0.975,-16.5 0.345,-5.01 -0.825,-10.005 -1.23,-15 0,0 7.5,-1.5 7.5,-1.5 0,0 -6,-5.999999 -6,-5.999999 0,0 6,1.5 6,1.5 z m -322.5,214.500029 c 0,0 -13.5,-1.5 -13.5,-1.5 0,0 -4.499998,9 -4.499998,9 0,0 -3,0 -3,0 0,0 -4.499996,-6 -4.499996,-6 0,0 -7.5,15 -7.5,15 0,0 -3,0 -3,0 0,0 -4.5,-6 -4.5,-6 0,0 -1.5,16.5 -1.5,16.5 -7.935,1.365 -7.305,4.725 -7.5,12 0,0 -4.5,-1.5 -4.5,-1.5 -1.74,6.15 -1.17,22.59 1.275,28.44 1.725,4.125 13.11,18.165 16.725,21.06 3.765,-8.67 4.5,-11.265 13.499996,-15 0,0 -1.499996,-6 -1.499996,-6 0,0 5.999996,0 5.999996,0 0.525,-6.405 0.555,-8.625 7.499998,-9 0,0 1.5,-1.5 1.5,-1.5 -3.33,-9.21 -3.195,-12.63 7.5,-13.5 0,0 -1.5,-7.5 -1.5,-7.5 0,0 -7.5,1.5 -7.5,1.5 0,0 2.88,-15 2.88,-15 0,0 0,-10.5 0,-10.5 0,0 7.62,-10.5 7.62,-10.5 z m 166.5,60 c -2.775,-3.66 -2.94,-3.09 -7.5,-3 0.51,6.21 0.435,7.365 6,10.5 -1.215,-4.29 -2.025,-4.59 1.5,-7.5 z m 57,15 c 0,0 -1.5,0 -1.5,0 0,0 1.5,1.5 1.5,1.5 0,0 0,-1.5 0,-1.5 z" - style="fill:#000000;stroke:#f4e3d7" /> + style="fill:#000000;stroke:none" /> diff --git a/icons/creatures/mule.svg b/icons/creatures/mule.svg new file mode 100644 index 00000000..acf6cec2 --- /dev/null +++ b/icons/creatures/mule.svg @@ -0,0 +1,60 @@ + + + + + + image/svg+xml + + + + + + + + + diff --git a/icons/svg/gift.svg b/icons/svg/gift.svg new file mode 100644 index 00000000..d62ef934 --- /dev/null +++ b/icons/svg/gift.svg @@ -0,0 +1,118 @@ + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/icons/svg/wave.svg b/icons/svg/wave.svg new file mode 100644 index 00000000..ac6af981 --- /dev/null +++ b/icons/svg/wave.svg @@ -0,0 +1,94 @@ + + + + + + + +Created by potrace 1.15, written by Peter Selinger 2001-2017 + + + image/svg+xml + + + + + + + + + + + + + + diff --git a/module/actor-sheet.js b/module/actor-sheet.js index 6c7314f0..13d5c932 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -5,10 +5,10 @@ import { RdDUtility } from "./rdd-utility.js"; import { HtmlUtility } from "./html-utility.js"; -import { RdDItem } from "./item.js"; import { RdDItemArme } from "./item-arme.js"; import { RdDItemCompetence } from "./item-competence.js"; import { RdDBonus } from "./rdd-bonus.js"; +import { Misc } from "./misc.js"; /* -------------------------------------------- */ export class RdDActorSheet extends ActorSheet { @@ -38,11 +38,11 @@ export class RdDActorSheet extends ActorSheet { data.data.showCompNiveauBase = this.options.showCompNiveauBase; data.data.montrerArchetype = this.options.montrerArchetype; - data.itemsByType = RdDItem.buildItemsClassification(data.items); + data.itemsByType = Misc.classify(data.items); // Competence per category data.data.competenceXPTotal = 0; - data.competenceByCategory = RdDItem.classify( + data.competenceByCategory = Misc.classify( data.itemsByType.competence, item => item.data.categorie, item => { @@ -123,6 +123,7 @@ export class RdDActorSheet extends ActorSheet { RdDUtility.filterItemsPerTypeForSheet(data); data.data.sortReserve = data.data.reve.reserve.list; + data.data.rencontres = duplicate(data.data.reve.rencontre.list); data.data.caseSpeciales = data.itemsByType['casetmr']; RdDUtility.buildArbreDeConteneur(this, data); data.data.surEncombrementMessage = (data.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : ""; @@ -188,18 +189,23 @@ export class RdDActorSheet extends ActorSheet { // Everything below here is only needed if the sheet is editable if (!this.options.editable) return; - // Update Inventory Item html.find('.item-edit').click(ev => { const li = $(ev.currentTarget).parents(".item"); const item = this.actor.getOwnedItem(li.data("item-id")); item.sheet.render(true); }); + // Update Inventory Item + html.find('.rencontre-delete').click(ev => { + const li = $(ev.currentTarget).parents(".item"); + const rencontreKey = li.data("item-id"); + this.actor.deleteTMRRencontre(rencontreKey); + }); // Delete Inventory Item html.find('.item-delete').click(ev => { const li = $(ev.currentTarget).parents(".item"); RdDUtility.confirmerSuppression(this, li); - }); + }); html.find('.subacteur-delete').click(ev => { const li = $(ev.currentTarget).parents(".item"); RdDUtility.confirmerSuppressionSubacteur(this, li); @@ -303,6 +309,11 @@ export class RdDActorSheet extends ActorSheet { let musiqueId = li.data('item-id'); this.actor.rollMusique(musiqueId); }); + html.find('.oeuvre-label a').click((event) => { + const li = $(event.currentTarget).parents(".item"); + let oeuvreId = li.data('item-id'); + this.actor.rollOeuvre(oeuvreId); + }); html.find('.jeu-label a').click((event) => { const li = $(event.currentTarget).parents(".item"); let jeuId = li.data('item-id'); diff --git a/module/actor-vehicule-sheet.js b/module/actor-vehicule-sheet.js index b9136a2b..a2dd0cb3 100644 --- a/module/actor-vehicule-sheet.js +++ b/module/actor-vehicule-sheet.js @@ -5,7 +5,7 @@ import { RdDUtility } from "./rdd-utility.js"; import { HtmlUtility } from "./html-utility.js"; -import { RdDItem } from "./item.js"; +import { Misc } from "./misc.js"; /* -------------------------------------------- */ export class RdDActorVehiculeSheet extends ActorSheet { @@ -36,7 +36,7 @@ export class RdDActorVehiculeSheet extends ActorSheet { getData() { let data = super.getData(); - data.itemsByType = RdDItem.buildItemsClassification(data.items); + data.itemsByType = Misc.classify(data.items); RdDUtility.filterItemsPerTypeForSheet(data); RdDUtility.buildArbreDeConteneur(this, data); diff --git a/module/actor.js b/module/actor.js index 56df451a..ed4258c5 100644 --- a/module/actor.js +++ b/module/actor.js @@ -21,6 +21,10 @@ import { RdDAlchimie } from "./rdd-alchimie.js"; import { StatusEffects } from "./status-effects.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { ReglesOptionelles } from "./regles-optionelles.js"; +import { TMRRencontres } from "./tmr-rencontres.js"; +import { Poetique } from "./poetique.js"; +import { EffetsDraconiques } from "./tmr/effets-draconiques.js"; +import { Draconique } from "./tmr/draconique.js"; /* -------------------------------------------- */ @@ -33,6 +37,8 @@ export class RdDActor extends Actor { static init() { Hooks.on("deleteActiveEffect", (actor, effect, options) => actor.onDeleteActiveEffect(effect, options)); Hooks.on("createActiveEffect", (actor, effect, options) => actor.onCreateActiveEffect(effect, options)); + Hooks.on("createOwnedItem", (actor, item, options, id) => actor.onCreateOwnedItem(item, options, id)); + Hooks.on("deleteOwnedItem", (actor, item, options, id) => actor.onDeleteOwnedItem(item, options, id)); Hooks.on("updateActor", (actor, update, options, actorId) => actor.onUpdateActor(update, options, actorId)); } @@ -71,7 +77,7 @@ export class RdDActor extends Actor { } else if (data.type == "entite") { compendiumName = "foundryvtt-reve-de-dragon.competences-entites"; } - if ( compendiumName ) { + if (compendiumName) { data.items = await RdDUtility.loadCompendium(compendiumName); } // Ajout monnaie @@ -113,7 +119,7 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - _prepareVehiculeData( actorData ) { + _prepareVehiculeData(actorData) { this.computeEncombrementTotalEtMalusArmure(); } @@ -214,7 +220,7 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ getAgilite() { - switch(this.data.type) { + switch (this.data.type) { case 'personnage': return Misc.toInt(this.data.data.carac.agilite?.value); case 'creature': return Misc.toInt(this.data.data.carac.force?.value); case 'entite': return Misc.toInt(this.data.data.carac.reve?.value); @@ -277,6 +283,9 @@ export class RdDActor extends Actor { getMusique(id) { return this.data.items.find(item => item.type == 'musique' && item._id == id); } + getOeuvre(id, type = 'oeuvre') { + return this.data.items.find(item => item.type == type && item._id == id); + } getJeu(id) { return this.data.items.find(item => item.type == 'jeu' && item._id == id); } @@ -291,7 +300,6 @@ export class RdDActor extends Actor { } return duplicate(list[0]); } - /* -------------------------------------------- */ async deleteSortReserve(sortReserve) { let reserve = duplicate(this.data.data.reve.reserve); @@ -312,11 +320,11 @@ export class RdDActor extends Actor { getSurprise(isCombat = undefined) { let niveauSurprise = Array.from(this.effects?.values() ?? []) .map(effect => StatusEffects.valeurSurprise(effect.data, isCombat)) - .reduce((a,b)=> a+b, 0); - if (niveauSurprise>1) { + .reduce((a, b) => a + b, 0); + if (niveauSurprise > 1) { return 'totale'; } - if (niveauSurprise==1 || this.getSonne()) { + if (niveauSurprise == 1 || this.getSonne()) { return 'demi'; } return ''; @@ -466,22 +474,19 @@ export class RdDActor extends Actor { async dormir(heures = 1) { let message = { whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), - content: this.name +": Vous dormez " + heures + " heure" + (heures > 1 ? "s" : "") + content: this.name + ": Vous dormez " + heures + (heures > 1 ? " heures. " : "heure. ") }; await this.recupereEndurance(message); for (let i = 0; i < heures; i++) { await this._recupererEthylisme(message); await this.recupererFatigue(message); await this.recuperationReve(message); - if (this.isDonDoubleReve()) { + if (EffetsDraconiques.isDonDoubleReve(this)) { await this.recuperationReve(message); } } ChatMessage.create(message); } - isDonDoubleReve() { - return this.data.items.find(item => item.type == 'tete' && item.name == 'Don de double-rêve'); - } /* -------------------------------------------- */ async _recupererEthylisme(message) { @@ -491,7 +496,7 @@ export class RdDActor extends Actor { if (ethylisme.value < 1) { ethylisme.value = Math.min(ethylisme.value + 1, 1); if (ethylisme.value <= 0) { - message.content += `
Vous dégrisez un peu (${RdDUtility.getNomEthylisme(ethylisme.value)})`; + message.content += `Vous dégrisez un peu (${RdDUtility.getNomEthylisme(ethylisme.value)}). `; } } await this.update({ "data.compteurs.ethylisme": ethylisme }); @@ -502,7 +507,7 @@ export class RdDActor extends Actor { const manquant = this._computeEnduranceMax() - this.data.data.sante.endurance.value; if (manquant > 0) { await this.santeIncDec("endurance", manquant); - message.content += "
Vous récuperez " + manquant + " points d'endurance"; + message.content += "Vous récuperez " + manquant + " points d'endurance. "; } } @@ -511,14 +516,14 @@ export class RdDActor extends Actor { let fatigue = duplicate(this.data.data.sante.fatigue) const fatigueMin = this._computeFatigueMin(); if (fatigue.value <= fatigueMin) { - message.content += "
Vous êtes déjà reposé"; + message.content += "Vous êtes déjà reposé. "; return; } fatigue.value = Math.max(fatigueMin, this._calculRecuperationSegment(fatigue.value)); console.log("recupererFatigue", fatigue) await this.update({ "data.sante.fatigue": fatigue }); if (fatigue.value == 0) { - message.content += "
Vous êtes bien reposé"; + message.content += "Vous êtes complêtement reposé. "; } } @@ -547,18 +552,18 @@ export class RdDActor extends Actor { const seuil = this.data.data.reve.seuil.value; const reveActuel = this.getReveActuel(); if (reveActuel >= seuil) { - message.content += `
Vous avez suffisament rêvé (seuil ${seuil}, rêve actuel ${reveActuel})`; + message.content += `Vous avez suffisament rêvé, au delà de votre seuil. `; } else { let deRecuperation = (await DeDraconique.ddr("selfroll")).total; console.log("recuperationReve", deRecuperation); if (deRecuperation >= 7) { // Rêve de Dragon ! - message.content += `
Vous faites un Rêve de Dragon de ${deRecuperation} Points de rêve`; - /*message.content += */await this.combattreReveDeDragon(deRecuperation); + message.content += `Vous faites un Rêve de Dragon de ${deRecuperation} Points de rêve! `; + await this.combattreReveDeDragon(deRecuperation); } else { - message.content += `
Vous récupérez ${deRecuperation} Points de rêve`; + message.content += `Vous récupérez ${deRecuperation} Points de rêve. `; await this.reveActuelIncDec(deRecuperation); } } @@ -576,15 +581,57 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async combattreReveDeDragon(force) { - let draconic = this.getBestDraconic(); - let niveau = Math.max(0, draconic.data.niveau); - let etat = this.getEtatGeneral(); - let difficulte = niveau - etat - force; - let reveActuel = this.getReveActuel(); - let rolled = await RdDResolutionTable.roll(reveActuel, difficulte); - // TODO: xp particulière - console.log("combattreReveDeDragon", rolled); - return await this.appliquerReveDeDragon(rolled, force); + let rollData = { + actor: this, + competence: duplicate(this.getBestDraconic()), + canClose: false, + rencontre: duplicate(TMRRencontres.getRencontre('rdd')), + tmr: true, + use: { libre: false, conditions: false }, + forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.getReveActuel() } } + } + rollData.rencontre.force = force; + rollData.competence.data.defaut_carac = 'reve-actuel'; + + const dialog = await RdDRoll.create(this, rollData, + { + html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-reve-de-dragon.html', + options: { height: 400 } + }, + { + name: 'maitrise', + label: 'Maîtriser le Rêve de Dragon', + callbacks: [ + this.createCallbackExperience(), + { action: r => this.resultCombatReveDeDragon(r) } + ] + } + ); + dialog.render(true); + } + + async resultCombatReveDeDragon(rollData) { + rollData.queues = []; + if (rollData.rolled.isEchec) { + rollData.queues.push(await this.ajouterQueue()); + } + if (rollData.rolled.isETotal) { + rollData.queues.push(await this.ajouterQueue()); + } + if (rollData.rolled.isSuccess) { + await this.updatePointDeSeuil(); + await this.reveActuelIncDec(rollData.rencontre.force); + } + if (rollData.rolled.isPart) { + // TODO: un dialogue pour demander le type de tête? + rollData.tete = true; + } + rollData.poesie = Poetique.getExtrait(); + + ChatMessage.create({ + whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), + content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.html`, rollData) + }); } /* -------------------------------------------- */ @@ -615,16 +662,16 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async sortMisEnReserve(rollData, sort) { let reserve = duplicate(this.data.data.reve.reserve); - reserve.list.push({ coord: rollData.coord, sort: sort, draconic: duplicate(rollData.competence) }); + reserve.list.push({ coord: rollData.tmr.coord, sort: sort, draconic: duplicate(rollData.competence) }); await this.update({ "data.reve.reserve": reserve }); - this.currentTMR.updateSortReserve(); + this.currentTMR.updateTokens(); } /* -------------------------------------------- */ async updateCarac(caracName, caracValue) { let caracpath = "data.carac." + caracName + ".value" if (caracName == "force") { - if ( Number(caracValue) > this.getTaille() + 4) { + if (Number(caracValue) > this.getTaille() + 4) { ui.notifications.warn("Votre FORCE doit être au maximum de TAILLE+4"); return; } @@ -702,19 +749,20 @@ export class RdDActor extends Actor { } else { console.log("Competence not found", compName); } + RdDUtility.checkThanatosXP(compName); } - /* -------------------------------------------- */ - async updateCompetenceXPSort(compName, compValue) { - let comp = this.getCompetence(compName); - if (comp) { - const update = { _id: comp._id, 'data.xp_sort': compValue }; - const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity - } else { - console.log("Competence not found", compName); - } + /* -------------------------------------------- */ + async updateCompetenceXPSort(compName, compValue) { + let comp = this.getCompetence(compName); + if (comp) { + const update = { _id: comp._id, 'data.xp_sort': compValue }; + const updated = await this.updateEmbeddedEntity("OwnedItem", update); // Updates one EmbeddedEntity + } else { + console.log("Competence not found", compName); } - + } + /* -------------------------------------------- */ async updateCompetenceArchetype(compName, compValue) { let comp = this.getCompetence(compName); @@ -761,14 +809,14 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - getRecursiveEnc( objet ) { + getRecursiveEnc(objet) { let sumEnc = 0; - if ( objet.type == 'conteneur') { + if (objet.type == 'conteneur') { for (let id of objet.data.data.contenu) { let subobjet = this.items.find(objet => (id == objet._id)); - if ( subobjet ) { - if ( subobjet && subobjet.type == 'conteneur') { - sumEnc += this.getRecursiveEnc( subobjet ); + if (subobjet) { + if (subobjet && subobjet.type == 'conteneur') { + sumEnc += this.getRecursiveEnc(subobjet); } else { sumEnc += Number(subobjet.data.data.encombrement) * Number(subobjet.data.data.quantite); } @@ -791,11 +839,11 @@ export class RdDActor extends Actor { //console.log("Conteneur trouvé : ", conteneur); if (conteneur && conteneur.type == "conteneur") { // Calculer le total actuel des contenus - let encContenu = this.getRecursiveEnc( conteneur ) - Number(conteneur.data.data.encombrement); + let encContenu = this.getRecursiveEnc(conteneur) - Number(conteneur.data.data.encombrement); let nouvelObjet = this.items.find(objet => (itemId == objet._id)); // On chope l'objet - let newEnc = (nouvelObjet) ? this.getRecursiveEnc( nouvelObjet ) : 0; // Calculer le total actuel du nouvel objet + let newEnc = (nouvelObjet) ? this.getRecursiveEnc(nouvelObjet) : 0; // Calculer le total actuel du nouvel objet //console.log( currentEnc, newEnc, conteneur.data.data.capacite, conteneur.name); - if (nouvelObjet && ( (encContenu + newEnc) > Number(conteneur.data.data.capacite)) ) { + if (nouvelObjet && ((encContenu + newEnc) > Number(conteneur.data.data.capacite))) { ui.notifications.warn("Capacité d'encombrement insuffisante dans le conteneur !"); return false; } @@ -812,8 +860,8 @@ export class RdDActor extends Actor { if (subObj && subObj.type == 'conteneur') { this.buildSubConteneurObjetList(subId, deleteList); } - if ( subObj) // Robust... - deleteList.push( {id: subId, conteneurId: conteneurId } ); + if (subObj) // Robust... + deleteList.push({ id: subId, conteneurId: conteneurId }); } } } @@ -821,7 +869,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async deleteAllConteneur(itemId) { let list = []; - list.push( {id: itemId, conteneurId: undefined }); // Init list + list.push({ id: itemId, conteneurId: undefined }); // Init list this.buildSubConteneurObjetList(itemId, list); //console.log("List to delete", list); for (let item of list) { @@ -878,42 +926,42 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async moveItemsBetweenActors(itemId, sourceActorId) { let itemsList = [] - let sourceActor = game.actors.get( sourceActorId ); - itemsList.push( {id: itemId, conteneurId: undefined }); // Init list - sourceActor.buildSubConteneurObjetList( itemId, itemsList ); // Get itemId list + let sourceActor = game.actors.get(sourceActorId); + itemsList.push({ id: itemId, conteneurId: undefined }); // Init list + sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list let itemMap = {}; for (let item of itemsList) { - let srcItem = sourceActor.data.items.find( subItem => subItem._id == item.id ); - let newItem = await this.createOwnedItem( duplicate(srcItem) ); + let srcItem = sourceActor.data.items.find(subItem => subItem._id == item.id); + let newItem = await this.createOwnedItem(duplicate(srcItem)); console.log('New object', newItem, srcItem); itemMap[srcItem._id] = newItem._id; // Pour garder le lien ancien / nouveau } for (let item of itemsList) { // Second boucle pour traiter la remise en conteneurs // gestion conteneur/contenu - if ( item.conteneurId) { // l'Objet était dans un conteneur + if (item.conteneurId) { // l'Objet était dans un conteneur let newConteneurId = itemMap[item.conteneurId]; // Get conteneur - let newConteneur = this.data.items.find( subItem => subItem._id == newConteneurId ); - + let newConteneur = this.data.items.find(subItem => subItem._id == newConteneurId); + let newItemId = itemMap[item.id]; // Get newItem - console.log('New conteneur filling!', newConteneur, newItemId, item ); + console.log('New conteneur filling!', newConteneur, newItemId, item); let contenu = duplicate(newConteneur.data.contenu); - contenu.push( newItemId ); - await this.updateOwnedItem( {_id: newConteneurId, 'data.contenu': contenu }); + contenu.push(newItemId); + await this.updateOwnedItem({ _id: newConteneurId, 'data.contenu': contenu }); } } - for( let item of itemsList) { - await sourceActor.deleteOwnedItem( item.id ); + for (let item of itemsList) { + await sourceActor.deleteOwnedItem(item.id); } } /* -------------------------------------------- */ detectSurEncombrement() { let maxEnc = 0; - if ( this.data.type == 'vehicule') + if (this.data.type == 'vehicule') maxEnc = this.data.data.capacite_encombrement; - else + else maxEnc = this.data.data.attributs.encombrement.value; let diffEnc = Number(this.encTotal) - Number(maxEnc); return Math.max(0, Math.ceil(diffEnc)); @@ -950,7 +998,7 @@ export class RdDActor extends Actor { await this.update({ "data.attributs.malusarmure": malusArmureData }); } } - + /* -------------------------------------------- */ async computePrixTotalEquipement() { let prixTotalEquipement = 0; @@ -962,7 +1010,7 @@ export class RdDActor extends Actor { if (item.data.quantite == undefined) item.data.quantite = 1; // Auto-fix if (item.data.cout < 0) item.data.cout = 0; // Auto-fix prixTotalEquipement += Number(item.data.cout) * Number(item.data.quantite); - } + } } // Mise à jour valeur totale de l'équipement this.prixTotalEquipement = prixTotalEquipement; @@ -1018,7 +1066,7 @@ export class RdDActor extends Actor { data.compteurs.surenc.value = - this.detectSurEncombrement(); } } - + /* -------------------------------------------- */ async ajouterRefoulement(value = 1) { let ret = "none"; @@ -1047,17 +1095,18 @@ export class RdDActor extends Actor { content: this.name + " subit un Souffle de Dragon : " + souffle.name }); } + // TODO: fermeture cité return souffle; } /* -------------------------------------------- */ async ajouterQueue(options = { chat: false }) { - // TODO: Déterminer si Thanatos a été utilisé? => laisser le joueur ne pas choisir Thanatos => choisir sa voie? - let utiliseThanatos = false; let queue; - if (utiliseThanatos) { + if (this.data.data.reve.reve.thanatosused) { queue = await RdDRollTables.getOmbre(); - // mettre à jour: plus d'ombre en vue + let myReve = duplicate(this.data.data.reve.reve); + myReve.thanatosused = false; + await this.update({ "data.reve.reve": myReve } ); } else { queue = await RdDRollTables.getQueue(); @@ -1069,46 +1118,46 @@ export class RdDActor extends Actor { content: this.name + " subit une Queue de Dragon : " + queue.name }); } - return queue.name; + return queue; } /* -------------------------------------------- */ displayTMRQueueSouffleInformation() { + let messages = []; for (let item of this.data.items) { - let content - if (item.type == 'queue') { - if (item.name.toLowerCase() == 'conquête') { - content = "RAPPEL ! Vous souffrez d'une Conquête : " + item.data.description; - } - else if (item.name.toLowerCase() == 'pélerinage') { - content = "RAPPEL ! Vous souffrez d'un Pélerinage : " + item.data.description; - } - else if (item.name.toLowerCase() == 'urgence draconique') { - content = "RAPPEL ! Vous souffrez d'une Urgence Draconique : " + item.data.description; - } - } else if (item.type == 'souffle') { - if (item.name.toLowerCase() == 'périple') { - content = "RAPPEL ! Vous souffrez du Souffle Périple. Vous devez gérer manuellement le détail du Périple.
" + item.data.description; - } else if (item.name.toLowerCase() == 'fermeture des cités') { - content = "RAPPEL ! Vous souffrez du Souffle Fermeture des Cités. Vous devez gérer manuellement le détail des Citées ré-ouvertes.
" + item.data.description; - } else if (item.name.toLowerCase() == 'désorientation') { - content = "RAPPEL ! Vous souffrez du Souffle Désorientation. Vous devez gérer avec votre MJ les effets de ce souffle.
" + item.data.description; - } else if (item.name.toLowerCase() == 'double résistance du fleuve') { - content = "RAPPEL ! Vous souffrez du Souffle Double Résistance du Fleuve. Vous devez gérer avec votre MJ les effets de ce souffle.
" + item.data.description; - } + if (EffetsDraconiques.isConquete(item)) { + messages.push("Vous souffrez d'une Conquête : " + item.data.description); } - if (content) { - ChatMessage.create({ - whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), - content: content - }); + if (EffetsDraconiques.isPelerinage(item)) { + messages.push("Vous souffrez d'un Pélerinage : " + item.data.description); } + if (EffetsDraconiques.isUrgenceDraconique(item)) { + messages.push("Vous souffrez d'une Urgence Draconique : " + item.data.description); + } + if (EffetsDraconiques.isPeriple(item)) { + messages.push("Vous souffrez du Souffle Périple. Vous devez gérer manuellement le détail du Périple.
" + item.data.description); + } + if (EffetsDraconiques.isDesorientation(item)) { + messages.push("Vous souffrez du Souffle Désorientation. Vous devez gérer avec votre MJ les effets de ce souffle.
" + item.data.description); + } + } + + if (messages.length > 0) { + ChatMessage.create({ + whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), + content: "RAPPEL !
" + messages.join('
') + }); } } + /* -------------------------------------------- */ + getTMRRencontres() { + return this.data.data.reve.rencontre; + } + /* -------------------------------------------- */ async deleteTMRRencontreAtPosition() { - let rencontres = duplicate(this.data.data.reve.rencontre); + let rencontres = duplicate(this.getTMRRencontres()); let len = rencontres.list.length; let i = 0; //console.log("List", rencontres, len); @@ -1126,7 +1175,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async addTMRRencontre(currentRencontre) { - let rencontres = duplicate(this.data.data.reve.rencontre); + let rencontres = duplicate(this.getTMRRencontres()); let len = rencontres.list.length; let i = 0; let already = false; @@ -1135,11 +1184,22 @@ export class RdDActor extends Actor { already = true; } if (!already) { - rencontres.list.push({ coord: this.data.data.reve.tmrpos.coord, rencontre: currentRencontre }); + rencontres.list.push(currentRencontre); await this.update({ "data.reve.rencontre": rencontres }); } } + /* -------------------------------------------- */ + async deleteTMRRencontre(rencontreKey) { + let list = duplicate(this.data.data.reve.rencontre.list); + let newList = []; + for (let i = 0; i < list.length; i++) { + if ( i != rencontreKey) + newList.push( list[i]); + } + await this.update({ "data.reve.rencontre.list": newList }); + } + /* -------------------------------------------- */ async updateCoordTMR(coord) { let tmrPos = duplicate(this.data.data.reve.tmrpos); @@ -1176,7 +1236,7 @@ export class RdDActor extends Actor { chance.value = value; await this.update({ "data.compteurs.chance": chance }); } - + /* -------------------------------------------- */ getSonne() { return !this.isEntiteCauchemar() && (this.data.data.sante.sonne?.value ?? false); @@ -1187,7 +1247,7 @@ export class RdDActor extends Actor { } await this.setStatusSonne(sonne); await this.setStateSonne(sonne); - } + } async setStateSonne(sonne) { if (this.isEntiteCauchemar()) { return; @@ -1241,7 +1301,7 @@ export class RdDActor extends Actor { await RdDDice.show(myRoll); let msgText = "Jet d'Endurance : " + myRoll.total + " / " + this.data.data.sante.endurance.value + "
"; - if (myRoll.total == 1 || (myRoll.total != 20 && myRoll.total <= this.data.data.sante.endurance.value) ) { + if (myRoll.total == 1 || (myRoll.total != 20 && myRoll.total <= this.data.data.sante.endurance.value)) { msgText += `${this.name} a réussi son Jet d'Endurance !`; if (myRoll.total == 1) { msgText += `et gagne 1 Point d'Experience en Constitution`; @@ -1292,20 +1352,20 @@ export class RdDActor extends Actor { const sante = duplicate(this.data.data.sante); let compteur = sante[name]; if (!compteur) { - return ; + return; } let result = { sonne: false, }; - let minValue = name == "vie" ? -this.getSConst()-1 : 0; + let minValue = name == "vie" ? -this.getSConst() - 1 : 0; result.newValue = Math.max(minValue, Math.min(compteur.value + inc, compteur.max)); //console.log("New value ", inc, minValue, result.newValue); let fatigue = 0; if (name == "endurance" && !this.isEntiteCauchemar()) { if (result.newValue == 0 && inc < 0 && !isCritique) { // perte endurance et endurance devient 0 (sauf critique) -> -1 vie - sante.vie.value --; + sante.vie.value--; } result.newValue = Math.max(0, result.newValue); if (inc > 0) { // le max d'endurance s'applique seulement à la récupération @@ -1339,7 +1399,7 @@ export class RdDActor extends Actor { } isDead() { - return !this.isEntiteCauchemar() && this.data.data.sante.vie.value<-this.getSConst() + return !this.isEntiteCauchemar() && this.data.data.sante.vie.value < -this.getSConst() } /* -------------------------------------------- */ @@ -1523,11 +1583,11 @@ export class RdDActor extends Actor { if (stress <= 0) { return; } - + const stressRoll = await this._stressRoll(this.getReveActuel()); - + const conversion = Math.floor(stress * stressRoll.factor / 100); - let dissolution = Math.max(0, Misc.toInt(this.data.data.compteurs.dissolution.value)); + let dissolution = Math.max(0, Misc.toInt(this.data.data.compteurs.dissolution.value)); let exaltation = Math.max(0, Misc.toInt(this.data.data.compteurs.exaltation.value)); const annule = Math.min(dissolution, exaltation); dissolution -= annule; @@ -1541,7 +1601,7 @@ export class RdDActor extends Actor { stress: stress, perte: Math.min(conversion, stress), convertis: conversion - perteDissolution, - xp: conversion - perteDissolution + exaltation, + xp: conversion - perteDissolution + exaltation, dissolution: dissolution, exaltation: exaltation }; @@ -1550,13 +1610,13 @@ export class RdDActor extends Actor { whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-transformer-stress.html`, stressRollData) }); - + let compteurs = duplicate(this.data.data.compteurs); compteurs.stress.value = Math.max(stress - stressRollData.perte - 1, 0); compteurs.experience.value += stressRollData.xp; compteurs.dissolution.value = dissolution - perteDissolution; compteurs.exaltation.value = 0; - await this.update({ "data.compteurs": compteurs }); + await this.update({ "data.compteurs": compteurs }); } /* -------------------------------------------- */ @@ -1568,7 +1628,7 @@ export class RdDActor extends Actor { result.factor = this._getFacteurStress(result); return result; } - + _getFacteurStress(stressRoll) { switch (stressRoll.code) { case "sign": return 75; @@ -1577,11 +1637,11 @@ export class RdDActor extends Actor { case "epart": return 10; case "etotal": return 0; case "part": - if (stressRoll.second.isSign) { - stressRoll.quality = "Double Particulière"; - return 150; - } - return 100; + if (stressRoll.second.isSign) { + stressRoll.quality = "Double Particulière"; + return 150; + } + return 100; } return 0; } @@ -1606,7 +1666,7 @@ export class RdDActor extends Actor { async checkCaracXP(caracName) { let carac = this.data.data.carac[caracName]; if (carac && carac.xp > 0) { - let xpNeeded = RdDUtility.getCaracNextXp(carac.value+1); + let xpNeeded = RdDUtility.getCaracNextXp(carac.value + 1); if (carac.xp >= xpNeeded) { carac = duplicate(carac); carac.value = Number(carac.value) + 1; @@ -1627,12 +1687,12 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async checkCompetenceXP(compName, newXP = undefined) { let competence = RdDItemCompetence.findCompetence(this.data.items, compName); - if ( competence && newXP && newXP == competence.data.xp ) { // Si édition, mais sans changement XP + if (competence && newXP && newXP == competence.data.xp) { // Si édition, mais sans changement XP return; } newXP = (newXP) ? newXP : competence.data.xp; if (competence && newXP > 0) { - let xpNeeded = RdDItemCompetence.getCompetenceNextXp(competence.data.niveau+1); + let xpNeeded = RdDItemCompetence.getCompetenceNextXp(competence.data.niveau + 1); if (newXP >= xpNeeded) { let newCompetence = duplicate(competence); newCompetence.data.niveau += 1; @@ -1659,10 +1719,10 @@ export class RdDActor extends Actor { let xpResult = this.appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence); if (display && xpResult.result) { let xpmsg = "
Points d'expérience gagnés ! Carac: " + xpResult.xpCarac + ", Comp: " + xpResult.xpCompetence; - let message = { - whisher: ChatMessage.getWhisperRecipients( ["GM", this.name ] ), - content: "" + rollData.selectedCarac.label + "" + xpmsg, - } + let message = { + whisher: ChatMessage.getWhisperRecipients(["GM", this.name]), + content: "" + rollData.selectedCarac.label + "" + xpmsg, + } ChatMessage.create(message); } if (xpResult && xpResult.xpComp > 0 && rollData.competence) { @@ -1683,18 +1743,18 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ filterSortList(sortList, coord) { - let tmr = TMRUtility.getTMR( coord); + let tmr = TMRUtility.getTMR(coord); let letfilteredList = [] - for ( let sort of sortList) { + for (let sort of sortList) { //console.log(sort.name, sort.data.caseTMR.toLowerCase(), sort.data.caseTMRspeciale.toLowerCase(), coord.toLowerCase() ); - if (sort.data.caseTMR.toLowerCase().includes('variable') ) { - letfilteredList.push( sort); - } else if (sort.data.caseTMRspeciale.toLowerCase().includes('variable') ) { - letfilteredList.push( sort); - } else if (sort.data.caseTMR.toLowerCase() == tmr.type ) { - letfilteredList.push( sort); - } else if ( sort.data.caseTMR.toLowerCase().includes('special') && sort.data.caseTMRspeciale.toLowerCase().includes( coord.toLowerCase() ) ) { - letfilteredList.push( sort); + if (sort.data.caseTMR.toLowerCase().includes('variable')) { + letfilteredList.push(sort); + } else if (sort.data.caseTMRspeciale.toLowerCase().includes('variable')) { + letfilteredList.push(sort); + } else if (sort.data.caseTMR.toLowerCase() == tmr.type) { + letfilteredList.push(sort); + } else if (sort.data.caseTMR.toLowerCase().includes('special') && sort.data.caseTMRspeciale.toLowerCase().includes(coord.toLowerCase())) { + letfilteredList.push(sort); } } @@ -1702,22 +1762,24 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - filterDraconicList(sortList ) { + filterDraconicList(sortList) { let draconicDone = {}; let newDraconicList = []; let draconicList = this.getDraconicList(); let bestDraconic = this.getBestDraconic(); - for ( let sort of sortList) { + for (let sort of sortList) { let voie = sort.data.draconic.toLowerCase(); - let competenceVoie = draconicList.find(item => item.data.categorie == 'draconic' && item.name.toLowerCase().includes( voie ) ); - if ( sort.name.toLowerCase().includes('aura') ) { - competenceVoie = bestDraconic; + let draconic = draconicList.find(item => item.data.categorie == 'draconic' && item.name.toLowerCase().includes(voie)); + if (sort.name.toLowerCase().includes('aura')) { + draconic = bestDraconic; } - if (!draconicDone[competenceVoie.name]) { - newDraconicList.push( competenceVoie ); - draconicDone[competenceVoie.name] = newDraconicList.length-1; // Patch local pour relier facilement voie/compétence + draconic = duplicate(draconic); + if (draconicDone[draconic.name] == undefined) { + draconic.data.defaut_carac = 'reve'; + newDraconicList.push(draconic); + draconicDone[draconic.name] = newDraconicList.length - 1; // Patch local pour relier facilement voie/compétence } - sort.data.listIndex = draconicDone[competenceVoie.name] || 0; + sort.data.listIndex = draconicDone[draconic.name] || 0; } return newDraconicList; } @@ -1738,20 +1800,20 @@ export class RdDActor extends Actor { let draconicList = this.filterDraconicList(sortList); let rollData = { - selectedCarac: this.data.data.carac.reve, + forceCarac: { 'reve': duplicate(this.data.data.carac.reve) }, draconicList: draconicList, sortList: sortList, - competence: this.getBestDraconic(), + competence: draconicList[0], selectedSort: sortList[0], - coord: coord, - coordLabel: TMRUtility.getTMR(coord).label, + tmr: TMRUtility.getTMR(coord), diffLibre: sortList[0].data.difficulte, // Per default at startup coutreve: Array(20).fill().map((item, index) => 1 + index) } - if ( this.currentTMR ) this.currentTMR.minimize(); // Hide + if (this.currentTMR) this.currentTMR.minimize(); // Hide const dialog = await RdDRoll.create(this, rollData, - { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html', + { + html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html', close: html => { this.currentTMR.maximize() } // Re-display TMR }, { @@ -1777,10 +1839,10 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ isRencontreSpeciale() { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective' let addMsg = ""; - let rencSpecial = this.data.items.find(item => (item.type == 'queue' || item.type == 'souffle') && item.name.toLowerCase().includes('mauvaise rencontre')); + let rencSpecial = this.data.items.find(item => EffetsDraconiques.isMauvaiseRencontre(item)); if (rencSpecial) { rencSpecial = duplicate(rencSpecial); // To keep it - if (rencSpecial.type == 'queue') { + if (rencSpecial.type != 'souffle') { this.deleteOwnedItem(rencSpecial._id); // Suppression dans la liste des queues addMsg = " La queue a été supprimée de votre fiche automatiquement"; } else { @@ -1796,82 +1858,28 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ getTMRFatigue() { // Pour l'instant uniquement Inertie Draconique - let inertieDraconique = this.data.items.find(item => item.type == 'queue' && item.name.toLowerCase().includes('inertie draconique')); - if (inertieDraconique) { + let countInertieDraconique = EffetsDraconiques.countInertieDraconique(this); + if (countInertieDraconique > 0) { ChatMessage.create({ - content: "Vous êtes sous le coup d'une Inertie Draconique : vous perdez 2 cases de Fatigue par déplacement au lieu d'1.", + content: `Vous êtes sous le coup d'une Inertie Draconique : vous perdez ${countInertieDraconique + 1} cases de Fatigue par déplacement au lieu d'une.`, whisper: ChatMessage.getWhisperRecipients(game.user.name) }); - return 2; } - return 1; - } - - /* -------------------------------------------- */ - isConnaissanceFleuve() { - return this.data.items.find(item => item.type == 'tete' && item.name.toLowerCase().includes('connaissance du fleuve')); - } - - /* -------------------------------------------- */ - isReserveEnSecurite() { - let reserveSecurite = this.data.items.find(item => item.type == 'tete' && item.name.toLowerCase().includes(' en sécurité')); - return reserveSecurite; - } - - /* -------------------------------------------- */ - isDoubleResistanceFleuve() { - let resistFleuve = this.data.items.find(item => item.type == 'souffle' && item.name.toLowerCase().includes('résistance du fleuve')); - if (resistFleuve) { - ChatMessage.create({ - content: "Vous êtes sous le coup d'une Double Résistance du Fleuve : vous devez maîtriser 2 fois chaque case humide, un second jet est donc effectué.", - whisper: ChatMessage.getWhisperRecipients(game.user.name) - }); - return true; - } - return false; + return countInertieDraconique + 1; } /* -------------------------------------------- */ async checkSoufflePeage(cellDescr) { - let peage = this.data.items.find(item => item.type == 'souffle' && item.name.toLowerCase().includes('péage')); + let peage = this.data.items.find(item => EffetsDraconiques.isPeage(item)); if (peage && (cellDescr.type == 'pont' || cellDescr.type == 'cite')) { await this.reveActuelIncDec(-1); ChatMessage.create({ - content: "Vous êtes sous le coup d'un Péage : l'entrée sur cette case vous coûte 1 Point de Rêve (déduit automatiquement).", + content: "Vous êtes sous le coup d'un Péage : l'entrée sur cette case vous a coûté 1 Point de Rêve (déduit automatiquement).", whisper: ChatMessage.getWhisperRecipients(game.user.name) }); } } - /* -------------------------------------------- */ - checkTeteDeplacementAccelere() { - let deplAccelere = this.data.items.find(item => item.type == 'tete' && item.name.toLowerCase().includes(' déplacement accéléré')); - if (deplAccelere) { - return true; - } - return false; - } - - /* -------------------------------------------- */ - checkIsAdditionnalHumide(cellDescr, coordTMR) { - let pontHumide = this.data.items.find(item => item.type == 'souffle' && item.name.toLowerCase().includes(' des ponts')); - if (pontHumide && cellDescr.type == 'pont') { - ChatMessage.create({ - content: "Vous êtes sous le coup d'une Impraticabilité des Ponts : ils doivent être maîtrisés comme des cases humides.", - whisper: ChatMessage.getWhisperRecipients(game.user.name) - }); - return true; - } - // Débordement ? - let debordementList = this.data.items.filter(item => item.type == 'casetmr' && item.data.specific == 'debordement'); - for (let caseTMR of debordementList) { - if (caseTMR.data.coord == coordTMR) - return true; - } - - return false; - } - /* -------------------------------------------- */ async _rollUnSortResult(rollData, isSortReserve = false) { let rolled = rollData.rolled; @@ -1895,10 +1903,12 @@ export class RdDActor extends Actor { if (rollData.isSortReserve) { rollData.depenseReve++; } - + if ( rollData.competence.name.includes('Thanatos')) { // Si Thanatos + myReve.thanatosused = true; + } if (myReve.value > rollData.depenseReve) { // Incrémenter/gére le bonus de case - RdDItemSort.incrementBonusCase(this, selectedSort, rollData.coord); + RdDItemSort.incrementBonusCase(this, selectedSort, rollData.tmr.coord); if (rollData.isSortReserve) { await this.sortMisEnReserve(rollData, selectedSort); @@ -1963,7 +1973,7 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async rollCompetence(name) { let rollData = { competence: this.getCompetence(name) } - + if (rollData.competence.type == 'competencecreature') { if (rollData.competence.data.iscombat) { const arme = RdDItemCompetenceCreature.toArme(competence); @@ -2018,7 +2028,7 @@ export class RdDActor extends Actor { competence: competence, tache: tache, diffConditions: tache.data.difficulte, - use: { libre: false, conditions: false}, + use: { libre: false, conditions: false }, carac: {} }; rollData.carac[tache.data.carac] = duplicate(this.data.data.carac[tache.data.carac]); // Single carac @@ -2054,20 +2064,21 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - async _rollArt(artData, selectedCarac, competence, oeuvre) { + async _rollArt(artData, selected, oeuvre, callBackResult = r => this._resultArt(r)) { mergeObject(artData, { oeuvre: oeuvre, - competence: duplicate(competence), - diffLibre: -oeuvre.data.niveau, + art: oeuvre.type, + competence: duplicate(this.getCompetence(oeuvre.data.competence ?? artData.art)), + diffLibre: - (oeuvre.data.niveau ?? 0), diffConditions: 0, - use: { libre: false, conditions: true, }, - selectedCarac: duplicate(this.data.data.carac[selectedCarac]), + use: { libre: false, conditions: true }, + selectedCarac: duplicate(this.data.data.carac[selected]), forceCarac: {} }); - artData.competence.data.defaut_carac = selectedCarac; - artData.forceCarac[selectedCarac] = duplicate(this.data.data.carac[selectedCarac]); + artData.competence.data.defaut_carac = selected; + artData.forceCarac[selected] = duplicate(this.data.data.carac[selected]); - console.log("rollArtiste !!!", artData); + console.log("rollArt !!!", artData); const dialog = await RdDRoll.create(this, artData, { html: `systems/foundryvtt-reve-de-dragon/templates/dialog-roll-${artData.art}.html` }, { name: `jet-${artData.art}`, @@ -2075,7 +2086,7 @@ export class RdDActor extends Actor { height: 600, callbacks: [ this.createCallbackExperience(), - { action: r => this._resultArt(r) } + { action: r => callBackResult(r) } ] }); dialog.render(true); @@ -2090,84 +2101,65 @@ export class RdDActor extends Actor { RdDResolutionTable.displayRollData(artData, this.name, `chat-resultat-${artData.art}.html`); } + /* -------------------------------------------- */ + async rollChant(id) { + const artData = { art: 'chant', verbe: 'Chanter' }; + const oeuvre = duplicate(this.getChant(id)); + await this._rollArt(artData, "ouie", oeuvre); + } /* -------------------------------------------- */ async rollDanse(id) { - const oeuvre = duplicate(this.getDanse(id)); - const competence = this.getCompetence("danse"); - const selectedCarac = this._getCaracDanse(oeuvre, competence); const artData = { art: 'danse', verbe: 'Danser' }; - await this._rollArt(artData, selectedCarac, competence, oeuvre); + const oeuvre = duplicate(this.getOeuvre(id, artData.art)); + const selectedCarac = this._getCaracDanse(oeuvre,); + await this._rollArt(artData, selectedCarac, oeuvre); } - _getCaracDanse(oeuvre, competence) { + _getCaracDanse(oeuvre) { if (oeuvre.data.agilite) { return "agilite"; } else if (oeuvre.data.apparence) { return "apparence"; } + const competence = this.getCompetence(oeuvre.data.competence); return competence.data.defaut_carac; } /* -------------------------------------------- */ async rollMusique(id) { - const oeuvre = duplicate(this.getMusique(id)); - const competence = this.getCompetence("musique"); - const selectedCarac = "ouie"; const artData = { art: 'musique', verbe: 'Jouer' }; - await this._rollArt(artData, selectedCarac, competence, oeuvre); + const oeuvre = duplicate(this.getOeuvre(id, artData.art)); + await this._rollArt(artData, "ouie", oeuvre); } /* -------------------------------------------- */ async rollRecetteCuisine(id) { - const oeuvre = duplicate(this.getRecetteCuisine(id)); - const competence = this.getCompetence("cuisine"); - const selectedCarac = 'odoratgout'; const artData = { art: 'cuisine', verbe: 'Cuisiner' }; - await this._rollArt(artData, selectedCarac, competence, oeuvre); + const oeuvre = duplicate(this.getRecetteCuisine(id)); + await this._rollArt(artData, 'odoratgout', oeuvre, r => this._resultRecetteCuisine(r)); } - + + /* -------------------------------------------- */ + async _resultRecetteCuisine(artData) { + const baseQualite = (artData.rolled.isSuccess ? artData.oeuvre.data.niveau : artData.competence.data.niveau); + artData.qualiteFinale = Math.min(baseQualite, artData.oeuvre.data.niveau) + artData.rolled.ptQualite; + artData.exotismeFinal = Math.min(Math.min(artData.qualiteFinale, -Math.abs(artData.oeuvre.data.exotisme ?? 0)), 0); + console.log("OEUVRE", artData.art, artData) + RdDResolutionTable.displayRollData(artData, this.name, `chat-resultat-${artData.art}.html`); + } + /* -------------------------------------------- */ async rollJeu(id) { - const oeuvre = duplicate(this.getJeu(id)); - const competence = this.getCompetence("jeu"); - const selectedCarac = competence.data.defaut_carac; const artData = { art: 'jeu', verbe: 'Jeu', use: { libre: true, conditions: true, }, }; - await this._rollArt(artData, selectedCarac, competence, oeuvre); - } - - - /* -------------------------------------------- */ - async rollJeu( id ) { - let jeu = duplicate(this.getJeu(id)); - let competence = duplicate(this.getCompetence("jeu")); - let jeuData = { - competence: competence, - jeu: jeu, - diffLibre: 0, - diffConditions: 0, - use: { libre: true, conditions: true, }, - carac: {} - }; - - console.log("rollJeu !!!", jeuData); - - const dialog = await RdDRoll.create(this, jeuData, { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-jeu.html' }, { - name: 'jet-jeu', - label: 'Jeu ' + jeu.name, - height: 600, - callbacks: [ - this.createCallbackExperience(), - { action: r => this._jeuResult(r) } - ] - }); - dialog.render(true); - } - /* -------------------------------------------- */ - async _jeuResult(jeudData) { - console.log("JEU", jeudData) - RdDResolutionTable.displayRollData(jeudData, this.name, 'chat-resultat-jeu.html'); + const oeuvre = duplicate(this.getJeu(id)); + await this._rollArt(artData, oeuvre.data?.caraccomp.toLowerCase() ?? 'chance', oeuvre); } + async rollOeuvre(id) { + const artData = { art: 'oeuvre', verbe: 'Interpréter' }; + const oeuvre = duplicate(this.getOeuvre(id)); + await this._rollArt(artData, oeuvre.data.default_carac, oeuvre); + } /* -------------------------------------------- */ async rollMeditation(id) { @@ -2260,7 +2252,7 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - async chanceActuelleIncDec(value, limit=true) { + async chanceActuelleIncDec(value, limit = true) { let chance = duplicate(this.data.data.compteurs.chance); chance.value = Math.max(chance.value + value, 0); if (limit) { @@ -2417,23 +2409,22 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - checkMonteeLaborieuse() { // Return +1 si la queue Montée Laborieuse est présente, 0 sinon - let monteLaborieuse = this.data.items.find(item => (item.type == 'queue' || item.type == 'souffle') && item.name.toLowerCase().includes('montée laborieuse')); - if (monteLaborieuse) { + countMonteeLaborieuse() { // Return +1 par queue/ombre/souffle Montée Laborieuse présente + let countMonteeLaborieuse = this.data.items.filter(item => EffetsDraconiques.isMonteeLaborieuse(item)).length; + if (countMonteeLaborieuse > 0) { ChatMessage.create({ - content: "Vous êtes sous le coup d'une Montée Laborieuse : vos montées en TMR coûtent 1 Point de Rêve de plus.", + content: `Vous êtes sous le coup d'une Montée Laborieuse : vos montées en TMR coûtent ${countMonteeLaborieuse} Point de Rêve de plus.`, whisper: ChatMessage.getWhisperRecipients(game.user.name) }); - return 1; } - return 0; + return countMonteeLaborieuse; } /* -------------------------------------------- */ - refreshTMRView( tmrData ) { + refreshTMRView(tmrData) { console.log("REFRESH !!!!"); - if ( this.currentTMR ) { - this.currentTMR.forceDemiRevePositionView(tmrData.tmrPos); + if (this.currentTMR) { + this.currentTMR.forceDemiRevePositionView(); } } @@ -2441,22 +2432,18 @@ export class RdDActor extends Actor { async displayTMR(mode = "normal") { let isRapide = mode == "rapide"; if (mode != "visu") { - let minReveValue = (isRapide) ? 3 : 2; + let minReveValue = (isRapide && !EffetsDraconiques.isDeplacementAccelere(this) ? 3 : 2) + this.countMonteeLaborieuse(); if (this.getReveActuel() < minReveValue) { ChatMessage.create({ - content: "Vous n'avez plus assez de Points de Reve pour monter dans les Terres Médianes", + content: `Vous n'avez les ${minReveValue} Points de Reve nécessaires pour monter dans les Terres Médianes`, whisper: ChatMessage.getWhisperRecipients(game.user.name) }); return; } } - if (mode != 'visu') { - // Notification au MJ - ChatMessage.create({ content: this.name + " est monté dans les TMR en mode : " + mode, whisper: ChatMessage.getWhisperRecipients("GM") }); - } - let data = { + mode: mode, fatigue: { malus: RdDUtility.calculMalusFatigue(this.data.data.sante.fatigue.value, this.data.data.sante.endurance.max), html: "" + RdDUtility.makeHTMLfatigueMatrix(this.data.data.sante.fatigue.value, this.data.data.sante.endurance.max).html() + "
" @@ -2468,7 +2455,7 @@ export class RdDActor extends Actor { isRapide: isRapide } let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', data); - this.currentTMR = new RdDTMRDialog(html, this, data, mode); + this.currentTMR = await RdDTMRDialog.create(html, this, data); this.currentTMR.render(true); } @@ -2494,11 +2481,20 @@ export class RdDActor extends Actor { return undefined; } + /* -------------------------------------------- */ getArmeParade(armeParadeId) { const item = armeParadeId ? this.getOwnedItem(armeParadeId) : undefined; return RdDItemArme.getArmeData(item); } + /* -------------------------------------------- */ + verifierForceMin( item ) { + if ( item.type == 'arme' && item.data.force > this.data.data.carac.force.value ) { + ChatMessage.create( { content: `${this.name} s'est équipé(e) de l'arme ${item.name}, mais n'a pas une force suffisante pour l'utiliser normalement + (${item.data.force} nécessaire pour une Force de ${this.data.data.carac.force.value})` } ); + } + } + /* -------------------------------------------- */ async equiperObjet(itemID) { let item = this.getOwnedItem(itemID); @@ -2507,12 +2503,14 @@ export class RdDActor extends Actor { await this.updateEmbeddedEntity("OwnedItem", update); this.computeEncombrementTotalEtMalusArmure(); // Mise à jour encombrement this.computePrixTotalEquipement(); // Mis à jour du prix total de l'équipement + if ( item.data.data.equipe ) + this.verifierForceMin( item.data ); } } /* -------------------------------------------- */ computeArmure(attackerRoll) { - let dmg = (attackerRoll.dmg.dmgArme ??0) + (attackerRoll.dmg.dmgActor ?? 0); + let dmg = (attackerRoll.dmg.dmgArme ?? 0) + (attackerRoll.dmg.dmgActor ?? 0); let arme = attackerRoll.arme; let protection = 0; const armures = this.data.items.filter(it => it.type == "armure" && it.data.equipe); @@ -2575,7 +2573,7 @@ export class RdDActor extends Actor { this.ajouterBlessure(encaissement); // Will upate the result table const perteVie = this.isEntiteCauchemar() - ? { newValue: 0} + ? { newValue: 0 } : await this.santeIncDec("vie", - encaissement.vie); const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, (encaissement.critiques > 0)); @@ -2620,7 +2618,7 @@ export class RdDActor extends Actor { let encaissement = RdDUtility.selectEncaissement(jetTotal, rollData.dmg.mortalite) let over20 = Math.max(jetTotal - 20, 0); encaissement.dmg = rollData.dmg; - encaissement.dmg.loc = rollData.dmg.loc ?? RdDUtility.getLocalisation(); + encaissement.dmg.loc = rollData.dmg.loc ?? RdDUtility.getLocalisation( this.data.type ); encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;' encaissement.roll = roll; encaissement.armure = armure; @@ -2681,8 +2679,10 @@ export class RdDActor extends Actor { } else { // TODO: status effect dead this.addStatusEffectById('dead'); - ChatMessage.create({ content: `charge - ${this.name} vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !` }); + ChatMessage.create({ + content: `charge + ${this.name} vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !` + }); encaissement.critiques -= count; encaissement.mort = true; break; @@ -2706,6 +2706,29 @@ export class RdDActor extends Actor { return data; } + /* -------------------------------------------- */ + async resetItemUse( ) { + await this.setFlag('foundryvtt-reve-de-dragon', 'itemUse', null ); + await this.setFlag('foundryvtt-reve-de-dragon', 'itemUse', {} ); + } + + /* -------------------------------------------- */ + async incItemUse( itemId ) { + let itemUse = this.getFlag('foundryvtt-reve-de-dragon', 'itemUse'); + itemUse = (itemUse) ? duplicate(itemUse) : {}; + itemUse[itemId] = (itemUse[itemId]) ? itemUse[itemId] + 1 : 1; + await this.setFlag( 'foundryvtt-reve-de-dragon', 'itemUse', itemUse); + console.log("ITEM USE INC", itemUse); + } + + /* -------------------------------------------- */ + getItemUse( itemId ) { + let itemUse = this.getFlag('foundryvtt-reve-de-dragon', 'itemUse'); + itemUse = (itemUse) ? itemUse : {}; + console.log("ITEM USE GET", itemUse); + return itemUse[itemId] ? itemUse[itemId] : 0; + } + /* -------------------------------------------- */ /* -- entites -- */ /* retourne true si on peut continuer, false si on ne peut pas continuer */ @@ -2897,9 +2920,13 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ buildVehiculesList() { return this._buildActorLinksList( - this.data.data.subacteurs?.vehicules??[], - vehicle => {return { id: vehicle.id, name: vehicle.data.name, categorie: vehicle.data.data.categorie, - structure: vehicle.data.data.structure, img: vehicle.data.img } ;}); + this.data.data.subacteurs?.vehicules ?? [], + vehicle => { + return { + id: vehicle.id, name: vehicle.data.name, categorie: vehicle.data.data.categorie, + structure: vehicle.data.data.structure, img: vehicle.data.img + }; + }); } /* -------------------------------------------- */ @@ -2912,49 +2939,49 @@ export class RdDActor extends Actor { return this._buildActorLinksList(this.data.data.subacteurs?.montures ?? []); } - _buildActorLinksList(links, actorTransformation=it => { return { id: it.id, name: it.data.name, img: it.data.img }; }) { + _buildActorLinksList(links, actorTransformation = it => { return { id: it.id, name: it.data.name, img: it.data.img }; }) { return links.map(link => game.actors.get(link.id)) .filter(it => it != null) .map(actorTransformation); } /* -------------------------------------------- */ - async pushSubacteur( actor, dataArray, dataPath, dataName ) { - let alreadyPresent = dataArray.find( attached => attached.id == actor.data._id); - if ( !alreadyPresent ) { + async pushSubacteur(actor, dataArray, dataPath, dataName) { + let alreadyPresent = dataArray.find(attached => attached.id == actor.data._id); + if (!alreadyPresent) { let newArray = duplicate(dataArray); - newArray.push( { id: actor.data._id }); - await this.update( { [dataPath]: newArray }); + newArray.push({ id: actor.data._id }); + await this.update({ [dataPath]: newArray }); } else { - ui.notifications.warn(dataName+" est déja attaché à ce Personnage."); + ui.notifications.warn(dataName + " est déja attaché à ce Personnage."); } } /* -------------------------------------------- */ - addSubacteur( actorId ) { - let actor = game.actors.get( actorId ); + addSubacteur(actorId) { + let actor = game.actors.get(actorId); //console.log("Ajout acteur : ", actor, this); - if (actor && actor.owner ) { + if (actor && actor.owner) { if (actor.data.type == 'vehicule') { - this.pushSubacteur( actor, this.data.data.subacteurs.vehicules, 'data.subacteurs.vehicules', 'Ce Véhicule' ); + this.pushSubacteur(actor, this.data.data.subacteurs.vehicules, 'data.subacteurs.vehicules', 'Ce Véhicule'); } else if (actor.data.type == 'creature') { - this.pushSubacteur( actor, this.data.data.subacteurs.montures, 'data.subacteurs.montures', 'Cette Monture' ); + this.pushSubacteur(actor, this.data.data.subacteurs.montures, 'data.subacteurs.montures', 'Cette Monture'); } else if (actor.data.type == 'personnage') { - this.pushSubacteur( actor, this.data.data.subacteurs.suivants, 'data.subacteurs.suivants', 'Ce Suivant' ); + this.pushSubacteur(actor, this.data.data.subacteurs.suivants, 'data.subacteurs.suivants', 'Ce Suivant'); } } else { ui.notifications.warn("Vous n'avez pas les droits sur l'acteur que vous attachez.") } } - + /* -------------------------------------------- */ - async removeSubacteur( actorId ) { - let newVehicules = this.data.data.subacteurs.vehicules.filter(function(obj, index, arr){ return obj.id != actorId } ); - let newSuivants = this.data.data.subacteurs.suivants.filter(function(obj, index, arr){ return obj.id != actorId } ); - let newMontures = this.data.data.subacteurs.montures.filter(function(obj, index, arr){ return obj.id != actorId } ); - await this.update( { 'data.subacteurs.vehicules': newVehicules }); - await this.update( { 'data.subacteurs.suivants': newSuivants }); - await this.update( { 'data.subacteurs.montures': newMontures }); + async removeSubacteur(actorId) { + let newVehicules = this.data.data.subacteurs.vehicules.filter(function (obj, index, arr) { return obj.id != actorId }); + let newSuivants = this.data.data.subacteurs.suivants.filter(function (obj, index, arr) { return obj.id != actorId }); + let newMontures = this.data.data.subacteurs.montures.filter(function (obj, index, arr) { return obj.id != actorId }); + await this.update({ 'data.subacteurs.vehicules': newVehicules }); + await this.update({ 'data.subacteurs.suivants': newSuivants }); + await this.update({ 'data.subacteurs.montures': newMontures }); } /* -------------------------------------------- */ async onUpdateActor(update, options, actorId) { @@ -3022,16 +3049,16 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - deleteStatusEffectById(id, options = { renderSheet: true}) { + deleteStatusEffectById(id, options = { renderSheet: true }) { const effects = Array.from(this.effects?.values()) - .filter(it => it.data.flags.core?.statusId == id); + .filter(it => it.data.flags.core?.statusId == id); this._deleteStatusEffects(effects, options); } /* -------------------------------------------- */ - deleteStatusEffect(effect, options = { renderSheet: true}) { + deleteStatusEffect(effect, options = { renderSheet: true }) { const toDelete = Array.from(this.effects?.values()) - .filter(it => StatusEffects.statusId(it.data) == StatusEffects.statusId(effect)); + .filter(it => StatusEffects.statusId(it.data) == StatusEffects.statusId(effect)); this._deleteStatusEffects(toDelete, options); } @@ -3047,13 +3074,13 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - async addStatusEffectById(id, options = { renderSheet: true}) { + async addStatusEffectById(id, options = { renderSheet: true }) { const statusEffect = CONFIG.statusEffects.find(it => it.id == id); await this.addStatusEffect(statusEffect, options); } /* -------------------------------------------- */ - async addStatusEffect(statusEffect, options = { renderSheet: true}) { + async addStatusEffect(statusEffect, options = { renderSheet: true }) { this.deleteStatusEffectById(statusEffect.id, options); const effet = duplicate(statusEffect); effet["flags.core.statusId"] = effet.id; @@ -3063,9 +3090,57 @@ export class RdDActor extends Actor { /* -------------------------------------------- */ async updateEmbeddedEntity(embeddedName, data, options) { - if ( data && data['data.defaut_carac'] && data['data.xp'] ) { // C'est une compétence - this.checkCompetenceXP(data['name'], data['data.xp'] ); + if (data && data['data.defaut_carac'] && data['data.xp']) { // C'est une compétence + this.checkCompetenceXP(data['name'], data['data.xp']); } return super.updateEmbeddedEntity(embeddedName, data, options); } -} + + /* -------------------------------------------- */ + async onCreateOwnedItem(item, options, id) { + switch (item.type) { + case 'tete': + case 'queue': + case 'ombre': + case 'souffle': + await this.onCreateOwnedDraconique(item, options, id); + break; + } + } + + async onDeleteOwnedItem(item, options, id) { + switch (item.type) { + case 'tete': + case 'queue': + case 'ombre': + case 'souffle': + await this.onDeleteOwnedDraconique(item, options, id); + break; + } + } + + async onCreateOwnedDraconique(item, options, id) { + + let draconique = Draconique.all().find(it => it.match(item)); + if (draconique) { + draconique.onActorCreateOwned(this, item) + + this.notifyGestionTeteSouffleQueue(item, draconique.manualMessage()); + } + } + + async onDeleteOwnedDraconique(item, options, id) { + + let draconique = Draconique.all().find(it => it.match(item)); + if (draconique) { + draconique.onActorDeleteOwned(this, item) + } + } + + notifyGestionTeteSouffleQueue(item, manualMessage=true){ + ChatMessage.create({ + whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), + content: `${this.name} a reçu un/une ${item.type}: ${item.name}, qui ${manualMessage ? "n'est pas" : "est" } géré automatiquement. ${manualMessage ?? ''}` + }); + }} + diff --git a/module/chat-utility.js b/module/chat-utility.js index be3c737b..d38514ca 100644 --- a/module/chat-utility.js +++ b/module/chat-utility.js @@ -4,12 +4,14 @@ */ export class ChatUtility { + /* -------------------------------------------- */ static onSocketMessage(sockmsg) { switch (sockmsg.msg) { case "msg_delete_chat_message": return ChatUtility.onRemoveMessages(sockmsg.part, sockmsg.gmId); } } + /* -------------------------------------------- */ static onRemoveMessages(part, gmId) { if (game.user._id == gmId) { const toDelete = game.messages.filter(it => it.data.content.includes(part)); @@ -107,5 +109,5 @@ export class ChatUtility { ChatMessage.create(data); } } - + } diff --git a/module/grammar.js b/module/grammar.js index a5bb7472..df4162a2 100644 --- a/module/grammar.js +++ b/module/grammar.js @@ -18,6 +18,23 @@ export class Grammar { } static toLowerCaseNoAccent(words) { - return words?.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "") ?? words; + return words?.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "") ?? words; + } + static articleDetermine(genre) { + switch (genre?.toLowerCase()) { + case 'f': case 'feminin': return 'la'; + case 'p': case 'pluriel': return 'les'; + default: + case 'm': case 'masculin': return 'le'; + } + } + static articleIndétermine(genre) { + switch (genre?.toLowerCase()) { + case 'f': case 'feminin': return 'une'; + case 'p': case 'pluriel': return 'des'; + case 'n': case 'neutre': return 'du' + default: + case 'm': case 'masculin': return 'un'; + } } } \ No newline at end of file diff --git a/module/item-competence.js b/module/item-competence.js index 8bd78974..deca47f1 100644 --- a/module/item-competence.js +++ b/module/item-competence.js @@ -59,10 +59,12 @@ export class RdDItemCompetence extends Item { static computeCompetenceXPCost(competence) { let xp = RdDItemCompetence.getDeltaXp(competence.data.base, competence.data.niveau ?? competence.data.base); xp += competence.data.xp ?? 0; + if ( competence.name.includes('Thanatos') ) xp *= 2; /// Thanatos compte double ! xp += competence.data.xp_sort ?? 0; return xp; } + /* -------------------------------------------- */ static computeEconomieCompetenceTroncXP(competences) { let economie = 0; for (let troncList of competenceTroncs) { @@ -87,17 +89,20 @@ export class RdDItemCompetence extends Item { return RdDItemCompetence.getCompetenceXp(niveau + 1); } + /* -------------------------------------------- */ static getCompetenceXp(niveau) { RdDItemCompetence._valideNiveau(niveau); return niveau < -10 ? 0 : competence_xp_par_niveau[niveau + 10]; } + /* -------------------------------------------- */ static getDeltaXp(from, to) { RdDItemCompetence._valideNiveau(from); RdDItemCompetence._valideNiveau(to); return competence_xp_cumul[to] - competence_xp_cumul[from]; } + /* -------------------------------------------- */ static _valideNiveau(niveau){ if (niveau < -11 || niveau > competence_niveau_max) { console.warn("Niveau en dehors des niveaux de compétences: [-11, " + competence_niveau_max + "]", niveau) diff --git a/module/item-competencecreature.js b/module/item-competencecreature.js index 524d5829..67896acb 100644 --- a/module/item-competencecreature.js +++ b/module/item-competencecreature.js @@ -29,7 +29,7 @@ export class RdDItemCompetenceCreature extends Item { }); return arme; } - console.error("RdDItem.toArme(", item, ") : impossible de transformer l'Item en arme"); + console.error("RdDItemCompetenceCreature.toArme(", item, ") : impossible de transformer l'Item en arme"); return undefined; } diff --git a/module/item-sheet.js b/module/item-sheet.js index 5c2dc75c..f70e3483 100644 --- a/module/item-sheet.js +++ b/module/item-sheet.js @@ -49,7 +49,7 @@ export class RdDItemSheet extends ItemSheet { async getData() { let data = super.getData(); data.categorieCompetences = RdDUtility.getCategorieCompetences(); - if ( data.item.type == 'tache' || data.item.type == 'livre' || data.item.type == 'meditation') { + if ( data.item.type == 'tache' || data.item.type == 'livre' || data.item.type == 'meditation' || data.item.type == 'oeuvre') { data.caracList = duplicate(game.system.model.Actor.personnage.carac); data.competences = await RdDUtility.loadCompendiumNames( 'foundryvtt-reve-de-dragon.competences' ); } @@ -80,6 +80,12 @@ export class RdDItemSheet extends ItemSheet { // Select competence categorie html.find("#categorie").on("click", this._onClickSelectCategorie.bind(this) ); + html.find('#sheet-competence-xp').change((event) => { + if ( this.object.data.type == 'competence') { + RdDUtility.checkThanatosXP( this.object.data.name ); + } + } ); + html.find('#creer-tache-livre').click((event) => { let actorId = event.currentTarget.attributes['data-actor-id'].value; let actor = game.actors.get( actorId ); diff --git a/module/item-sort.js b/module/item-sort.js index 1ebf950b..d529f879 100644 --- a/module/item-sort.js +++ b/module/item-sort.js @@ -68,13 +68,13 @@ export class RdDItemSort extends Item { let list = []; let caseCheck = {}; for(let i=0; i 0 && caseCheck[caseTMR] == undefined ) { - caseCheck[caseTMR] = bonus; - list.push( caseTMR+":"+bonus ); + if ( bonus > 0 && caseCheck[coord] == undefined ) { + caseCheck[coord] = bonus; + list.push( coord+":"+bonus ); } } } @@ -86,21 +86,21 @@ export class RdDItemSort extends Item { } /* -------------------------------------------- */ - static incrementBonusCase( actor, sort, coordTMR ) { + static incrementBonusCase( actor, sort, coord ) { let bonusCaseList = this.buildBonusCaseList(sort.data.bonuscase, false); //console.log("ITEMSORT", sort, bonusCaseList); let found = false; let StringList = []; for( let bc of bonusCaseList) { - if (bc.case == coordTMR) { // Case existante + if (bc.case == coord) { // Case existante found = true; bc.bonus = Number(bc.bonus) + 1; } StringList.push( bc.case+':'+bc.bonus ); } if ( !found) { //Nouvelle case, bonus de 1 - StringList.push(coordTMR+':1'); + StringList.push(coord+':1'); } // Sauvegarde/update @@ -110,10 +110,10 @@ export class RdDItemSort extends Item { } /* -------------------------------------------- */ - static getCaseBonus( sort, coordTMR) { + static getCaseBonus( sort, coord) { let bonusCaseList = this.buildBonusCaseList(sort.data.bonuscase, false); for( let bc of bonusCaseList) { - if (bc.case == coordTMR) { // Case existante + if (bc.case == coord) { // Case existante return Number(bc.bonus); } } diff --git a/module/item.js b/module/item.js deleted file mode 100644 index 46ad7721..00000000 --- a/module/item.js +++ /dev/null @@ -1,28 +0,0 @@ - -/* -------------------------------------------- */ -export class RdDItem { - - /* -------------------------------------------- */ - static buildItemsClassification(items) { - return RdDItem.classify(items, it => it.type) - } - - static classify(items, classifier = it => it.type, transform = it => it) { - let itemsBy = {}; - RdDItem.classifyInto(itemsBy, items, classifier, transform); - return itemsBy; - } - - static classifyInto(itemsBy, items, classifier = it => it.type, transform = it => it) { - for (const item of items) { - const classification = classifier(item); - let list = itemsBy[classification]; - if (!list) { - list = []; - itemsBy[classification] = list; - } - list.push(transform(item)); - } - } - -} \ No newline at end of file diff --git a/module/misc.js b/module/misc.js index 6b754e23..50566a09 100644 --- a/module/misc.js +++ b/module/misc.js @@ -1,5 +1,4 @@ - /** * This class is intended as a placeholder for utility methods unrelated * to actual classes of the game system or of FoundryVTT @@ -41,4 +40,23 @@ export class Misc { default: return '1/' + diviseur; } } + + static classify(items, classifier = it => it.type, transform = it => it) { + let itemsBy = {}; + Misc.classifyInto(itemsBy, items, classifier, transform); + return itemsBy; + } + + static classifyInto(itemsBy, items, classifier = it => it.type, transform = it => it) { + for (const item of items) { + const classification = classifier(item); + let list = itemsBy[classification]; + if (!list) { + list = []; + itemsBy[classification] = list; + } + list.push(transform(item)); + } + } + } \ No newline at end of file diff --git a/module/poetique.js b/module/poetique.js new file mode 100644 index 00000000..67f0d387 --- /dev/null +++ b/module/poetique.js @@ -0,0 +1,70 @@ + +const poesieHautReve = [ + { + reference: 'Le Ratier Bretonien', + extrait: `Le courant du Fleuve +
Te domine et te Porte +
Avant que tu te moeuves +
Combat le, ou il t'emporte` + }, + { + reference: 'Incompatibilité, Charles Beaudelaire', + extrait: `Et lorsque par hasard une nuée errante +
Assombrit dans son vol le lac silencieux, +
On croirait voir la robe ou l'ombre transparente +
D'un esprit qui voyage et passe dans les cieux.` + }, + { + reference: 'Au fleuve de Loire, Joachim du Bellay', + extrait: `Ô de qui la vive course +
Prend sa bienheureuse source, +
D’une argentine fontaine, +
Qui d’une fuite lointaine, +
Te rends au sein fluctueux +
De l’Océan monstrueux` + }, + { + reference: 'Denis Gerfaud', + extrait: `Et l'on peut savoir qui est le maître d'Oniros, c'est le Fleuve de l'Oubli. + Et l'on sait qui est le créateur du Fleuve de l'Oubli, c'est Hypnos et Narcos. + Mais l'on ne sait pas qui est le maître du Fleuve de l'Oubli, + sinon peut-être lui-même, ou peut-être Thanatos` }, + { + reference: 'Denis Gerfaud', + extrait: `Narcos est la source du Fleuve de l'Oubli et Hypnos l'embouchure + Remonter le Fleuve est la Voie de la Nuit, la Voie du Souvenir. + Descendre le Fleuve est la Voie du Jour, la Voie de l'Oubli` + }, + { + reference: 'Denis Gerfaud', + extrait: `Narcos engendre le fils dont il est la mère à l'heure du Vaisseau, + car Oniros s'embarque pour redescendre le Fleuve + vers son père Hypnos sur la Voie de l'Oubli` + }, + { + reference: 'Denis Gerfaud', + extrait: `Hypnos engendre le fils dont il est la mère à l'heure du Serpent, car + tel les serpents, Oniros commence à remonter le Fleuve + sur le Voie du Souvenir vers son père Narcos` + }, + { + reference: 'Denis Gerfaud', + extrait: `Ainsi se cuccèdent les Jours et les Ages. +
Les jours des Dragons sont les Ages des Hommes.` + }, + { + reference: 'Denis Gerfaud', + extrait: `Ainsi parlent les sages: + «Les Dragons sont créateurs de leurs rêves, mais ils ne sont pas créateurs d'Oniros + Les Dragons ne sont pas les maîtres de leurs rêvezs, car ils ne sont pas maîtres d'Oniros. + Nul ne sait qui est le créateur des Dragons, ni qui est leur maître. + Mais l'on peut supposer qui est le maître du Rêve des Dragons, c'est Oniros»` + }, +] + +export class Poetique { + static getExtrait(){ + return poesieHautReve[new Roll("1d" + poesieHautReve.length).evaluate().total - 1] + } + +} \ No newline at end of file diff --git a/module/rdd-calendrier.js b/module/rdd-calendrier.js index d0f7c47b..705317b6 100644 --- a/module/rdd-calendrier.js +++ b/module/rdd-calendrier.js @@ -79,7 +79,8 @@ export class RdDCalendrier extends Application { } /* -------------------------------------------- */ - getDateFromIndex( index ) { + getDateFromIndex( index = undefined ) { + if ( !index) index = this.getCurrentDayIndex(); let month = Math.floor(index / 28); let day = (index - (month*28)) + 1; return day+" "+heuresList[month]; diff --git a/module/rdd-combat.js b/module/rdd-combat.js index 6e313123..300d8e67 100644 --- a/module/rdd-combat.js +++ b/module/rdd-combat.js @@ -9,6 +9,23 @@ import { RdDRoll } from "./rdd-roll.js"; import { RdDRollTables } from "./rdd-rolltables.js"; import { ReglesOptionelles } from "./regles-optionelles.js"; +/* -------------------------------------------- */ +export class RdDCombatManager extends Combat { + + /* -------------------------------------------- */ + cleanItemUse() { + for(let turn of this.turns) { + turn.actor.resetItemUse() + } + } + + /* -------------------------------------------- */ + async nextRound() { + console.log('New round !'); + this.cleanItemUse(); + } +} + /* -------------------------------------------- */ export class RdDCombat { @@ -39,13 +56,15 @@ export class RdDCombat { /* -------------------------------------------- */ static onUpdateCombat(combat, data) { if (combat.data.round != 0 && combat.turns && combat.data.active) { - RdDCombat.combatNouveauRound(combat); + RdDCombat.combatNouveauTour(combat); } + } /* -------------------------------------------- */ static onPreDeleteCombat(combat, options) { if (game.user.isGM) { + combat.cleanItemUse(); ChatUtility.removeChatMessageContaining(`
`) /* * TODO: support de plusieurs combats parallèles @@ -64,7 +83,7 @@ export class RdDCombat { } /* -------------------------------------------- */ - static combatNouveauRound(combat) { + static combatNouveauTour(combat) { let turn = combat.turns.find(t => t.tokenId == combat.current.tokenId); if (game.user.isGM) { // seul le GM notifie le status @@ -358,6 +377,8 @@ export class RdDCombat { let rollData = this._prepareAttaque(competence, arme); console.log("RdDCombat.attaque >>>", rollData); + this.attacker.incItemUse( arme._id ); // Usage + this.attacker.verifierForceMin( arme ); const dialog = await RdDRoll.create(this.attacker, rollData, { @@ -457,15 +478,24 @@ export class RdDCombat { if (essaisPrecedents) { mergeObject(attackerRoll.essais, essaisPrecedents, { overwrite: true }); } + + // # utilisation esquive + let esquiveUsage = 0; + let esquive = this.defender.getCompetence("esquive"); + if (esquive) { + esquiveUsage = this.defender.getItemUse( esquive._id); + } + const paramChatDefense = { passeArme: attackerRoll.passeArme, essais: attackerRoll.essais, defender: this.defender, attacker: this.attacker, attackerId: this.attackerId, + esquiveUsage: esquiveUsage, defenderTokenId: this.defenderTokenId, mainsNues: attackerRoll.dmg.mortalite != 'mortel' && this.defender.getCompetence("Corps à corps"), - armes: this._filterArmesParade(this.defender.data.items, attackerRoll.competence, attackerRoll.arme), + armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme), diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0, attaqueParticuliere: attackerRoll.particuliere, attaqueCategorie: attackerRoll.competence.data.categorie, @@ -510,8 +540,12 @@ export class RdDCombat { } /* -------------------------------------------- */ - _filterArmesParade(items, competence) { + _filterArmesParade(defender, competence) { + let items = defender.data.items; items = items.filter(item => RdDItemArme.isArmeUtilisable(item) || RdDItemCompetenceCreature.isCompetenceParade(item)); + for( let item of items) { + item.data.nbUsage = defender.getItemUse( item._id); // Ajout du # d'utilisation ce round + } switch (competence.data.categorie) { case 'tir': case 'lancer': @@ -575,6 +609,7 @@ export class RdDCombat { let arme = this.defender.getArmeParade(armeParadeId); console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme); + this.defender.incItemUse( armeParadeId ); // Usage let rollData = this._prepareParade(attackerRoll, arme); @@ -596,6 +631,7 @@ export class RdDCombat { dialog.render(true); } + /* -------------------------------------------- */ _prepareParade(attackerRoll, armeParade) { const compName = armeParade.data.competence; const armeAttaque = attackerRoll.arme; @@ -681,6 +717,7 @@ export class RdDCombat { } console.log("RdDCombat.esquive >>>", attackerRoll, esquive); let rollData = this._prepareEsquive(attackerRoll, esquive); + this.defender.incItemUse( esquive._id ); // Usage const dialog = await RdDRoll.create(this.defender, rollData, { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html' }, { diff --git a/module/rdd-commands.js b/module/rdd-commands.js index d148eca9..3e5c3280 100644 --- a/module/rdd-commands.js +++ b/module/rdd-commands.js @@ -1,16 +1,16 @@ /* -------------------------------------------- */ -import { ChatUtility } from "./chat-utility.js"; import { DeDraconique } from "./de-draconique.js"; import { RdDItemCompetence } from "./item-competence.js"; import { Misc } from "./misc.js"; import { RdDDice } from "./rdd-dice.js"; +import { RdDNameGen } from "./rdd-namegen.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js"; import { RdDRollTables } from "./rdd-rolltables.js"; import { RdDUtility } from "./rdd-utility.js"; import { TMRRencontres } from "./tmr-rencontres.js"; -import { TMRUtility } from "./tmr-utility.js"; +import { TMRType, TMRUtility } from "./tmr-utility.js"; const rddRollNumeric = /(\d+)\s*([\+\-]?\d+)?\s*(s)?/; @@ -22,21 +22,25 @@ export class RdDCommands { const rddCommands = new RdDCommands(); rddCommands.registerCommand({ path: ["/aide"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" }); rddCommands.registerCommand({ path: ["/help"], func: (content, msg, params) => rddCommands.help(msg), descr: "Affiche l'aide pour toutes les commandes" }); - rddCommands.registerCommand({ path: ["/table", "queues"], func: (content, msg, params) => RdDRollTables.getQueue(), descr: "Tire une Queue de Dragon" }); - rddCommands.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre(), descr: "Tire une Ombre de Dragon" }); - rddCommands.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR(), descr: "Tire une Tête de Dragon pour Hauts Revants" }); - rddCommands.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete(), descr: "Tire une Tête de Dragon" }); - rddCommands.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle(), descr: " Tire un Souffle de Dragon" }); - rddCommands.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot(), descr: "Tire une carte du Tarot Draconique" }); - rddCommands.registerCommand({ path: ["/table", "tmr"], func: (content, msg, params) => TMRUtility.getTMRAleatoire(), descr: "Tire une case aléatoire des Terres médianes" }); + rddCommands.registerCommand({ path: ["/table", "queues"], func: (content, msg, params) => RdDRollTables.getQueue(true), descr: "Tire une Queue de Dragon" }); + rddCommands.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre(true), descr: "Tire une Ombre de Dragon" }); + rddCommands.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR(true), descr: "Tire une Tête de Dragon pour Hauts Revants" }); + rddCommands.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete(true), descr: "Tire une Tête de Dragon" }); + rddCommands.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle(true), descr: " Tire un Souffle de Dragon" }); + rddCommands.registerCommand({ path: ["/table", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence(true), descr: "Tire une compétence au hasard" }); + rddCommands.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot(true), descr: "Tire une carte du Tarot Draconique" }); + rddCommands.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" }); - rddCommands.registerCommand({ path: ["/tmra"], func: (content, msg, params) => TMRUtility.getTMRAleatoire(), descr: "Tire une case aléatoire des Terres médianes" }); + rddCommands.registerCommand({ + path: ["/tmra"], func: (content, msg, params) => rddCommands.getTMRAleatoire(msg, params), + descr: `Tire une case aléatoire des Terres médianes +
/tmra forêt détermine une 'forêt' aléatoire +
/tmra détermine une case aléatoire dans toutes les TMR` }); rddCommands.registerCommand({ path: ["/tmrr"], func: (content, msg, params) => rddCommands.getRencontreTMR(params), - descr: ` - Exemple: /tmrr foret lance un d100 et détermine la rencontre correspondante en 'forêt' - Exemple: /tmrr forêt 47 détermine la rencontre en 'forêt' pour un jet de dé de 47 - ` + descr: `Détermine une rencontre dans un type de case +
/tmrr foret lance un d100 et détermine la rencontre correspondante en 'forêt' +
/tmrr forêt 47 détermine la rencontre en 'forêt' pour un jet de dé de 47` }); rddCommands.registerCommand({ @@ -55,27 +59,24 @@ export class RdDCommands { rddCommands.registerCommand({ path: ["/rdd"], func: (content, msg, params) => rddCommands.rollRdd(msg, params), descr: `Effectue un jet de dés dans la table de résolution. Exemples: -
/rdd ouvre la table de résolution -
/rdd 10 3 effectue un jet 10 à +3 -
/rdd 10 +2 effectue un jet 10 à +2 -
/rdd 15 -2 effectue un jet 15 à -2 -
/rdd 15 0 s effectue un jet 15 à 0, avec significative requise - ` +
/rdd ouvre la table de résolution +
/rdd 10 3 effectue un jet 10 à +3 +
/rdd 10 +2 effectue un jet 10 à +2 +
/rdd 15 -2 effectue un jet 15 à -2 +
/rdd 15 0 s effectue un jet 15 à 0, avec significative requise` }); rddCommands.registerCommand({ path: ["/ddr"], func: (content, msg, params) => rddCommands.rollDeDraconique(msg), descr: "Lance un Dé Draconique" }); rddCommands.registerCommand({ path: ["/payer"], func: (content, msg, params) => RdDUtility.afficherDemandePayer(params[0], params[1]), descr: `Permet de payer un montant. Exemples: -
/payer 5s 10d permet d'envoyer un message pour payer 5 sols et 10 deniers -
/payer 10d permet d'envoyer un message pour payer 10 deniers - ` +
/payer 5s 10d permet d'envoyer un message pour payer 5 sols et 10 deniers +
/payer 10d permet d'envoyer un message pour payer 10 deniers` }); rddCommands.registerCommand({ path: ["/astro"], func: (content, msg, params) => RdDUtility.afficherHeuresChanceMalchance(params[0]), descr: `Affiche les heures de chance et de malchance selon l'heure de naissance donnée en argument. Exemples: -
/astro Lyre - ` +
/astro Lyre` }); game.system.rdd.commands = rddCommands; } @@ -187,7 +188,7 @@ export class RdDCommands { /* -------------------------------------------- */ async getRencontreTMR(params) { - if (params.length == 1 || params.length ==2) { + if (params.length == 1 || params.length == 2) { return TMRRencontres.rollRencontre(params[0], params[1]) } else { @@ -234,6 +235,18 @@ export class RdDCommands { RdDCommands._chatAnswer(msg, `Lancer d'un Dé draconique: ${ddr.total}`); } + getTMRAleatoire(msg, params) { + if (params.length < 2) { + let type = params[0]; + const tmr = TMRUtility.getTMRAleatoire(it => it.type == type); + RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`); + } + else { + return false; + } + } + + /* -------------------------------------------- */ getCoutXpComp(msg, params) { if (params && (params.length == 1 || params.length == 2)) { diff --git a/module/rdd-compendium-organiser.js b/module/rdd-compendium-organiser.js index 2017af97..ad7e1ea2 100644 --- a/module/rdd-compendium-organiser.js +++ b/module/rdd-compendium-organiser.js @@ -1,17 +1,15 @@ import { Misc } from "./misc.js"; +/* -------------------------------------------- */ +/** + * Mapping des types d'Item/Actor vers le nom d'affichage. + * Par défaut, on prend le type avec la première lettre + * majuscule, pas besoin d'ajouter tous les types. + */ const typeDisplayName = { - "objet": "Objet", - "arme": "Arme", - "armure": "Armure", - "conteneur": "Conteneur", "competence": "Compétence", - "sort": "Sort", "herbe": "Plante", "ingredient": "Ingrédient", - "livre": "Livre", - "potion": "Potion", - "munition": "Munition", "queue": "Queue de dragon", "ombre": "Ombre de Thanatos", "souffle": "Souffle de Dragon", @@ -20,20 +18,16 @@ const typeDisplayName = { "rencontresTMR": "Rencontre des TMR", "competencecreature": "Compétence de créature", "nombreastral": "Nombre astral", - "casetmr": "Case des TMR", + "casetmr": "Effet sur TMR", "recettealchimique": "Recette alchimique", "recettecuisine": "Recette de cuisine", "tarot": "Carte de tarot draconique", "tache": "Tâche", "meditation": "Méditation", - "monnaie": "Monnaie", "musique": "Morceau de musique", "chant": "Chanson", - "danse": "Danse", - "jeu": "Jeu", - "personnage": "Personnage", "creature": "Créature", - "entite": "Entité de cauchemar", + "entite": "Entité", "vehicule": "Véhicule" } diff --git a/module/rdd-hotbar-drop.js b/module/rdd-hotbar-drop.js new file mode 100644 index 00000000..12b925bb --- /dev/null +++ b/module/rdd-hotbar-drop.js @@ -0,0 +1,84 @@ + +export class RdDHotbar { + + /** + * Create a macro when dropping an entity on the hotbar + * Item - open roll dialog for item + * Actor - open actor sheet + * Journal - open journal sheet + */ + static initDropbar( ) { + + Hooks.on("hotbarDrop", async (bar, data, slot) => { + // Create item macro if rollable item - weapon, spell, prayer, trait, or skill + if (data.type == "Item") { + if (data.data.type != "arme" && data.data.type != "competence" ) + return + let item = data.data + let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}");`; + let macro = game.macros.entities.find(m => (m.name === item.name) && (m.command === command)); + if (!macro) { + macro = await Macro.create({ + name: item.name, + type: "script", + img: item.img, + command: command + }, { displaySheet: false }) + } + game.user.assignHotbarMacro(macro, slot); + } + // Create a macro to open the actor sheet of the actor dropped on the hotbar + else if (data.type == "Actor") { + let actor = game.actors.get(data.id); + let command = `game.actors.get("${data.id}").sheet.render(true)` + let macro = game.macros.entities.find(m => (m.name === actor.name) && (m.command === command)); + if (!macro) { + macro = await Macro.create({ + name: actor.data.name, + type: "script", + img: actor.data.img, + command: command + }, { displaySheet: false }) + game.user.assignHotbarMacro(macro, slot); + } + } + // Create a macro to open the journal sheet of the journal dropped on the hotbar + else if (data.type == "JournalEntry") { + let journal = game.journal.get(data.id); + let command = `game.journal.get("${data.id}").sheet.render(true)` + let macro = game.macros.entities.find(m => (m.name === journal.name) && (m.command === command)); + if (!macro) { + macro = await Macro.create({ + name: journal.data.name, + type: "script", + img: "systems/wfrp4e/icons/buildings/scroll.png", + command: command + }, { displaySheet: false }) + game.user.assignHotbarMacro(macro, slot); + } + } + return false; + }); + } + + /** Roll macro */ + static rollMacro(itemName, itemType, bypassData) { + const speaker = ChatMessage.getSpeaker(); + let actor; + if (speaker.token) actor = game.actors.tokens[speaker.token]; + if (!actor) actor = game.actors.get(speaker.actor); + let item = actor ? actor.items.find(i => i.name === itemName && i.type == itemType) : null; + if (!item) return ui.notifications.warn(`Impossible de trouver l'objet de cette macro`); + + item = item.data; + + // Trigger the item roll + switch (item.type) { + case "arme": + return actor.rollArme(item.data.competence, itemName); + case "competence": + return actor.rollCompetence( itemName ); + } + } + +} diff --git a/module/rdd-main.js b/module/rdd-main.js index aab4d527..2b6b990f 100644 --- a/module/rdd-main.js +++ b/module/rdd-main.js @@ -20,13 +20,15 @@ import { RdDCalendrier } from "./rdd-calendrier.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDTokenHud } from "./rdd-token-hud.js"; import { RdDCommands } from "./rdd-commands.js"; -import { RdDCombat } from "./rdd-combat.js"; +import { RdDCombatManager, RdDCombat } from "./rdd-combat.js"; import { ChatUtility } from "./chat-utility.js"; import { RdDItemCompetence } from "./item-competence.js"; import { StatusEffects } from "./status-effects.js"; import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js"; import { ReglesOptionelles } from "./regles-optionelles.js"; import { TMRRencontres } from "./tmr-rencontres.js"; +import { RdDHotbar } from "./rdd-hotbar-drop.js" +import { EffetsDraconiques } from "./tmr/effets-draconiques.js"; /* -------------------------------------------- */ /* Foundry VTT Initialization */ @@ -113,7 +115,8 @@ Hooks.once("init", async function () { // Create useful storage space game.system.rdd = { TMRUtility, - RdDUtility + RdDUtility, + RdDHotbar } /* -------------------------------------------- */ @@ -217,6 +220,7 @@ Hooks.once("init", async function () { Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorEntiteSheet, { types: ["entite"], makeDefault: true }); Items.unregisterSheet("core", ItemSheet); Items.registerSheet("foundryvtt-reve-de-dragon", RdDItemSheet, { makeDefault: true }); + CONFIG.Combat.entityClass = RdDCombatManager; // Handlebar function pour container Handlebars.registerHelper('buildConteneur', (objet) => { return RdDUtility.buildConteneur(objet); }); @@ -231,8 +235,10 @@ Hooks.once("init", async function () { RdDActor.init(); RddCompendiumOrganiser.init(); ReglesOptionelles.init(); + EffetsDraconiques.init() TMRUtility.init(); TMRRencontres.init(); + RdDHotbar.initDropbar(); }); /* -------------------------------------------- */ @@ -296,4 +302,9 @@ Hooks.on("chatMessage", (html, content, msg) => { /* -------------------------------------------- */ Hooks.on("getCombatTrackerEntryContext", (html, options) => { RdDUtility.pushInitiativeOptions(html, options); -}) +}); + +/* -------------------------------------------- */ +Hooks.on("renderChatMessage", async (app, html, msg) => { + RdDUtility.onRenderChatMessage(app, html, msg); +}); diff --git a/module/rdd-namegen.js b/module/rdd-namegen.js new file mode 100644 index 00000000..dd59097f --- /dev/null +++ b/module/rdd-namegen.js @@ -0,0 +1,17 @@ +import { Misc } from "./misc.js"; + +const words = [ 'pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i', 'onse', 'iane', 'ane', 'zach', 'arri', 'ba', 'bo', 'bi', + 'alta', 'par', 'pir', 'zor', 'zir', 'de', 'pol', 'tran', 'no', 'la','al' , 'pul', 'one', 'ner', 'nur' ]; + +/* -------------------------------------------- */ +export class RdDNameGen { + + static getName( msg, params ) { + let max = words.length; + let name = words[new Roll("1d"+max+" -1").roll().total]; + name += words[new Roll("1d"+max+" -1").roll().total]; + //console.log(name); + ChatMessage.create( { content: `Nom : ${name}`, whisper: ChatMessage.getWhisperRecipients("GM") } ); + } + +} \ No newline at end of file diff --git a/module/rdd-roll.js b/module/rdd-roll.js index 0b51a02a..04ed49d5 100644 --- a/module/rdd-roll.js +++ b/module/rdd-roll.js @@ -46,18 +46,23 @@ export class RdDRoll extends Dialog { surencMalusFlag: actor.isPersonnage() ? (actor.data.data.compteurs.surenc.value < 0) : false, surencMalusValue: actor.getSurenc(), useMalusSurenc: false, +<<<<<<< HEAD appelAuMoralPossible : false, /* Est-ce que l'appel au moral est possible ? Variable utisé pour l'affichage ou non de la ligne concernant le moral */ appelAuMoralDemander :false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */ jetEchouerMoralDiminuer : false, /* Pour l'affichage dans le chat */ use: { libre:true, conditions: true, surenc: false, encTotal: false, appelAuMoral : false /* Le jet se fait ou non en utilisant l'appel au moral */}, +======= + use: { libre: true, conditions: true, surenc: false, encTotal: false, }, +>>>>>>> v1.3 isMalusEncombrementTotal: RdDItemCompetence.isMalusEncombrementTotal(rollData.competence), useMalusEncTotal: false, encTotal: actor.getEncTotal(), ajustementAstrologique: actor.ajustementAstrologique(), surprise: actor.getSurprise(false), + canClose: true } mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false }); - if ( rollData.forceCarac) { + if (rollData.forceCarac) { rollData.carac = rollData.forceCarac; } RollDataAjustements.calcul(rollData, actor); @@ -85,7 +90,12 @@ export class RdDRoll extends Dialog { close: close }; for (let action of actions) { - conf.buttons[action.name] = { label: action.label, callback: html => this.onAction(action, html) }; + conf.buttons[action.name] = { + label: action.label, callback: html => { + this.rollData.canClose = true; + this.onAction(action, html) + } + }; } super(conf, options); @@ -94,6 +104,14 @@ export class RdDRoll extends Dialog { this.rollData = rollData; } + close() { + if (this.rollData.canClose) { + return super.close(); + } + ui.notifications.info("Vous devez faire ce jet de dés!"); + } + + /* -------------------------------------------- */ async onAction(action, html) { await RdDResolutionTable.rollData(this.rollData); @@ -114,7 +132,7 @@ export class RdDRoll extends Dialog { this.bringToTop(); var dialog = this; - + function onLoad() { let rollData = dialog.rollData; // Update html, according to data @@ -124,7 +142,7 @@ export class RdDRoll extends Dialog { $("#carac").val(rollData.competence.data.defaut_carac); } if (rollData.selectedSort) { - $("#draconic").val( rollData.selectedSort.data.listIndex ); // Uniquement a la selection du sort, pour permettre de changer + $("#draconic").val(rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer } RdDItemSort.setCoutReveReel(rollData.selectedSort); $("#diffLibre").val(Misc.toInt(rollData.diffLibre)); @@ -157,9 +175,9 @@ export class RdDRoll extends Dialog { html.find('#sort').change((event) => { let sortKey = Misc.toInt(event.currentTarget.value); this.rollData.selectedSort = this.rollData.sortList[sortKey]; // Update the selectedCarac - this.rollData.bonus = RdDItemSort.getCaseBonus(this.rollData.selectedSort, this.rollData.coord); + this.rollData.bonus = RdDItemSort.getCaseBonus(this.rollData.selectedSort, this.rollData.tmr.coord); RdDItemSort.setCoutReveReel(this.rollData.selectedSort); - $("#draconic").val( this.rollData.selectedSort.data.listIndex ); // Uniquement a la selection du sort, pour permettre de changer + $("#draconic").val(this.rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer this.updateRollResult(); }); html.find('#ptreve-variable').change((event) => { @@ -168,12 +186,6 @@ export class RdDRoll extends Dialog { console.log("RdDRollSelectDialog - Cout reve", ptreve); this.updateRollResult(); }); - html.find('#ptreve-variable').change((event) => { - let ptreve = Misc.toInt(event.currentTarget.value); - this.rollData.selectedSort.data.ptreve_reel = ptreve; // Update the selectedCarac - console.log("RdDRollSelectDialog - Cout reve", ptreve); - this.updateRollResult(); - }); html.find('#coupsNonMortels').change((event) => { this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel"; this.updateRollResult(); @@ -232,7 +244,9 @@ export class RdDRoll extends Dialog { dmgText = '(' + dmgText + ')'; } if (rollData.selectedSort) { - rollData.bonus = RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.coord); + rollData.bonus = RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.tmr.coord); + HtmlUtility._showControlWhen($("#div-sort-difficulte"), RdDItemSort.isDifficulteVariable(rollData.selectedSort)) + HtmlUtility._showControlWhen($("#div-sort-ptreve"), RdDItemSort.isCoutVariable(rollData.selectedSort)) } if ( ! RdDCarac.isActionPhysique(rollData.selectedCarac || ! actor.isPersonnage() ) ) { @@ -244,28 +258,18 @@ export class RdDRoll extends Dialog { } - RollDataAjustements.calcul(rollData, this.actor); rollData.finalLevel = this._computeFinalLevel(rollData); - + HtmlUtility._showControlWhen($(".diffMoral"), rollData.ajustements.moralTotal.used); HtmlUtility._showControlWhen($("#divAppelAuMoral"), rollData.appelAuMoralPossible ); HtmlUtility._showControlWhen($("#etat-general"), !RdDCarac.isIgnoreEtatGeneral(rollData.selectedCarac, rollData.competence)); HtmlUtility._showControlWhen($("#ajust-astrologique"), RdDResolutionTable.isAjustementAstrologique(rollData)); - // Sort management - if (rollData.selectedSort) { - rollData.bonus = RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.coord); - //console.log("Toggle show/hide", rollData.selectedSort); - HtmlUtility._showControlWhen($("#div-sort-difficulte"), RdDItemSort.isDifficulteVariable(rollData.selectedSort)) - HtmlUtility._showControlWhen($("#div-sort-ptreve"), RdDItemSort.isCoutVariable(rollData.selectedSort)) - } - // Mise à jour valeurs $("#compdialogTitle").text(this._getTitle(rollData)); $('#coupsNonMortels').prop('checked', rollData.coupsNonMortels); $("#dmg-arme-actor").text(dmgText); -// $("#defenseur-surprise").text(RdDBonus.description(rollData.ajustements.attaqueDefenseurSurpris.descr)); $('.table-ajustement').remove(); $(".table-resolution").remove(); $(".table-proba-reussite").remove(); @@ -276,7 +280,7 @@ export class RdDRoll extends Dialog { /* -------------------------------------------- */ - async buildAjustements(rollData){ + async buildAjustements(rollData) { const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-roll-ajustements.html`, rollData); return html; } diff --git a/module/rdd-rolltables.js b/module/rdd-rolltables.js index 8d7ba802..61b1fb19 100644 --- a/module/rdd-rolltables.js +++ b/module/rdd-rolltables.js @@ -35,15 +35,20 @@ export class RdDRollTables { } /* -------------------------------------------- */ - static async getSouffle(toChat = true) { + static async getCompetence(toChat = false) { + return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat); + } + + /* -------------------------------------------- */ + static async getSouffle(toChat = false) { return await RdDRollTables.drawItemFromRollTable("Souffles de Dragon", toChat); } /* -------------------------------------------- */ - static async getQueue(toChat = true) { - let queue = await RdDRollTables.drawItemFromRollTable("Queues de dragon", toChat); + static async getQueue(toChat = false) { + let queue = await RdDRollTables.drawItemFromRollTable("Queues de dragon", toChat); if (queue.name.toLowerCase().includes('lancinant') ) { - queue = await RdDRollTables.drawItemFromRollTable("Désirs lancinants", toChat); + queue = await RdDRollTables.drawItemFromRollTable("Désirs lancinants", toChat); } if (queue.name.toLowerCase().includes('fixe') ) { queue = await RdDRollTables.drawItemFromRollTable("Idées fixes", toChat); @@ -52,17 +57,17 @@ export class RdDRollTables { } /* -------------------------------------------- */ - static async getTete(toChat = true) { + static async getTete(toChat = false) { return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour haut-rêvants", toChat); } /* -------------------------------------------- */ - static async getTeteHR(toChat = true) { + static async getTeteHR(toChat = false) { return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour tous personnages", toChat); } /* -------------------------------------------- */ - static async getOmbre(toChat = true) { + static async getOmbre(toChat = false) { return await RdDRollTables.drawItemFromRollTable("Ombre de Thanatos", toChat); } diff --git a/module/rdd-tmr-dialog.js b/module/rdd-tmr-dialog.js index 61b9059e..db874e8e 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -1,21 +1,31 @@ -/** - * Extend the base Dialog entity by defining a custom window to perform spell. - * @extends {Dialog} - */ import { RollDataAjustements } from "./rolldata-ajustements.js"; import { RdDUtility } from "./rdd-utility.js"; -import { TMRUtility } from "./tmr-utility.js"; -import { tmrConstants } from "./tmr-utility.js"; +import { TMRUtility, tmrConstants } from "./tmr-utility.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDTMRRencontreDialog } from "./rdd-tmr-rencontre-dialog.js"; import { TMRRencontres } from "./tmr-rencontres.js"; import { ChatUtility } from "./chat-utility.js"; +import { RdDRoll } from "./rdd-roll.js"; +import { Poetique } from "./poetique.js"; +import { EffetsDraconiques } from "./tmr/effets-draconiques.js"; +import { PixiTMR } from "./tmr/pixi-tmr.js"; +import { Draconique } from "./tmr/draconique.js"; /* -------------------------------------------- */ export class RdDTMRDialog extends Dialog { + static async create(html, actor, tmrData) { + + if (tmrData.mode != 'visu') { + // Notification au MJ + ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatMessage.getWhisperRecipients("GM") }); + } + + return new RdDTMRDialog(html, actor, tmrData); + } + /* -------------------------------------------- */ - constructor(html, actor, tmrData, mode) { + constructor(html, actor, tmrData) { const dialogConf = { title: "Terres Médianes de Rêve", content: html, @@ -35,23 +45,150 @@ export class RdDTMRDialog extends Dialog { this.tmrdata = duplicate(tmrData); this.actor = actor; this.actor.tmrApp = this; // reference this app in the actor structure - this.viewOnly = mode == "visu" - this.nbFatigue = this.viewOnly ? 0 : 1; // 1 premier point de fatigue du à la montée - this.rencontresExistantes = duplicate(this.actor.data.data.reve.rencontre.list); - this.sortReserves = duplicate(this.actor.data.data.reve.reserve.list); - this.casesSpeciales = this.actor.data.items.filter(item => item.type == 'casetmr'); + this.viewOnly = tmrData.mode == "visu" + this.fatigueParCase = this.viewOnly ? 0 : this.actor.getTMRFatigue(); + this.cumulFatigue = 0; + this.loadRencontres(); + this.loadSortsReserve(); + this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item)); this.allTokens = []; this.rencontreState = 'aucune'; this.pixiApp = new PIXI.Application({ width: 720, height: 860 }); + + this.pixiTMR = new PixiTMR(this, this.pixiApp); + + this.callbacksOnAnimate = []; if (!this.viewOnly) { this.actor.setStatusDemiReve(true); - this._tellToGM(this.actor.name + " monte dans les terres médianes (" + mode + ")"); + this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); } + // load the texture we need + this.pixiTMR.load((loader, resources) => this.createPixiSprites()); + } + + loadSortsReserve() { + this.sortsReserves = duplicate(this.actor.data.data.reve.reserve.list); + } + + loadRencontres() { + this.rencontresExistantes = duplicate(this.actor.getTMRRencontres()).list; + } + + /* -------------------------------------------- */ + createPixiSprites() { + EffetsDraconiques.carteTmr._createSprite(this.pixiTMR); + + this.updateTokens(); + + this.demiReve = this._tokenDemiReve(); + this._updateDemiReve(); + } + + /* -------------------------------------------- */ + _createTokens() { + let tokens = this._getTokensCasesTmr() + .concat(this._getTokensRencontres()) + .concat(this._getTokensSortsReserve()); + + for (let t of tokens) { + this._trackToken(t); + } + } + + updateTokens() { + this._removeTokens(t => true); + this.loadRencontres(); + this.loadSortsReserve(); + this._createTokens(); + } + + /* -------------------------------------------- */ + _getTokensCasesTmr() { + return this.casesSpeciales.map(c => this._tokenCaseSpeciale(c)).filter(token => token); + } + _getTokensRencontres() { + return this.rencontresExistantes.map(it => this._tokenRencontre(it)); + } + _getTokensSortsReserve() { + return this.sortsReserves.map(it => this._tokenSortEnReserve(it)); + } + + /* -------------------------------------------- */ + _tokenRencontre(rencontre) { + return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord); + } + _tokenCaseSpeciale(caseSpeciale) { + const draconique = Draconique.get(caseSpeciale.data.specific); + return draconique?.token(this.pixiTMR, caseSpeciale, () => caseSpeciale.data.coord); + } + _tokenSortEnReserve(sortEnReserve) { + return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortEnReserve.sort, () => sortEnReserve.coord); + } + _tokenDemiReve() { + return EffetsDraconiques.demiReve.token(this.pixiTMR, this.actor, () => this.actor.data.data.reve.tmrpos.coord); + } + + _updateDemiReve() { + this._setTokenPosition(this.demiReve); + } + + /* -------------------------------------------- */ + async activateListeners(html) { + super.activateListeners(html); + + document.getElementById("tmrrow1").insertCell(1).append(this.pixiApp.view); + + if (this.viewOnly) { + html.find('#lancer-sort').remove(); + } + else { + // Roll Sort + html.find('#lancer-sort').click((event) => { + this.actor.rollUnSort(this.actor.data.data.reve.tmrpos.coord); + }); + } + if (this.viewOnly) { + return; + } + + // Gestion du cout de montée en points de rêve + let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) + - this.actor.countMonteeLaborieuse(); + this.cumulFatigue += this.fatigueParCase; + await this.actor.reveActuelIncDec(reveCout); + + // Le reste... + this.updateValuesDisplay(); + let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord); + await this.manageRencontre(tmr, () => { + this.postRencontre(tmr); + this.actor.displayTMRQueueSouffleInformation(); + }); + } + + /* -------------------------------------------- */ + updateValuesDisplay() { + let ptsreve = document.getElementById("tmr-pointsreve-value"); + ptsreve.innerHTML = this.actor.data.data.reve.reve.value; + + let tmrpos = document.getElementById("tmr-pos"); + let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord); + tmrpos.innerHTML = this.actor.data.data.reve.tmrpos.coord + " (" + tmr.label + ")"; + + let etat = document.getElementById("tmr-etatgeneral-value"); + etat.innerHTML = this.actor.getEtatGeneral(); + + let refoulement = document.getElementById("tmr-refoulement-value"); + refoulement.innerHTML = this.actor.data.data.reve.refoulement.value; + + let fatigueItem = document.getElementById("tmr-fatigue-table"); + //console.log("Refresh : ", this.actor.data.data.sante.fatigue.value); + fatigueItem.innerHTML = "" + RdDUtility.makeHTMLfatigueMatrix(this.actor.data.data.sante.fatigue.value, this.actor.data.data.sante.endurance.max).html() + "
"; } /* -------------------------------------------- */ close() { - this.actor.santeIncDec("fatigue", this.nbFatigue).then(super.close()); // moving 1 cell costs 1 fatigue + this.actor.santeIncDec("fatigue", this.cumulFatigue).then(super.close()); // moving 1 cell costs 1 fatigue this.actor.tmrApp = undefined; // Cleanup reference this.actor.setStatusDemiReve(false); if (!this.viewOnly) { @@ -59,51 +196,6 @@ export class RdDTMRDialog extends Dialog { } } - /* -------------------------------------------- */ - displaySortReserve() { - console.debug("displaySortReserve", this.sortReserves); - for (let sort of this.sortReserves) { - this._trackToken(this._tokenSortEnReserve(sort)); - } - } - - /* -------------------------------------------- */ - displaySpecificCase() { - for (let caseTMR of this.casesSpeciales) { - console.log("SPEC CASE ", caseTMR); - if (caseTMR.data.specific == 'trounoir') { - this._trackToken(this._tokenTrouNoir(caseTMR.data.coord)); - } else if (caseTMR.data.specific == 'attache') { - this._trackToken(this._tokenTerreAttache(caseTMR.data.coord)); - } else if (caseTMR.data.specific == 'debordement') { - this._trackToken(this._tokenDebordement(caseTMR.data.coord)); - } else if (caseTMR.data.specific == 'maitrisee') { - this._trackToken(this._tokenMaitrisee(caseTMR.data.coord)); - } - } - } - - /* -------------------------------------------- */ - displayPreviousRencontres() { - console.debug("displayPreviousRencontres", this.rencontresExistantes); - for (let rencontre of this.rencontresExistantes) { - this._trackToken(this._tokenRencontre(rencontre)); - } - } - - /* -------------------------------------------- */ - updatePreviousRencontres() { - this._removeTokens(t => t.rencontre != undefined); - this.rencontresExistantes = duplicate(this.actor.data.data.reve.rencontre.list); - this.displayPreviousRencontres(); - } - - /* -------------------------------------------- */ - updateSortReserve() { - this._removeTokens(t => t.sort != undefined); - this.sortReserves = duplicate(this.actor.data.data.reve.reserve.list); - this.displaySortReserve(); - } /* -------------------------------------------- */ async derober() { @@ -117,7 +209,7 @@ export class RdDTMRDialog extends Dialog { this._tellToGM(this.actor.name + " a refoulé : " + this.currentRencontre.name); await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary await this.actor.ajouterRefoulement(this.currentRencontre.refoulement ?? 1); - this.updatePreviousRencontres(); + this.updateTokens(); console.log("-> refouler", this.currentRencontre) this.updateValuesDisplay(); this.nettoyerRencontre(); @@ -127,7 +219,7 @@ export class RdDTMRDialog extends Dialog { async ignorerRencontre() { this._tellToGM(this.actor.name + " a ignoré : " + this.currentRencontre.name); await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary - this.updatePreviousRencontres(); + this.updateTokens(); this.updateValuesDisplay(); this.nettoyerRencontre(); } @@ -162,7 +254,7 @@ export class RdDTMRDialog extends Dialog { } async choisirCaseType(type) { - const locList = TMRUtility.getListCoordTMR(type); + const locList = TMRUtility.filterTMR(it => it.type == type).map(it => it.coord); this.colorierZoneRencontre(locList); } @@ -174,7 +266,7 @@ export class RdDTMRDialog extends Dialog { this.close(); return true; } - const resteAvantInconscience = this.actor.getFatigueMax() - this.actor.getFatigueActuelle() - this.nbFatigue; + const resteAvantInconscience = this.actor.getFatigueMax() - this.actor.getFatigueActuelle() - this.cumulFatigue; if (resteAvantInconscience <= 0) { this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !"); this.quitterLesTMRInconscient(); @@ -196,10 +288,9 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async maitriser() { + async maitriserRencontre() { this.actor.deleteTMRRencontreAtPosition(); - this.updatePreviousRencontres(); - + this.updateTokens(); let rencontreData = { actor: this.actor, @@ -208,12 +299,14 @@ export class RdDTMRDialog extends Dialog { competence: this.actor.getBestDraconic(), rencontre: this.currentRencontre, nbRounds: 1, + canClose: false, tmr: TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord) } await this._tentativeMaitrise(rencontreData); } + /* -------------------------------------------- */ async _tentativeMaitrise(rencontreData) { console.log("-> matriser", rencontreData); @@ -223,7 +316,6 @@ export class RdDTMRDialog extends Dialog { RollDataAjustements.calcul(rencontreData, this.actor); rencontreData.rolled = await RdDResolutionTable.roll(rencontreData.reve, RollDataAjustements.sum(rencontreData.ajustements)); - let postProcess = await TMRRencontres.gererRencontre(this, rencontreData); ChatMessage.create({ @@ -246,22 +338,25 @@ export class RdDTMRDialog extends Dialog { else if (rencontreData.rolled.isEchec && rencontreData.rencontre.isPersistant) { setTimeout(() => { rencontreData.nbRounds++; - this.nbFatigue += 1; + this.cumulFatigue += this.fatigueParCase; this._tentativeMaitrise(rencontreData); - setTimeout(() => this._deleteTmrMessages(rencontreData.actor, rencontreData.nbRounds), 500); + this._deleteTmrMessages(rencontreData.actor, rencontreData.nbRounds); }, 2000); } } + /* -------------------------------------------- */ _deleteTmrMessages(actor, nbRounds = -1) { - if (nbRounds < 0) { - ChatUtility.removeChatMessageContaining(`

`); + setTimeout(() => { + if (nbRounds < 0) { + ChatUtility.removeChatMessageContaining(`

`); + } + } + }, 500); } /* -------------------------------------------- */ @@ -275,171 +370,211 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async manageRencontre(coordTMR, cellDescr) { + async manageRencontre(tmr, postRencontre) { if (this.viewOnly) { return; } this.currentRencontre = undefined; - let rencontre = await this._jetDeRencontre(coordTMR, cellDescr); + let rencontre = await this._jetDeRencontre(tmr); if (rencontre) { // Manages it if (rencontre.rencontre) rencontre = rencontre.rencontre; // Manage stored rencontres console.log("manageRencontre", rencontre); this.currentRencontre = duplicate(rencontre); - let dialog = new RdDTMRRencontreDialog("", this, this.currentRencontre); + let dialog = new RdDTMRRencontreDialog("", this, this.currentRencontre, postRencontre); dialog.render(true); } + else { + postRencontre(); + } } /* -------------------------------------------- */ - async _jetDeRencontre(coordTMR, cellDescr) { - if (TMRUtility.isForceRencontre()) { - return await TMRUtility.rencontreTMRRoll(coordTMR, cellDescr); - } - let rencontre = this.rencontresExistantes.find(prev => prev.coord == coordTMR); + async _jetDeRencontre(tmr) { + let rencontre = this.rencontresExistantes.find(prev => prev.coord == tmr.coord); if (rencontre) { return rencontre; } - let myRoll = new Roll("1d7").evaluate(); - if (myRoll.total == 7) { - let isMauvaise = this.actor.isRencontreSpeciale(); - return await TMRUtility.rencontreTMRRoll(coordTMR, cellDescr, isMauvaise); + // TODO: dialog pour remplacer la rencontre par un présent + //if (this.casesSpeciales.find(c => EffetsDraconiques.isPresentCite(c, tmr.coord))) { + + + let myRoll = new Roll("1d7").evaluate().total; + if (TMRUtility.isForceRencontre() || myRoll == 7) { + return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale()); } - this._tellToUser(myRoll.total + ": Pas de rencontre en " + cellDescr.label + " (" + coordTMR + ")"); + this._tellToUser(myRoll + ": Pas de rencontre en " + tmr.label + " (" + tmr.coord + ")"); + } + + + /* -------------------------------------------- */ + async rencontreTMRRoll(tmr, isMauvaise = false) { + let rencontre = TMRUtility.utiliseForceRencontre() ?? + (isMauvaise + ? await TMRRencontres.getMauvaiseRencontre() + : await TMRRencontres.getRencontreAleatoire(tmr.type)); + rencontre.coord = tmr.coord; + rencontre.date = game.system.rdd.calendrier.getDateFromIndex(); + rencontre.heure = game.system.rdd.calendrier.getCurrentHeure(); + return rencontre; } /* -------------------------------------------- */ - updateValuesDisplay() { - let ptsreve = document.getElementById("tmr-pointsreve-value"); - ptsreve.innerHTML = this.actor.data.data.reve.reve.value; - - let tmrpos = document.getElementById("tmr-pos"); - let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord); - tmrpos.innerHTML = this.actor.data.data.reve.tmrpos.coord + " (" + tmr.label + ")"; - - let etat = document.getElementById("tmr-etatgeneral-value"); - etat.innerHTML = this.actor.getEtatGeneral(); - - let refoulement = document.getElementById("tmr-refoulement-value"); - refoulement.innerHTML = this.actor.data.data.reve.refoulement.value; - - let fatigueItem = document.getElementById("tmr-fatigue-table"); - //console.log("Refresh : ", this.actor.data.data.sante.fatigue.value); - fatigueItem.innerHTML = "" + RdDUtility.makeHTMLfatigueMatrix(this.actor.data.data.sante.fatigue.value, this.actor.data.data.sante.endurance.max).html() + "
"; - } - - /* -------------------------------------------- */ - async manageCaseSpeciale(cellDescr, coordTMR) { - for (let caseTMR of this.casesSpeciales) { - if (caseTMR.data.coord == coordTMR) { // Match ! - if (caseTMR.data.specific == 'trounoir') { - let newTMR = TMRUtility.getTMRAleatoire(); - let tmrPos = duplicate(this.actor.data.data.reve.tmrpos); - tmrPos.coord = newTMR; - await this.actor.update({ "data.reve.tmrpos": tmrPos }); - ChatMessage.create({ - content: "Vous êtes rentré sur un Trou Noir : ré-insertion aléatoire.", - whisper: ChatMessage.getWhisperRecipients(game.user.name) - }); - } - } + async manageCaseSpeciale(tmr) { + if (this.casesSpeciales.find(c => EffetsDraconiques.isCaseTrouNoir(c, tmr.coord))) { + let newTMR = TMRUtility.getTMRAleatoire(); + let tmrPos = duplicate(this.actor.data.data.reve.tmrpos); + tmrPos.coord = newTMR.coord; + await this.actor.update({ "data.reve.tmrpos": tmrPos }); + ChatMessage.create({ + content: "Vous êtes rentré sur un Trou Noir : ré-insertion aléatoire.", + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); } } /* -------------------------------------------- */ - isCaseMaitrisee(coordTMR) { - for (let caseTMR of this.casesSpeciales) { - if (caseTMR.data.coord == coordTMR && caseTMR.data.specific == 'maitrisee') { - return true; - } - } - return false; - } - - /* -------------------------------------------- */ - manageCaseHumideResult() { - if (this.toclose) - this.close(); - } - - /* -------------------------------------------- */ - async manageCaseHumide(cellDescr, coordTMR) { + async manageCaseHumide(tmr) { if (this.viewOnly || this.currentRencontre) { return; } - let isHumide = this.actor.checkIsAdditionnalHumide(cellDescr, coordTMR); - if (cellDescr.type == "lac" || cellDescr.type == "fleuve" || cellDescr.type == "marais" || isHumide) { - if (this.isCaseMaitrisee(coordTMR)) { - ChatMessage.create({ - content: "Cette case humide est déja maitrisée grâce à votre Tête Quête des Eaux", - whisper: ChatMessage.getWhisperRecipients(game.user.name) - }); - return; + if (this.isCaseHumide(tmr)) { + let rollData = { + actor: this.actor, + competence: duplicate(this.actor.getBestDraconic()), + tmr: tmr, + canClose: false, + diffLibre: -7, + forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } }, + maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' } } - // TODO: permettre de choisir la voie de draconic? - let draconic = this.actor.getBestDraconic(); + rollData.competence.data.defaut_carac = 'reve-actuel'; - let carac = this.actor.getReveActuel(); - const etatGeneral = this.actor.getEtatGeneral(); - let difficulte = draconic.data.niveau - 7; - let rolled = await RdDResolutionTable.roll(carac, difficulte); - - // Gestion du souffle Double Résistance du Fleuve - if (this.actor.isDoubleResistanceFleuve()) { - let rolled2 = await RdDResolutionTable.roll(carac, difficulte); - if (rolled2.isEchec) - rolled = rolled; - } - console.log("manageCaseHumide >>", rolled); - - let explication = ""; - let msg2MJ = ""; - this.toclose = rolled.isEchec; - if (rolled.isEchec) { - explication += "Vous êtes entré sur une case humide, et vous avez raté votre maîtrise ! Vous quittez les Terres Médianes !" - msg2MJ += game.user.name + " est rentré sur une case humides : Echec !"; - } - else { - explication += "Vous êtes entré sur une case humide, et vous avez réussi votre maîtrise !" - msg2MJ += game.user.name + " est rentré sur une case humides : Réussite !"; - } - explication += "
Test : Rêve actuel / " + draconic.name + " / " + cellDescr.type + "" - + RdDResolutionTable.explain(rolled); - - if (rolled.isETotal) { - let souffle = await this.actor.ajouterSouffle({ chat: false }); - explication += "
Vous avez fait un Echec Total. Vous subissez un Souffle de Dragon : " + souffle.name; - msg2MJ += "
Et a reçu un Souffle de Dragon : " + souffle.name; - } - if (rolled.isPart) { - explication += "
Vous avez fait une Réussite Particulière"; - this.actor._appliquerAjoutExperience({ rolled: rolled, seletedCarac: { label: 'reve' }, competence: draconic.name }) - msg2MJ += "
Et a fait une réussite particulière"; - } - - // Notification au MJ - ChatMessage.create({ content: msg2MJ, whisper: ChatMessage.getWhisperRecipients("GM") }); - // Et au joueur (ca pourrait être un message de tchat d'ailleurs) - let humideDiag = new Dialog({ - title: "Case humide", - content: explication, - buttons: { - choice: { icon: '', label: "Fermer", callback: () => this.manageCaseHumideResult() } - } - } - ); - humideDiag.render(true); + await this._rollMaitriseCaseHumide(rollData); } } + /* -------------------------------------------- */ - isReserveExtensible(coordTMR) { - for (let caseTMR of this.casesSpeciales) { - if (caseTMR.data.specific == 'reserve_extensible' && caseTMR.data.coord == coordTMR) - return true; + async _rollMaitriseCaseHumide(rollData) { + await this._maitriserTMR(rollData, r => this._resultatMaitriseCaseHumide(r)); + } + + async _resultatMaitriseCaseHumide(rollData) { + if (rollData.rolled.isETotal) { + rollData.souffle = await this.actor.ajouterSouffle({ chat: false }); + } + this.toclose = rollData.rolled.isEchec; + if (rollData.rolled.isSuccess && !rollData.previous && EffetsDraconiques.isDoubleResistanceFleuve(this.actor)) { + rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements }; + await this._rollMaitriseCaseHumide(rollData); + return; + } + rollData.poesie = Poetique.getExtrait(); + ChatMessage.create({ + whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), + content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData) + }); + if (rollData.rolled.isEchec) { + this.close(); + } + } + + /* -------------------------------------------- */ + isCaseHumide(tmr) { + if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) { + return undefined; + } + if (this.isCaseMaitrisee(tmr.coord)) { + ChatMessage.create({ + content: tmr.label + ": cette case humide est déja maitrisée grâce à votre Tête Quête des Eaux", + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); + return undefined; + } + return -7; + } + + /* -------------------------------------------- */ + isCaseHumideAdditionelle(tmr) { + if (tmr.type == 'pont' && EffetsDraconiques.isPontImpraticable(this.actor)) { + ChatMessage.create({ + content: tmr.label + ": Vous êtes sous le coup d'une Impraticabilité des Ponts : ce pont doit être maîtrisé comme une case humide.", + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); + return true; + } + if (this.isCaseInondee(tmr.coord)) { + ChatMessage.create({ + content: tmr.label + ": cette case est inondée, elle doit être maîtrisée comme une case humide.", + whisper: ChatMessage.getWhisperRecipients(game.user.name) + }); + return true; } return false; } + + /* -------------------------------------------- */ + async conquerirCiteFermee(tmr) { + if (this.viewOnly || this.currentRencontre) { + return; + } + const citeFermee = this.isCiteFermee(tmr.coord); + if (citeFermee) { + let rollData = { + actor: this.actor, + competence: duplicate(this.actor.getBestDraconic()), + tmr: tmr, + canClose: false, + diffLibre: -9, + forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } }, + maitrise: { verbe: 'conquérir', action: 'Conquérir la cité' } + } + rollData.competence.data.defaut_carac = 'reve-actuel'; + + await this._maitriserTMR(rollData, r => this._resultatConqueteCiteFermee(r)); + } + } + async _resultatConqueteCiteFermee(rollData) { + if (rollData.rolled.isETotal) { + rollData.souffle = await this.actor.ajouterSouffle({ chat: false }); + } + this.toclose = rollData.rolled.isEchec; + + rollData.poesie = Poetique.getExtrait(); + ChatMessage.create({ + whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), + content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData) + }); + if (rollData.rolled.isEchec) { + this.close(); + } + else { + const citeFermee = this.actor.data.items.find(it => EffetsDraconiques.isCiteFermee(it, rollData.tmr.coord)); + this.actor.deleteOwnedItem(citeFermee._id); + this._removeTokens(t => t.coordTMR() == citeFermee.data.coord && t.caseSpeciale?._id == citeFermee._id); + } + } + + /* -------------------------------------------- */ + async _maitriserTMR(rollData, callbackMaitrise) { + this.minimize(); // Hide + const dialog = await RdDRoll.create(this.actor, rollData, + { + html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html', + options: { height: 350 }, + close: html => { this.maximize(); } // Re-display TMR + }, + { + name: rollData.maitrise.verbe, label: rollData.maitrise.action, + callbacks: [ + this.actor.createCallbackExperience(), + { action: callbackMaitrise } + ] + } + ); + dialog.render(true); + } /* -------------------------------------------- */ async declencheSortEnReserve(coordTMR) { @@ -447,9 +582,9 @@ export class RdDTMRDialog extends Dialog { return; } - let sortReserveList = TMRUtility.getSortReserveList(this.sortReserves, coordTMR); + let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR); if (sortReserveList.length > 0) { - if (this.actor.isReserveEnSecurite() || this.isReserveExtensible(coordTMR)) { + if (EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coordTMR)) { let msg = "Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête Reserve en Sécurité ou Réserve Exensible, vous pouvez contrôler le déclenchement. Cliquez si vous souhaitez le déclencher :
    "; for (let sortReserve of sortReserveList) { msg += "
  • " + sortReserve.sort.name + "
  • "; @@ -464,9 +599,10 @@ export class RdDTMRDialog extends Dialog { } } } + /* -------------------------------------------- */ lancerSortEnReserve(coordTMR, sortId) { - let sortReserveList = TMRUtility.getSortReserveList(this.sortReserves, coordTMR); + let sortReserveList = TMRUtility.getSortReserveList(this.sortsReserves, coordTMR); let sortReserve = sortReserveList.find(sortReserve => sortReserve.sort._id == sortId); //console.log("SORT RESA", sortReserveList, coordTMR, sortId, sortReserve); if (sortReserve) { @@ -516,81 +652,69 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - isTerreAttache(coordTMR) { - for (let caseTMR of this.casesSpeciales) { - if (caseTMR.data.specific == 'attache' && caseTMR.data.coord == coordTMR) { // Match ! - return true; - } - } - return false; + isCaseInondee(coord) { + return this.casesSpeciales.find(c => EffetsDraconiques.isCaseInondee(c, coord)); + } + + isCiteFermee(coord) { + return this.casesSpeciales.find(c => EffetsDraconiques.isCiteFermee(c, coord)); } /* -------------------------------------------- */ - checkConnaissanceFleuve(currentTMR, nextTMR) { - if (this.actor.isConnaissanceFleuve()) { - //console.log(currentTMR, nextTMR ); - if (TMRUtility.getTMR(currentTMR).type == 'fleuve' && TMRUtility.getTMR(nextTMR).type == 'fleuve') { - return true; - } - } - return false; + isTerreAttache(coord) { + return this.casesSpeciales.find(c => EffetsDraconiques.isTerreAttache(c, coord)); } /* -------------------------------------------- */ - async deplacerDemiReve(event) { + isCaseMaitrisee(coord) { + return this.casesSpeciales.find(c => EffetsDraconiques.isCaseMaitrisee(c, coord)); + } + + /* -------------------------------------------- */ + isReserveExtensible(coord) { + return this.casesSpeciales.find(c => EffetsDraconiques.isReserveExtensible(c, coord)); + } + + /* -------------------------------------------- */ + isConnaissanceFleuve(currentTMR, nextTMR) { + return TMRUtility.getTMR(currentTMR).type == 'fleuve' && + TMRUtility.getTMR(nextTMR).type == 'fleuve' && + EffetsDraconiques.isConnaissanceFleuve(this.actor); + } + + /* -------------------------------------------- */ + async onClickTMR(event) { if (this.viewOnly) { return; } let origEvent = event.data.originalEvent; - let myself = event.target.tmrObject; + let tmrObject = this; - let eventCoord = RdDTMRDialog._computeEventCoord(origEvent); - let cellx = eventCoord.cellx; - let celly = eventCoord.celly; - console.log("deplacerDemiReve >>>>", cellx, celly); - let currentPos = TMRUtility.convertToCellCoord(myself.actor.data.data.reve.tmrpos.coord); - let coordTMR = TMRUtility.convertToTMRCoord(cellx, celly); - let currentTMR = TMRUtility.convertToTMRCoord(currentPos.x, currentPos.y); + let eventPos = RdDTMRDialog._computeEventPos(origEvent); + await tmrObject._onClickTMRPos(eventPos); // Vérifier l'état des compteurs reve/fatigue/vie + } + + async _onClickTMRPos(eventPos) { + let currentPos = TMRUtility.convertToCellPos(this.actor.data.data.reve.tmrpos.coord); + + console.log("deplacerDemiReve >>>>", currentPos, eventPos); + + let targetCoordTMR = TMRUtility.convertToTMRCoord(eventPos); + let currentCoordTMR = TMRUtility.convertToTMRCoord(currentPos); // Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter) let deplacementType = 'erreur'; - if (myself.rencontreState == 'aucune') { // Pas de recontre en post-processing, donc deplacement normal - if (!RdDTMRDialog._horsDePortee(currentPos, cellx, celly) || myself.isTerreAttache(coordTMR) || myself.checkConnaissanceFleuve(currentTMR, coordTMR)) { + if (this.rencontreState == 'aucune') { // Pas de recontre en post-processing, donc deplacement normal + if (this.isTerreAttache(targetCoordTMR) || this.isConnaissanceFleuve(currentCoordTMR, targetCoordTMR) || !RdDTMRDialog._horsDePortee(currentPos, eventPos)) { deplacementType = 'normal'; } } else { - deplacementType = myself.processClickPostRencontre(coordTMR); + deplacementType = this.processClickPostRencontre(targetCoordTMR); } // Si le deplacement est valide if (deplacementType == 'normal' || deplacementType == 'saut') { - if (myself.currentRencontre != 'normal') - myself.nettoyerRencontre(); - let cellDescr = TMRUtility.getTMR(coordTMR); - - await myself.manageCaseSpeciale(cellDescr, coordTMR); // Gestion cases spéciales type Trou noir, etc - - console.log("deplacerDemiReve: TMR column is", coordTMR, cellx, celly, cellDescr, this); - - let tmrPos = duplicate(myself.actor.data.data.reve.tmrpos); - tmrPos.coord = coordTMR; - await myself.actor.update({ "data.reve.tmrpos": tmrPos }); - myself._updateDemiReve(myself); - myself.nbFatigue += 1; - myself.updateValuesDisplay(); - game.socket.emit("system.foundryvtt-reve-de-dragon", { - msg: "msg_tmr_move", data: { - actorId: myself.actor.data._id, - tmrPos: tmrPos - } - }); - - if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... - await myself.manageRencontre(coordTMR, cellDescr); - } - await myself.manageCaseHumide(cellDescr, coordTMR); - await myself.declencheSortEnReserve(coordTMR); - await myself.actor.checkSoufflePeage(cellDescr); + await this._deplacerDemiReve(targetCoordTMR, deplacementType); } else if (deplacementType == 'messager') { // Dans ce cas, ouverture du lancement de sort sur la case visée /* @@ -598,241 +722,104 @@ export class RdDTMRDialog extends Dialog { Si la case est le demi-rêve, ne pas lancer de sort. Si un lancement de sort est en cours, trouver un moyen de réafficher cette fenêtre si on essaie de lancer un sort (ou bloquer le lancer de sort) */ - await myself.actor.rollUnSort(coordTMR); - myself.nettoyerRencontre(); + await this._messagerDemiReve(targetCoordTMR); } else { ui.notifications.error("Vous ne pouvez vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre"); - console.log("STATUS :", myself.rencontreState, myself.currentRencontre); + console.log("STATUS :", this.rencontreState, this.currentRencontre); } - myself.checkQuitterTMR(); // Vérifier l'état des compteurs reve/fatigue/vie + this.checkQuitterTMR(); + } + + async _messagerDemiReve(targetCoordTMR) { + await this.actor.rollUnSort(targetCoordTMR); + this.nettoyerRencontre(); + } + + async _deplacerDemiReve(targetCoord, deplacementType) { + if (this.currentRencontre != 'normal') { + this.nettoyerRencontre(); + } + let tmr = TMRUtility.getTMR(targetCoord); + + await this.manageCaseSpeciale(tmr); // Gestion cases spéciales type Trou noir, etc + + console.log("deplacerDemiReve: TMR is", tmr, this); + + let tmrPos = duplicate(this.actor.data.data.reve.tmrpos); + tmrPos.coord = targetCoord; + await this.actor.update({ "data.reve.tmrpos": tmrPos }); + + this._updateDemiReve(); + this.cumulFatigue += this.fatigueParCase; + this.updateValuesDisplay(); + game.socket.emit("system.foundryvtt-reve-de-dragon", { + msg: "msg_tmr_move", data: { + actorId: this.actor.data._id, + tmrPos: tmrPos + } + }); + + if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... + await this.manageRencontre(tmr, () => this.postRencontre(tmr)); + } + else { + await this.postRencontre(tmr); + } + } + + async postRencontre(tmr) { + await this.manageCaseHumide(tmr); + await this.conquerirCiteFermee(tmr); + await this.declencheSortEnReserve(tmr.coord); + await this.actor.checkSoufflePeage(tmr); } /* -------------------------------------------- */ async forceDemiRevePositionView(coordTMR) { - this._updateDemiReve(this); + this._updateDemiReve(); } /* -------------------------------------------- */ async forceDemiRevePosition(coordTMR) { await this.actor.updateCoordTMR(coordTMR); - this._updateDemiReve(this); - let cellDescr = TMRUtility.getTMR(coordTMR); - this.manageCaseHumide(cellDescr, coordTMR); - await this.declencheSortEnReserve(coordTMR); + this._updateDemiReve(); + let tmr = TMRUtility.getTMR(coordTMR); + await this.manageCaseHumide(tmr); + await this.conquerirCiteFermee(tmr); + await this.declencheSortEnReserve(tmr.coord); } /* -------------------------------------------- */ - async activateListeners(html) { - super.activateListeners(html); - - var row = document.getElementById("tmrrow1"); - var cell1 = row.insertCell(1); - cell1.append(this.pixiApp.view); - - if (this.viewOnly) { - html.find('#lancer-sort').remove(); - } - else { - // Roll Sort - html.find('#lancer-sort').click((event) => { - this.actor.rollUnSort(this.actor.data.data.reve.tmrpos.coord); - }); - } - - // load the texture we need - await this.pixiApp.loader - .add('tmr', 'systems/foundryvtt-reve-de-dragon/styles/img/ui/tmp_main_r1.webp') - .add('demi-reve', "icons/svg/sun.svg") - .load((loader, resources) => { - - // This creates a texture from a TMR image - const mytmr = new PIXI.Sprite(resources.tmr.texture); - // Setup the position of the TMR - mytmr.x = 0; - mytmr.y = 0; - mytmr.width = 720; - mytmr.height = 860; - // Rotate around the center - mytmr.anchor.x = 0; - mytmr.anchor.y = 0; - mytmr.interactive = true; - mytmr.buttonMode = true; - mytmr.tmrObject = this; - if (!this.viewOnly) { - mytmr.on('pointerdown', this.deplacerDemiReve); - } - this.pixiApp.stage.addChild(mytmr); - - this._addDemiReve(); - this.displayPreviousRencontres(); - this.displaySortReserve(); - this.displaySpecificCase(); - }); - - if (this.viewOnly) { - return; - } - - // Gestion du cout de montée en points de rêve - let reveCout = -1; - if (this.actor.checkTeteDeplacementAccelere()) { - reveCout = -1; - } else { - reveCout = (this.tmrdata.isRapide) ? -2 : -1; - } - reveCout -= this.actor.checkMonteeLaborieuse(); - await this.actor.reveActuelIncDec(reveCout); - // Le reste... - this.updateValuesDisplay(); - let coordTMR = this.actor.data.data.reve.tmrpos.coord; - let cellDescr = TMRUtility.getTMR(coordTMR); - await this.manageRencontre(coordTMR, cellDescr); - this.manageCaseHumide(cellDescr, coordTMR); - // Mise à jour du nb de cases de Fatigue - this.nbFatigue = this.actor.getTMRFatigue(); - this.actor.displayTMRQueueSouffleInformation(); - } - - /* -------------------------------------------- */ - static _computeEventCoord(origEvent) { + static _computeEventPos(origEvent) { let canvasRect = origEvent.target.getBoundingClientRect(); let x = origEvent.clientX - canvasRect.left; let y = origEvent.clientY - canvasRect.top; let cellx = Math.floor(x / tmrConstants.cellw); // [From 0 -> 12] y -= (cellx % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; let celly = Math.floor(y / tmrConstants.cellh); // [From 0 -> 14] - return { cellx, celly }; + return { x: cellx, y: celly }; } /* -------------------------------------------- */ - static _horsDePortee(pos, cellx, celly) { - return Math.abs(cellx - pos.x) > 1 - || Math.abs(celly - pos.y) > 1 - || (pos.y == 0 && celly > pos.y && cellx != pos.x && pos.x % 2 == 0) - || (celly == 0 && celly < pos.y && cellx != pos.x && pos.x % 2 == 1); + static _horsDePortee(origin, target) { + return Math.abs(target.x - origin.x) > 1 + || Math.abs(target.y - origin.y) > 1 + || (origin.y == 0 && target.y > origin.y && target.x != origin.x && origin.x % 2 == 0) + || (target.y == 0 && target.y < origin.y && target.x != origin.x && origin.x % 2 == 1); } - /* -------------------------------------------- */ - _tokenRencontre(rencontre) { - let sprite = new PIXI.Graphics(); - sprite.beginFill(0x767610, 0.6); - sprite.drawCircle(0, 0, 6); - sprite.endFill(); - sprite.decallage = { - x: (tmrConstants.cellw / 2) - 16, - y: 16 - (tmrConstants.cellh / 2) - }; - return { sprite: sprite, rencontre: rencontre, coordTMR: () => rencontre.coord }; - } - - /* -------------------------------------------- */ - _tokenTrouNoir(coord) { - let sprite = new PIXI.Graphics(); - sprite.beginFill(0x050505, 0.8); - sprite.drawCircle(0, 0, (tmrConstants.cellw / 2) - 2); - sprite.endFill(); - sprite.decallage = { - x: 0, - y: 2 - } - return { sprite: sprite, coordTMR: () => coord } - } - - /* -------------------------------------------- */ - _tokenDebordement(coord) { - let sprite = new PIXI.Graphics(); - sprite.beginFill(0x0101FE, 0.3); - sprite.drawCircle(0, 0, (tmrConstants.cellw / 2) - 2); - sprite.endFill(); - sprite.decallage = { - x: 0, - y: 2 - } - return { sprite: sprite, coordTMR: () => coord } - } - - /* -------------------------------------------- */ - _tokenMaitrisee(coord) { - let sprite = new PIXI.Graphics(); - sprite.beginFill(0x1010F0, 0.8); - sprite.drawCircle(0, 0, 6); - sprite.endFill(); - sprite.decallage = { - x: 16 - (tmrConstants.cellw / 2), - y: 16 - (tmrConstants.cellh / 2) - } - return { sprite: sprite, coordTMR: () => coord } - } - - /* -------------------------------------------- */ - _tokenTerreAttache(coord) { - let sprite = new PIXI.Graphics(); - sprite.beginFill(0x10F010, 0.8); - sprite.drawCircle(0, 0, 6); - sprite.endFill(); - sprite.decallage = { - x: 16 - (tmrConstants.cellw / 2), - y: 16 - (tmrConstants.cellh / 2) - } - return { sprite: sprite, coordTMR: () => coord } - } - - /* -------------------------------------------- */ - _tokenSortEnReserve(sort) { - let sprite = new PIXI.Graphics(); - sprite.beginFill(0x101010, 0.8); - sprite.drawCircle(0, 0, 6); - sprite.endFill(); - sprite.decallage = { - x: 16 - (tmrConstants.cellw / 2), - y: 16 - (tmrConstants.cellh / 2) - } - return { sprite: sprite, sort: sort, coordTMR: () => sort.coord } - } - - /* -------------------------------------------- */ - _tokenDemiReve() { - let texture = PIXI.utils.TextureCache['demi-reve']; - let sprite = new PIXI.Sprite(texture); - sprite.width = tmrConstants.cellw * 0.7; - sprite.height = tmrConstants.cellh * 0.7; - sprite.anchor.set(0.5); - sprite.tint = 0x00FFEE; - return { sprite: sprite, actor: this.actor, coordTMR: () => this.actor.data.data.reve.tmrpos.coord } - } - - /* -------------------------------------------- */ - _addDemiReve() { - this.demiReve = this._tokenDemiReve(); - this._setTokenPosition(this.demiReve); - this.pixiApp.stage.addChild(this.demiReve.sprite); - } - - /* -------------------------------------------- */ - _updateDemiReve(myself) { - myself._setTokenPosition(myself.demiReve); - } /* -------------------------------------------- */ /** Retourne les coordonnées x, h, w, h du rectangle d'une case donnée */ _getCaseRectangleCoord(coord) { - let coordXY = TMRUtility.convertToCellCoord(coord); - let decallagePairImpair = (coordXY.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; - let x = tmrConstants.gridx + (coordXY.x * tmrConstants.cellw) - (tmrConstants.cellw / 2); - let y = tmrConstants.gridy + (coordXY.y * tmrConstants.cellh) - (tmrConstants.cellh / 2) + decallagePairImpair; - return { x: x, y: y, w: tmrConstants.cellw, h: tmrConstants.cellh } + return this.pixiTMR.getCaseRectangle(TMRUtility.convertToCellPos(coord)); } /* -------------------------------------------- */ _setTokenPosition(token) { - let coordXY = TMRUtility.convertToCellCoord(token.coordTMR()); - let decallagePairImpair = (coordXY.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; - let dx = (token.sprite.decallage == undefined) ? 0 : token.sprite.decallage.x; - let dy = (token.sprite.decallage == undefined) ? 0 : token.sprite.decallage.y; - token.sprite.x = tmrConstants.gridx + (coordXY.x * tmrConstants.cellw) + dx; - token.sprite.y = tmrConstants.gridy + (coordXY.y * tmrConstants.cellh) + dy + decallagePairImpair; + this.pixiTMR.setPosition(token.sprite, TMRUtility.convertToCellPos(token.coordTMR())); } /* -------------------------------------------- */ @@ -845,10 +832,9 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ _trackToken(token) { - this.allTokens.push(token) + this.allTokens.push(token); this._setTokenPosition(token); - this.pixiApp.stage.addChild(token.sprite); } - } + diff --git a/module/rdd-tmr-rencontre-dialog.js b/module/rdd-tmr-rencontre-dialog.js index 5b432fda..4c0b1fa8 100644 --- a/module/rdd-tmr-rencontre-dialog.js +++ b/module/rdd-tmr-rencontre-dialog.js @@ -1,22 +1,22 @@ /* -------------------------------------------- */ export class RdDTMRRencontreDialog extends Dialog { - + /* -------------------------------------------- */ - constructor(html, tmrApp, rencontre) { + constructor(html, tmrApp, rencontre, postRencontre) { const dialogConf = { title: "Rencontre en TMR!", content: "Vous recontrez un " + rencontre.name + " de force " + rencontre.force + "
    ", buttons: { - derober: { icon: '', label: "Se dérober", callback: () => { this.toClose = true; this.tmrApp.derober() } }, - refouler: { icon: '', label: "Refouler", callback: () => { this.toClose = true; this.tmrApp.refouler() } }, - maitiser: { icon: '', label: "Maîtriser", callback: () => { this.toClose = true; this.tmrApp.maitriser() } } + derober: { icon: '', label: "Se dérober", callback: () => { this.onButtonFuir(() => tmrApp.derober()); } }, + refouler: { icon: '', label: "Refouler", callback: () => this.onButtonAction(() => tmrApp.refouler()) }, + maitiser: { icon: '', label: "Maîtriser", callback: () => this.onButtonAction(() => tmrApp.maitriserRencontre()) } }, default: "derober" - } + }; if (rencontre.ignorer) { - dialogConf.buttons.ignorer = { icon: '', label: "Ignorer", callback: () => { this.toClose = true; this.tmrApp.ignorerRencontre() }}; - } - + dialogConf.buttons.ignorer = { icon: '', label: "Ignorer", callback: () => this.onButtonAction(() => tmrApp.ignorerRencontre()) } + }; + const dialogOptions = { classes: ["tmrrencdialog"], width: 320, height: 240, @@ -26,13 +26,25 @@ export class RdDTMRRencontreDialog extends Dialog { this.toClose = false; this.rencontreData = duplicate(rencontre); + this.postRencontre = postRencontre; this.tmrApp = tmrApp; this.tmrApp.minimize(); } + + async onButtonAction(action) { + this.toClose = true; + await action(); + this.postRencontre(); + } + async onButtonFuir(action) { + this.toClose = true; + await action(); + } + /* -------------------------------------------- */ close() { - if ( this.toClose ) { + if (this.toClose) { this.tmrApp.maximize(); return super.close(); } diff --git a/module/rdd-utility.js b/module/rdd-utility.js index 0a319a64..01b8fc3c 100644 --- a/module/rdd-utility.js +++ b/module/rdd-utility.js @@ -7,6 +7,8 @@ import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemArme } from "./item-arme.js"; import { RdDItemCompetence } from "./item-competence.js"; +import { Misc } from "./misc.js"; +import { Grammar } from "./grammar.js"; /* -------------------------------------------- */ const categorieCompetences = { @@ -95,7 +97,6 @@ function _buildAllSegmentsFatigue(max) { ligneFatigue[caseIncrementee + 6]++; ligneFatigue.fatigueMax = 2 * (i + 1); fatigue[i + 1] = ligneFatigue; - } return fatigue; } @@ -128,18 +129,6 @@ const fatigueMarche = { "tresdifficile": { "4": 4, "6": 6 } } -/* -------------------------------------------- */ -/* Static tables for commands /table */ -const table2func = { - "rdd": { descr: "rdd: Ouvre la table de résolution", func: RdDRollResolutionTable.open }, - "queues": { descr: "queues: Tire une queue de Dragon", func: RdDRollTables.getQueue }, - "ombre": { descr: "ombre: Tire une Ombre de Dragon", func: RdDRollTables.getOmbre }, - "tetehr": { descr: "tetehr: Tire une Tête de Dragon pour Hauts Revants", fund: RdDRollTables.getTeteHR }, - "tete": { descr: "tete: Tire une Tête de Dragon", func: RdDRollTables.getTete }, - "souffle": { descr: "souffle: Tire un Souffle de Dragon", func: RdDRollTables.getSouffle }, - "tarot": { descr: "tarot: Tire une carte de Tarot Dracnique", func: RdDRollTables.getTarot } -}; - /* -------------------------------------------- */ const definitionsBlessures = [ { type: "legere", facteur: 2 }, @@ -265,6 +254,11 @@ export class RdDUtility { 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html' ]; + Handlebars.registerHelper('upperFirst', str=> Misc.upperFirst(str ?? 'Null')); + Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? 'NULL' ); + Handlebars.registerHelper('le', str => Grammar.articleDetermine(str) ); + Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str) ); + return loadTemplates(templatePaths); } @@ -320,6 +314,7 @@ export class RdDUtility { data.data.chants = this.checkNull(data.itemsByType['chant']); data.data.danses = this.checkNull(data.itemsByType['danse']); data.data.musiques = this.checkNull(data.itemsByType['musique']); + data.data.oeuvres = this.checkNull(data.itemsByType['oeuvre']); data.data.jeux = this.checkNull(data.itemsByType['jeu']); data.data.recettescuisine = this.checkNull(data.itemsByType['recettecuisine']); data.data.recettesAlchimiques = this.checkNull(data.itemsByType['recettealchimique']); @@ -584,18 +579,23 @@ export class RdDUtility { } /* -------------------------------------------- */ - static getLocalisation() { - // TODO: bouger dans une RollTable du compendium et chercher dans les RoolTable puis compendium pour permettre le changement? + static getLocalisation( type = 'personnage' ) { let result = new Roll("1d20").roll().total; let txt = "" - if (result <= 3) txt = "Jambe, genou, pied, jarret"; - else if (result <= 7) txt = "Hanche, cuisse, fesse"; - else if (result <= 9) txt = "Ventre, reins"; - else if (result <= 12) txt = "Poitrine, dos"; - else if (result <= 14) txt = "Avant-bras, main, coude"; - else if (result <= 18) txt = "Epaule, bras, omoplate"; - else if (result == 19) txt = "Tête"; - else if (result == 20) txt = "Tête (visage)"; + if ( type == 'personnage') { + if (result <= 3) txt = "Jambe, genou, pied, jarret"; + else if (result <= 7) txt = "Hanche, cuisse, fesse"; + else if (result <= 9) txt = "Ventre, reins"; + else if (result <= 12) txt = "Poitrine, dos"; + else if (result <= 14) txt = "Avant-bras, main, coude"; + else if (result <= 18) txt = "Epaule, bras, omoplate"; + else if (result == 19) txt = "Tête"; + else if (result == 20) txt = "Tête (visage)"; + } else { + if (result <= 7) txt = "Jambes/Pattes"; + else if (result <= 18) txt = "Corps"; + else if (result <= 20) txt = "Tête"; + } return { result: result, label: txt }; } @@ -1024,5 +1024,22 @@ export class RdDUtility { ui.notifications.warn("Pas d'heure de naissance selectionnée") } } + + /*-------------------------------------------- */ + static checkThanatosXP(compName) { + if ( compName.includes('Thanatos') ) { + let message = "Vous avez mis des points d'Expérience dans la Voie de Thanatos !
    Vous devez réduire manuellement d'un même montant d'XP une autre compétence Draconique."; + ChatMessage.create({ + whisper: ChatMessage.getWhisperRecipients(game.user.name), + content: message + }); + } + } + + /*-------------------------------------------- */ + static async onRenderChatMessage( app, html, msg ) { + // TODO + //console.log(app, html, msg); + } } diff --git a/module/rolldata-ajustements.js b/module/rolldata-ajustements.js index 0fd3b7fe..049b0972 100644 --- a/module/rolldata-ajustements.js +++ b/module/rolldata-ajustements.js @@ -94,10 +94,10 @@ export const referenceAjustements = { getDescr: (rollData, actor) => rollData.diviseurSignificative > 1 ? `Facteur significative ×${Misc.getFractionHtml(rollData.diviseurSignificative)}` : '' }, isEcaille: { - isVisible: (rollData, actor) => rollData.arme && rollData.arme.data.magique && Number(rollData.arme.data.ecaille_efficacite) > 0, - isUsed: (rollData, actor) => rollData.arme && rollData.arme.data.magique && Number(rollData.arme.data.ecaille_efficacite) > 0, + isVisible: (rollData, actor) => rollData.arme?.data.magique && Number(rollData.arme?.data.ecaille_efficacite) > 0, + isUsed: (rollData, actor) => rollData.arme?.data.magique && Number(rollData.arme?.data.ecaille_efficacite) > 0, getLabel: (rollData, actor) => "Ecaille d'Efficacité: ", - getValue: (rollData, actor) => (rollData.arme && rollData.arme.data.magique && Number(rollData.arme.data.ecaille_efficacite) > 0) ? rollData.arme.data.ecaille_efficacite : 0, + getValue: (rollData, actor) => (rollData.arme?.data.magique && Number(rollData.arme.data.ecaille_efficacite) > 0) ? rollData.arme.data.ecaille_efficacite : 0, }, finesse: { isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData), @@ -112,12 +112,12 @@ export const referenceAjustements = { getDescr: (rollData, actor) => RdDBonus.find(actor.getSurprise()).descr }, bonusCase: { - isUsed: (rollData, actor) => rollData.selectedSort && rollData.coord, - getDescr: (rollData, actor) => rollData.selectedSort && rollData.coord ? `Bonus de case: ${RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.coord)}%` : '' + isUsed: (rollData, actor) => rollData.selectedSort && rollData.tmr.coord, + getDescr: (rollData, actor) => rollData.selectedSort && rollData.tmr.coord ? `Bonus de case: ${RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.tmr.coord)}%` : '' }, rencontreTMR: { - isVisible: (rollData, actor) => rollData.tmr && rollData.rencontre.name, - isUsed: (rollData, actor) => rollData.tmr && rollData.rencontre.name, + isVisible: (rollData, actor) => rollData.tmr && rollData.rencontre?.name, + isUsed: (rollData, actor) => rollData.tmr && rollData.rencontre?.name, getLabel: (rollData, actor) => rollData.rencontre?.name, getValue: (rollData, actor) => - (rollData.rencontre?.force ?? 0) } diff --git a/module/tmr-rencontres.js b/module/tmr-rencontres.js index da24a414..a3883396 100644 --- a/module/tmr-rencontres.js +++ b/module/tmr-rencontres.js @@ -84,9 +84,9 @@ const typeRencontres = { }, changeur: { - msgSucces: (data) => `Le ${data.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[data.tmr.type]} de votre choix en échange de sa liberté.`, + msgSucces: (data) => `Le ${data.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[data.tmr.type].name} de votre choix en échange de sa liberté.`, msgEchec: (data) => { - data.newTMR = TMRUtility.getTMRAleatoire(data.tmr.type); + data.newTMR = TMRUtility.getTMRAleatoire(it => it.type = data.tmr.type); return `Le ${data.rencontre.name} vous embobine avec des promesses, et vous transporte en ${data.newTMR.label} sans attendre votre avis.`; }, postSucces: (tmrDialog, data) => { @@ -230,7 +230,7 @@ const typeRencontres = { msgSucces: (data) => `A tout seigneur, tout honneur, vous faites face à un ${data.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${data.rencontre.force} points de rêve`, msgEchec: (data) => `A tout seigneur, tout honneur, vous faites face à un ${data.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${data.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`, postSucces: (tmrDialog, data) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, data), - postEchec: (tmrDialog, data) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, data), + postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, data), poesieSucces: { reference: "Rêve de Dragon, Denis Gerfaud", extrait: `Le monde est Rêve de Dragons, mais nous ne savons @@ -248,44 +248,44 @@ const typeRencontres = { /* -------------------------------------------- */ const mauvaisesRencontres = [ - { code: "mangeur1d6", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6", refoulement: 2, isMauvaise: true }, + { code: "mangeur", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6", refoulement: 2, isMauvaise: true }, { code: "mangeur2d6", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "2d6", refoulement: 2, isMauvaise: true }, - { code: "reflet2d6+4", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true }, - { code: "tbblanc2d6+4", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true }, - { code: "tbnoir2d8+4", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8+4", refoulement: 2, isPersistant: true, isMauvaise: true }, - { code: "passfou2d8", name: "Passeur fou", type: "passeurfou", genre: "m", force: "2d8", refoulement: 2, isMauvaise: true }, - { code: "tbrouge2d8", name: "Tourbillon rouge", type: "tbrouge", genre: "m", force: "2d8", refoulement: 3, isPersistant: true, isMauvaise: true } + { code: "reflet+4", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true }, + { code: "tbblanc+4", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6+4", refoulement: 2, isPersistant: true, isMauvaise: true }, + { code: "tbnoir+4", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8+4", refoulement: 2, isPersistant: true, isMauvaise: true }, + { code: "passfou", name: "Passeur fou", type: "passeurfou", genre: "m", force: "2d8", refoulement: 2, isMauvaise: true }, + { code: "tbrouge", name: "Tourbillon rouge", type: "tbrouge", genre: "m", force: "2d8", refoulement: 3, isPersistant: true, isMauvaise: true } ] /* -------------------------------------------- */ const rencontresStandard = [ - { code: "messager2d4", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d4", ignorer: true }, - { code: "passeur2d4", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d4", ignorer: true }, - { code: "fleur1d6", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "1d6", ignorer: true }, - { code: "mangeur1d6", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6" }, - { code: "changeur2d6", name: "Changeur de Rêve", type: "changeur", genre: "m", force: "2d6" }, - { code: "briseur2d6", name: "Briseur de Rêve", type: "briseur", genre: "m", force: "2d6", quitterTMR: true }, - { code: "reflet1d6", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6", isPersistant: true }, - { code: "tbblanc2d6", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6", isPersistant: true }, - { code: "tbnoir2d8", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8", isPersistant: true }, - { code: "rdd1ddr+7", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1ddr + 7", refoulement: 2, quitterTMR: true } + { code: "messager", name: "Messager des Rêves", type: "messager", genre: "m", force: "2d4", ignorer: true }, + { code: "passeur", name: "Passeur des Rêves", type: "passeur", genre: "m", force: "2d4", ignorer: true }, + { code: "fleur", name: "Fleur des Rêves", type: "fleur", genre: "f", force: "1d6", ignorer: true }, + { code: "mangeur", name: "Mangeur de Rêve", type: "mangeur", genre: "m", force: "1d6" }, + { code: "changeur", name: "Changeur de Rêve", type: "changeur", genre: "m", force: "2d6" }, + { code: "briseur", name: "Briseur de Rêve", type: "briseur", genre: "m", force: "2d6", quitterTMR: true }, + { code: "reflet", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6", isPersistant: true }, + { code: "tbblanc", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6", isPersistant: true }, + { code: "tbnoir", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8", isPersistant: true }, + { code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1ddr + 7", refoulement: 2, quitterTMR: true } ]; const tableRencontres = { - cite: [{ code: 'messager2d4', range: [1, 25] }, { code: 'passeur2d4', range: [26, 50] }, { code: 'fleur1d6', range: [51, 65] }, { code: 'mangeur1d6', range: [66, 70] }, { code: 'changeur2d6', range: [71, 80] }, { code: 'briseur2d6', range: [81, 85] }, { code: 'reflet2d6', range: [86, 90] }, { code: 'tbblanc2d6', range: [91, 94] }, { code: 'tbnoir2d8', range: [95, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - sanctuaire: [{ code: 'messager2d4', range: [1, 25] }, { code: 'passeur2d4', range: [26, 50] }, { code: 'fleur1d6', range: [51, 65] }, { code: 'mangeur1d6', range: [66, 70] }, { code: 'changeur2d6', range: [71, 80] }, { code: 'briseur2d6', range: [81, 85] }, { code: 'reflet2d6', range: [86, 90] }, { code: 'tbblanc2d6', range: [91, 94] }, { code: 'tbnoir2d8', range: [95, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - plaines: [{ code: 'messager2d4', range: [1, 20] }, { code: 'passeur2d4', range: [21, 40] }, { code: 'fleur1d6', range: [41, 55] }, { code: 'mangeur1d6', range: [56, 60] }, { code: 'changeur2d6', range: [61, 75] }, { code: 'briseur2d6', range: [76, 82] }, { code: 'reflet2d6', range: [83, 88] }, { code: 'tbblanc2d6', range: [89, 93] }, { code: 'tbnoir2d8', range: [94, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - pont: [{ code: 'messager2d4', range: [1, 20] }, { code: 'passeur2d4', range: [21, 40] }, { code: 'fleur1d6', range: [41, 55] }, { code: 'mangeur1d6', range: [56, 60] }, { code: 'changeur2d6', range: [61, 75] }, { code: 'briseur2d6', range: [76, 82] }, { code: 'reflet2d6', range: [83, 88] }, { code: 'tbblanc2d6', range: [89, 93] }, { code: 'tbnoir2d8', range: [94, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - collines: [{ code: 'messager2d4', range: [1, 15] }, { code: 'passeur2d4', range: [16, 30] }, { code: 'fleur1d6', range: [31, 42] }, { code: 'mangeur1d6', range: [43, 54] }, { code: 'changeur2d6', range: [55, 69] }, { code: 'briseur2d6', range: [70, 82] }, { code: 'reflet2d6', range: [83, 88] }, { code: 'tbblanc2d6', range: [89, 93] }, { code: 'tbnoir2d8', range: [94, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - foret: [{ code: 'messager2d4', range: [1, 15] }, { code: 'passeur2d4', range: [16, 30] }, { code: 'fleur1d6', range: [31, 42] }, { code: 'mangeur1d6', range: [43, 54] }, { code: 'changeur2d6', range: [55, 69] }, { code: 'briseur2d6', range: [70, 82] }, { code: 'reflet2d6', range: [83, 88] }, { code: 'tbblanc2d6', range: [89, 93] }, { code: 'tbnoir2d8', range: [94, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - monts: [{ code: 'messager2d4', range: [1, 10] }, { code: 'passeur2d4', range: [11, 20] }, { code: 'fleur1d6', range: [21, 26] }, { code: 'mangeur1d6', range: [27, 44] }, { code: 'changeur2d6', range: [45, 59] }, { code: 'briseur2d6', range: [60, 75] }, { code: 'reflet2d6', range: [76, 85] }, { code: 'tbblanc2d6', range: [86, 92] }, { code: 'tbnoir2d8', range: [93, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - desert: [{ code: 'messager2d4', range: [1, 10] }, { code: 'passeur2d4', range: [11, 20] }, { code: 'fleur1d6', range: [21, 26] }, { code: 'mangeur1d6', range: [27, 44] }, { code: 'changeur2d6', range: [45, 59] }, { code: 'briseur2d6', range: [60, 75] }, { code: 'reflet2d6', range: [76, 85] }, { code: 'tbblanc2d6', range: [86, 92] }, { code: 'tbnoir2d8', range: [93, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - fleuve: [{ code: 'messager2d4', range: [1, 5] }, { code: 'passeur2d4', range: [6, 10] }, { code: 'fleur1d6', range: [11, 13] }, { code: 'mangeur1d6', range: [14, 37] }, { code: 'changeur2d6', range: [38, 49] }, { code: 'briseur2d6', range: [50, 65] }, { code: 'reflet2d6', range: [66, 79] }, { code: 'tbblanc2d6', range: [80, 89] }, { code: 'tbnoir2d8', range: [90, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - lac: [{ code: 'messager2d4', range: [1, 5] }, { code: 'passeur2d4', range: [6, 10] }, { code: 'fleur1d6', range: [11, 13] }, { code: 'mangeur1d6', range: [14, 37] }, { code: 'changeur2d6', range: [38, 49] }, { code: 'briseur2d6', range: [50, 65] }, { code: 'reflet2d6', range: [66, 79] }, { code: 'tbblanc2d6', range: [80, 89] }, { code: 'tbnoir2d8', range: [90, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - marais: [{ code: 'messager2d4', range: [1, 2] }, { code: 'passeur2d4', range: [3, 4] }, { code: 'fleur1d6', range: [5, 5] }, { code: 'mangeur1d6', range: [6, 29] }, { code: 'changeur2d6', range: [30, 39] }, { code: 'briseur2d6', range: [40, 60] }, { code: 'reflet2d6', range: [61, 75] }, { code: 'tbblanc2d6', range: [76, 86] }, { code: 'tbnoir2d8', range: [87, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - gouffre: [{ code: 'messager2d4', range: [1, 2] }, { code: 'passeur2d4', range: [3, 4] }, { code: 'fleur1d6', range: [5, 5] }, { code: 'mangeur1d6', range: [6, 29] }, { code: 'changeur2d6', range: [30, 39] }, { code: 'briseur2d6', range: [40, 60] }, { code: 'reflet2d6', range: [61, 75] }, { code: 'tbblanc2d6', range: [76, 86] }, { code: 'tbnoir2d8', range: [87, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - necropole: [{ code: 'mangeur1d6', range: [1, 20] }, { code: 'changeur2d6', range: [21, 30] }, { code: 'briseur2d6', range: [31, 50] }, { code: 'reflet2d6', range: [51, 65] }, { code: 'tbblanc2d6', range: [66, 80] }, { code: 'tbnoir2d8', range: [81, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }], - desolation: [{ code: 'mangeur1d6', range: [1, 20] }, { code: 'changeur2d6', range: [21, 30] }, { code: 'briseur2d6', range: [31, 50] }, { code: 'reflet2d6', range: [51, 65] }, { code: 'tbblanc2d6', range: [66, 80] }, { code: 'tbnoir2d8', range: [81, 97] }, { code: 'rdd1ddr+7', range: [98, 100] }] + cite: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }], + sanctuaire: [{ code: 'messager', range: [1, 25] }, { code: 'passeur', range: [26, 50] }, { code: 'fleur', range: [51, 65] }, { code: 'mangeur', range: [66, 70] }, { code: 'changeur', range: [71, 80] }, { code: 'briseur', range: [81, 85] }, { code: 'reflet', range: [86, 90] }, { code: 'tbblanc', range: [91, 94] }, { code: 'tbnoir', range: [95, 97] }, { code: 'rdd', range: [98, 100] }], + plaines: [{ code: 'messager', range: [1, 20] }, { code: 'passeur', range: [21, 40] }, { code: 'fleur', range: [41, 55] }, { code: 'mangeur', range: [56, 60] }, { code: 'changeur', range: [61, 75] }, { code: 'briseur', range: [76, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }], + pont: [{ code: 'messager', range: [1, 20] }, { code: 'passeur', range: [21, 40] }, { code: 'fleur', range: [41, 55] }, { code: 'mangeur', range: [56, 60] }, { code: 'changeur', range: [61, 75] }, { code: 'briseur', range: [76, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }], + collines: [{ code: 'messager', range: [1, 15] }, { code: 'passeur', range: [16, 30] }, { code: 'fleur', range: [31, 42] }, { code: 'mangeur', range: [43, 54] }, { code: 'changeur', range: [55, 69] }, { code: 'briseur', range: [70, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }], + foret: [{ code: 'messager', range: [1, 15] }, { code: 'passeur', range: [16, 30] }, { code: 'fleur', range: [31, 42] }, { code: 'mangeur', range: [43, 54] }, { code: 'changeur', range: [55, 69] }, { code: 'briseur', range: [70, 82] }, { code: 'reflet', range: [83, 88] }, { code: 'tbblanc', range: [89, 93] }, { code: 'tbnoir', range: [94, 97] }, { code: 'rdd', range: [98, 100] }], + monts: [{ code: 'messager', range: [1, 10] }, { code: 'passeur', range: [11, 20] }, { code: 'fleur', range: [21, 26] }, { code: 'mangeur', range: [27, 44] }, { code: 'changeur', range: [45, 59] }, { code: 'briseur', range: [60, 75] }, { code: 'reflet', range: [76, 85] }, { code: 'tbblanc', range: [86, 92] }, { code: 'tbnoir', range: [93, 97] }, { code: 'rdd', range: [98, 100] }], + desert: [{ code: 'messager', range: [1, 10] }, { code: 'passeur', range: [11, 20] }, { code: 'fleur', range: [21, 26] }, { code: 'mangeur', range: [27, 44] }, { code: 'changeur', range: [45, 59] }, { code: 'briseur', range: [60, 75] }, { code: 'reflet', range: [76, 85] }, { code: 'tbblanc', range: [86, 92] }, { code: 'tbnoir', range: [93, 97] }, { code: 'rdd', range: [98, 100] }], + fleuve: [{ code: 'messager', range: [1, 5] }, { code: 'passeur', range: [6, 10] }, { code: 'fleur', range: [11, 13] }, { code: 'mangeur', range: [14, 37] }, { code: 'changeur', range: [38, 49] }, { code: 'briseur', range: [50, 65] }, { code: 'reflet', range: [66, 79] }, { code: 'tbblanc', range: [80, 89] }, { code: 'tbnoir', range: [90, 97] }, { code: 'rdd', range: [98, 100] }], + lac: [{ code: 'messager', range: [1, 5] }, { code: 'passeur', range: [6, 10] }, { code: 'fleur', range: [11, 13] }, { code: 'mangeur', range: [14, 37] }, { code: 'changeur', range: [38, 49] }, { code: 'briseur', range: [50, 65] }, { code: 'reflet', range: [66, 79] }, { code: 'tbblanc', range: [80, 89] }, { code: 'tbnoir', range: [90, 97] }, { code: 'rdd', range: [98, 100] }], + marais: [{ code: 'messager', range: [1, 2] }, { code: 'passeur', range: [3, 4] }, { code: 'fleur', range: [5, 5] }, { code: 'mangeur', range: [6, 29] }, { code: 'changeur', range: [30, 39] }, { code: 'briseur', range: [40, 60] }, { code: 'reflet', range: [61, 75] }, { code: 'tbblanc', range: [76, 86] }, { code: 'tbnoir', range: [87, 97] }, { code: 'rdd', range: [98, 100] }], + gouffre: [{ code: 'messager', range: [1, 2] }, { code: 'passeur', range: [3, 4] }, { code: 'fleur', range: [5, 5] }, { code: 'mangeur', range: [6, 29] }, { code: 'changeur', range: [30, 39] }, { code: 'briseur', range: [40, 60] }, { code: 'reflet', range: [61, 75] }, { code: 'tbblanc', range: [76, 86] }, { code: 'tbnoir', range: [87, 97] }, { code: 'rdd', range: [98, 100] }], + necropole: [{ code: 'mangeur', range: [1, 20] }, { code: 'changeur', range: [21, 30] }, { code: 'briseur', range: [31, 50] }, { code: 'reflet', range: [51, 65] }, { code: 'tbblanc', range: [66, 80] }, { code: 'tbnoir', range: [81, 97] }, { code: 'rdd', range: [98, 100] }], + desolation: [{ code: 'mangeur', range: [1, 20] }, { code: 'changeur', range: [21, 30] }, { code: 'briseur', range: [31, 50] }, { code: 'reflet', range: [51, 65] }, { code: 'tbblanc', range: [66, 80] }, { code: 'tbnoir', range: [81, 97] }, { code: 'rdd', range: [98, 100] }] } @@ -378,7 +378,8 @@ export class TMRRencontres { /* -------------------------------------------- */ static async evaluerForceRencontre(rencontre) { if (TMRRencontres.isReveDeDragon(rencontre)) { - rencontre.force = await DeDraconique.ddr("selfroll").total + 7; + const ddr = await DeDraconique.ddr("selfroll") + rencontre.force = 7 + ddr.total; } else { rencontre.force = new Roll(rencontre.force).evaluate().total; @@ -471,14 +472,14 @@ export class TMRRencontres { } static async onPostSuccessReveDeDragon(tmrDialog, data) { - await data.actor.appliquerReveDeDragon(data.rolled, data.rencontre.force); if (data.rolled.isPart) { await data.actor.appliquerExperience(data.rolled, 'reve', data.competence); } + await data.actor.resultCombatReveDeDragon(data); } - + static async onPostEchecReveDeDragon(tmrDialog, data) { - await data.actor.appliquerReveDeDragon(data.rolled, data.rencontre.force); + await data.actor.resultCombatReveDeDragon(data); tmrDialog.close(); } } diff --git a/module/tmr-utility.js b/module/tmr-utility.js index b423edc8..a2d2d013 100644 --- a/module/tmr-utility.js +++ b/module/tmr-utility.js @@ -1,243 +1,244 @@ import { DeDraconique } from "./de-draconique.js"; import { TMRRencontres } from "./tmr-rencontres.js"; import { Grammar } from "./grammar.js"; +import { Misc } from "./misc.js"; /* -------------------------------------------- */ -const TMRMapping = { - A1: { type: "cite", label: "Cité Vide"}, - B1: { type: "plaines", label: "Plaines d’Assorh"}, - C1: { type: "necropole", label: "Nécropole de Kroak"}, - D1: { type: "fleuve", label: "Fleuve"}, - E1: { type: "monts", label: "Monts de Kanaï"}, - F1: { type: "cite", label: "Cité Glauque"}, - G1: { type: "desolation", label: "Désolation de Demain"}, - H1: { type: "lac", label: "Lac d’Anticalme"}, - I1: { type: "plaines", label: "Plaines Grises"}, - J1: { type: "monts", label: "Monts Fainéants"}, - K1: { type: "cite", label: "Cité d’Onkause"}, - L1: { type: "fleuve", label: "Fleuve"}, - M1: { type: "cite", label: "Cité Jalouse"}, - - A2: { type: "desert", label: "Désert de Mieux"}, - B2: { type: "collines", label: "Collines de Dawell"}, - C2: { type: "marais", label: "Marais Glignants"}, - D2: { type: "cite", label: "Cité de Frost"}, - E2: { type: "plaines", label: "Plaines de Fiask"}, - F2: { type: "lac", label: "Lac de Misère"}, - G2: { type: "marais", label: "Marais Nuisants"}, - H2: { type: "collines", label: "Collines de Parta"}, - I2: { type: "foret", label: "Forêt Fade"}, - J2: { type: "desert", label: "Désert de Poly"}, - K2: { type: "foret", label: "Forêt Tamée"}, - L2: { type: "fleuve", label: "Fleuve"}, - M2: { type: "necropole", label: "Nécropole de Logos"}, +const TMRMapping = { + A1: { type: "cite", label: "Cité Vide" }, + B1: { type: "plaines", label: "Plaines d’Assorh" }, + C1: { type: "necropole", label: "Nécropole de Kroak" }, + D1: { type: "fleuve", label: "Fleuve de l'Oubli" }, + E1: { type: "monts", label: "Monts de Kanaï" }, + F1: { type: "cite", label: "Cité Glauque" }, + G1: { type: "desolation", label: "Désolation de Demain" }, + H1: { type: "lac", label: "Lac d’Anticalme" }, + I1: { type: "plaines", label: "Plaines Grises" }, + J1: { type: "monts", label: "Monts Fainéants" }, + K1: { type: "cite", label: "Cité d’Onkause" }, + L1: { type: "fleuve", label: "Fleuve de l'Oubli" }, + M1: { type: "cite", label: "Cité Jalouse" }, - A3: { type: "desolation", label: "Désolation de Demain"}, - B3: { type: "plaines", label: "Plaines de Rubéga"}, - C3: { type: "fleuve", label: "Fleuve"}, - D3: { type: "gouffre", label: "Gouffre d’Oki"}, - E3: { type: "foret", label: "Forêt d’Estoubh"}, - F3: { type: "fleuve", label: "Fleuve"}, - G3: { type: "gouffre", label: "Gouffre de Sun"}, - H3: { type: "foret", label: "Forêt de Ganna"}, - I3: { type: "monts", label: "Monts Grinçants"}, - J3: { type: "cite", label: "Cité Venin"}, - K3: { type: "plaines", label: "Plaines de Dois"}, - L3: { type: "lac", label: "Lac Laineux"}, - M3: { type: "monts", label: "Monts de Vdah"}, + A2: { type: "desert", label: "Désert de Mieux" }, + B2: { type: "collines", label: "Collines de Dawell" }, + C2: { type: "marais", label: "Marais Glignants" }, + D2: { type: "cite", label: "Cité de Frost" }, + E2: { type: "plaines", label: "Plaines de Fiask" }, + F2: { type: "lac", label: "Lac de Misère" }, + G2: { type: "marais", label: "Marais Nuisants" }, + H2: { type: "collines", label: "Collines de Parta" }, + I2: { type: "foret", label: "Forêt Fade" }, + J2: { type: "desert", label: "Désert de Poly" }, + K2: { type: "foret", label: "Forêt Tamée" }, + L2: { type: "fleuve", label: "Fleuve de l'Oubli" }, + M2: { type: "necropole", label: "Nécropole de Logos" }, - A4: { type: "foret", label: "Forêt de Falconax"}, - B4: { type: "monts", label: "Monts Crâneurs"}, - C4: { type: "pont", label: "Pont de Giolii"}, - D4: { type: "lac", label: "Lac de Foam"}, - E4: { type: "plaines", label: "Plaines d’Orti"}, - F4: { type: "fleuve", label: "Fleuve"}, - G4: { type: "sanctuaire", label: "Sanctuaire Blanc"}, - H4: { type: "plaines", label: "Plaines de Psark"}, - I4: { type: "plaines", label: "Plaines de Xiax"}, - J4: { type: "collines", label: "Collines d’Encre"}, - K4: { type: "pont", label: "Pont de Fah"}, - L4: { type: "sanctuaire", label: "Sanctuaire Mauve"}, - M4: { type: "gouffre", label: "Gouffre Grisant"}, + A3: { type: "desolation", label: "Désolation de Demain" }, + B3: { type: "plaines", label: "Plaines de Rubéga" }, + C3: { type: "fleuve", label: "Fleuve de l'Oubli" }, + D3: { type: "gouffre", label: "Gouffre d’Oki" }, + E3: { type: "foret", label: "Forêt d’Estoubh" }, + F3: { type: "fleuve", label: "Fleuve de l'Oubli" }, + G3: { type: "gouffre", label: "Gouffre de Sun" }, + H3: { type: "foret", label: "Forêt de Ganna" }, + I3: { type: "monts", label: "Monts Grinçants" }, + J3: { type: "cite", label: "Cité Venin" }, + K3: { type: "plaines", label: "Plaines de Dois" }, + L3: { type: "lac", label: "Lac Laineux" }, + M3: { type: "monts", label: "Monts de Vdah" }, - A5: { type: "plaines", label: "Plaines de Trilkh"}, - B5: { type: "collines", label: "Collines de Tanegy"}, - C5: { type: "marais", label: "Marais Flouants"}, - D5: { type: "fleuve", label: "Fleuve"}, - E5: { type: "monts", label: "Monts Brûlants"}, - F5: { type: "cite", label: "Cité de Panople"}, - G5: { type: "pont", label: "Pont d’Ik"}, - H5: { type: "desert", label: "Désert de Krane"}, - I5: { type: "desolation", label: "Désolation de Demain"}, - J5: { type: "marais", label: "Marais de Jab"}, - K5: { type: "fleuve", label: "Fleuve"}, - L5: { type: "collines", label: "Collines Suaves"}, - M5: { type: "cite", label: "Cité Rimarde"}, + A4: { type: "foret", label: "Forêt de Falconax" }, + B4: { type: "monts", label: "Monts Crâneurs" }, + C4: { type: "pont", label: "Pont de Giolii" }, + D4: { type: "lac", label: "Lac de Foam" }, + E4: { type: "plaines", label: "Plaines d’Orti" }, + F4: { type: "fleuve", label: "Fleuve de l'Oubli" }, + G4: { type: "sanctuaire", label: "Sanctuaire Blanc" }, + H4: { type: "plaines", label: "Plaines de Psark" }, + I4: { type: "plaines", label: "Plaines de Xiax" }, + J4: { type: "collines", label: "Collines d’Encre" }, + K4: { type: "pont", label: "Pont de Fah" }, + L4: { type: "sanctuaire", label: "Sanctuaire Mauve" }, + M4: { type: "gouffre", label: "Gouffre Grisant" }, - A6: { type: "necropole", label: "Nécropole de Zniak"}, - B6: { type: "foret", label: "Forêt de Bust"}, - C6: { type: "cite", label: "Cité Pavois"}, - D6: { type: "fleuve", label: "Fleuve"}, - E6: { type: "sanctuaire", label: "Sanctuaire de Plaine"}, - F6: { type: "fleuve", label: "Fleuve"}, - G6: { type: "marais", label: "Marais Glutants"}, - H6: { type: "monts", label: "Monts Gurdes"}, - I6: { type: "necropole", label: "Nécropole de Xotar"}, - J6: { type: "lac", label: "Lac d’Iaupe"}, - K6: { type: "desolation", label: "Désolation de Demain"}, - L6: { type: "foret", label: "Forêt Gueuse"}, - M6: { type: "desolation", label: "Désolation de Demain"}, + A5: { type: "plaines", label: "Plaines de Trilkh" }, + B5: { type: "collines", label: "Collines de Tanegy" }, + C5: { type: "marais", label: "Marais Flouants" }, + D5: { type: "fleuve", label: "Fleuve de l'Oubli" }, + E5: { type: "monts", label: "Monts Brûlants" }, + F5: { type: "cite", label: "Cité de Panople" }, + G5: { type: "pont", label: "Pont d’Ik" }, + H5: { type: "desert", label: "Désert de Krane" }, + I5: { type: "desolation", label: "Désolation de Demain" }, + J5: { type: "marais", label: "Marais de Jab" }, + K5: { type: "fleuve", label: "Fleuve de l'Oubli" }, + L5: { type: "collines", label: "Collines Suaves" }, + M5: { type: "cite", label: "Cité Rimarde" }, - A7: { type: "plaines", label: "Plaines de l’Arc"}, - B7: { type: "marais", label: "Marais Bluants"}, - C7: { type: "fleuve", label: "Fleuve"}, - D7: { type: "plaines", label: "Plaines d’A!a"}, - E7: { type: "foret", label: "Forêt de Glusks"}, - F7: { type: "fleuve", label: "Fleuve"}, - G7: { type: "cite", label: "Cité de Terwa"}, - H7: { type: "gouffre", label: "Gouffre de Kapfa"}, - I7: { type: "plaines", label: "Plaines de Troo"}, - J7: { type: "fleuve", label: "Fleuve"}, - K7: { type: "cite", label: "Cité de Kolix"}, - L7: { type: "gouffre", label: "Gouffre d’Episophe"}, - M7: { type: "desert", label: "Désert de Lave"}, + A6: { type: "necropole", label: "Nécropole de Zniak" }, + B6: { type: "foret", label: "Forêt de Bust" }, + C6: { type: "cite", label: "Cité Pavois" }, + D6: { type: "fleuve", label: "Fleuve de l'Oubli" }, + E6: { type: "sanctuaire", label: "Sanctuaire de Plaine" }, + F6: { type: "fleuve", label: "Fleuve de l'Oubli" }, + G6: { type: "marais", label: "Marais Glutants" }, + H6: { type: "monts", label: "Monts Gurdes" }, + I6: { type: "necropole", label: "Nécropole de Xotar" }, + J6: { type: "lac", label: "Lac d’Iaupe" }, + K6: { type: "desolation", label: "Désolation de Demain" }, + L6: { type: "foret", label: "Forêt Gueuse" }, + M6: { type: "desolation", label: "Désolation de Demain" }, - A8: { type: "gouffre", label: "Gouffre de Shok"}, - B8: { type: "fleuve", label: "Fleuve"}, - C8: { type: "foret", label: "Forêt Turmide"}, - D8: { type: "cite", label: "Cité d’Olak"}, - E8: { type: "plaines", label: "Plaines d’Iolise"}, - F8: { type: "lac", label: "Lac des Chats"}, - G8: { type: "plaines", label: "Plaines Sans Joie"}, - H8: { type: "foret", label: "Forêt d’Ourf"}, - I8: { type: "fleuve", label: "Fleuve"}, - J8: { type: "monts", label: "Monts Barask"}, - K8: { type: "desert", label: "Désert de Fumée"}, - L8: { type: "monts", label: "Monts Tavelés"}, - M8: { type: "plaines", label: "Plaines Lavées"}, + A7: { type: "plaines", label: "Plaines de l’Arc" }, + B7: { type: "marais", label: "Marais Bluants" }, + C7: { type: "fleuve", label: "Fleuve de l'Oubli" }, + D7: { type: "plaines", label: "Plaines d’A!a" }, + E7: { type: "foret", label: "Forêt de Glusks" }, + F7: { type: "fleuve", label: "Fleuve de l'Oubli" }, + G7: { type: "cite", label: "Cité de Terwa" }, + H7: { type: "gouffre", label: "Gouffre de Kapfa" }, + I7: { type: "plaines", label: "Plaines de Troo" }, + J7: { type: "fleuve", label: "Fleuve de l'Oubli" }, + K7: { type: "cite", label: "Cité de Kolix" }, + L7: { type: "gouffre", label: "Gouffre d’Episophe" }, + M7: { type: "desert", label: "Désert de Lave" }, - A9: { type: "collines", label: "Collines de Korrex"}, - B9: { type: "lac", label: "Lac de Lucre"}, - C9: { type: "monts", label: "Monts Tuméfiés"}, - D9: { type: "pont", label: "Pont d’Orx"}, - E9: { type: "fleuve", label: "Fleuve"}, - F9: { type: "plaines", label: "Plaines de Foe"}, - G9: { type: "desolation", label: "Désolation de Demain"}, - H9: { type: "collines", label: "Collines de Noirseul"}, - I9: { type: "fleuve", label: "Fleuve"}, - J9: { type: "marais", label: "Marais Gronchants"}, - K9: { type: "sanctuaire", label: "Sanctuaire Noir"}, - L9: { type: "collines", label: "Collines Cornues"}, - M9: { type: "necropole", label: "Nécropole de Zonar"}, + A8: { type: "gouffre", label: "Gouffre de Shok" }, + B8: { type: "fleuve", label: "Fleuve de l'Oubli" }, + C8: { type: "foret", label: "Forêt Turmide" }, + D8: { type: "cite", label: "Cité d’Olak" }, + E8: { type: "plaines", label: "Plaines d’Iolise" }, + F8: { type: "lac", label: "Lac des Chats" }, + G8: { type: "plaines", label: "Plaines Sans Joie" }, + H8: { type: "foret", label: "Forêt d’Ourf" }, + I8: { type: "fleuve", label: "Fleuve de l'Oubli" }, + J8: { type: "monts", label: "Monts Barask" }, + K8: { type: "desert", label: "Désert de Fumée" }, + L8: { type: "monts", label: "Monts Tavelés" }, + M8: { type: "plaines", label: "Plaines Lavées" }, - A10: { type: "sanctuaire", label: "Sanctuaire d’Olis"}, - B10: { type: "monts", label: "Monts Salés"}, - C10: { type: "marais", label: "Marais de Dom"}, - D10: { type: "fleuve", label: "Fleuve"}, - E10: { type: "gouffre", label: "Gouffre de Junk"}, - F10: { type: "marais", label: "Marais Zultants"}, - G10: { type: "cite", label: "Cité de Sergal"}, - H10: { type: "plaines", label: "Plaines Noires"}, - I10: { type: "lac", label: "Lac Wanito"}, - J10: { type: "fleuve", label: "Fleuve"}, - K10: { type: "plaines", label: "Plaines Jaunes"}, - L10: { type: "desert", label: "Désert de Nicrop"}, - M10: { type: "foret", label: "Forêt de Jajou"}, + A9: { type: "collines", label: "Collines de Korrex" }, + B9: { type: "lac", label: "Lac de Lucre" }, + C9: { type: "monts", label: "Monts Tuméfiés" }, + D9: { type: "pont", label: "Pont d’Orx" }, + E9: { type: "fleuve", label: "Fleuve de l'Oubli" }, + F9: { type: "plaines", label: "Plaines de Foe" }, + G9: { type: "desolation", label: "Désolation de Demain" }, + H9: { type: "collines", label: "Collines de Noirseul" }, + I9: { type: "fleuve", label: "Fleuve de l'Oubli" }, + J9: { type: "marais", label: "Marais Gronchants" }, + K9: { type: "sanctuaire", label: "Sanctuaire Noir" }, + L9: { type: "collines", label: "Collines Cornues" }, + M9: { type: "necropole", label: "Nécropole de Zonar" }, - A11: { type: "desolation", label: "Désolation de Demain"}, - B11: { type: "cite", label: "Cité de Brilz"}, - C11: { type: "pont", label: "Pont de Roï"}, - D11: { type: "desolation", label: "Désolation de Demain"}, - E11: { type: "lac", label: "Lac de Glinster"}, - F11: { type: "cite", label: "Cité de Noape"}, - G11: { type: "fleuve", label: "Fleuve"}, - H11: { type: "fleuve", label: "Fleuve"}, - I11: { type: "pont", label: "Pont de Yalm"}, - J11: { type: "plaines", label: "Plaines de Miltiar"}, - K11: { type: "cite", label: "Cité Tonnerre"}, - L11: { type: "collines", label: "Collines de Kol"}, - M11: { type: "cite", label: "Cité Crapaud"}, + A10: { type: "sanctuaire", label: "Sanctuaire d’Olis" }, + B10: { type: "monts", label: "Monts Salés" }, + C10: { type: "marais", label: "Marais de Dom" }, + D10: { type: "fleuve", label: "Fleuve de l'Oubli" }, + E10: { type: "gouffre", label: "Gouffre de Junk" }, + F10: { type: "marais", label: "Marais Zultants" }, + G10: { type: "cite", label: "Cité de Sergal" }, + H10: { type: "plaines", label: "Plaines Noires" }, + I10: { type: "lac", label: "Lac Wanito" }, + J10: { type: "fleuve", label: "Fleuve de l'Oubli" }, + K10: { type: "plaines", label: "Plaines Jaunes" }, + L10: { type: "desert", label: "Désert de Nicrop" }, + M10: { type: "foret", label: "Forêt de Jajou" }, - A12: { type: "plaines", label: "Plaines Sages"}, - B12: { type: "fleuve", label: "Fleuve"}, - C12: { type: "lac", label: "Lac de Fricassa"}, - D12: { type: "collines", label: "Collines d’Huaï"}, - E12: { type: "monts", label: "Monts Ajourés"}, - F12: { type: "necropole", label: "Nécropole de Troat"}, - G12: { type: "plaines", label: "Plaines de Lufmil"}, - H12: { type: "collines", label: "Collines de Tooth"}, - I12: { type: "gouffre", label: "Gouffre Abimeux"}, - J12: { type: "cite", label: "Cité Folle"}, - K12: { type: "desolation", label: "Désolation de Demain"}, - L12: { type: "plaines", label: "Plaines Venteuses"}, - M12: { type: "collines", label: "Collines Révulsantes"}, + A11: { type: "desolation", label: "Désolation de Demain" }, + B11: { type: "cite", label: "Cité de Brilz" }, + C11: { type: "pont", label: "Pont de Roï" }, + D11: { type: "desolation", label: "Désolation de Demain" }, + E11: { type: "lac", label: "Lac de Glinster" }, + F11: { type: "cite", label: "Cité de Noape" }, + G11: { type: "fleuve", label: "Fleuve de l'Oubli" }, + H11: { type: "fleuve", label: "Fleuve de l'Oubli" }, + I11: { type: "pont", label: "Pont de Yalm" }, + J11: { type: "plaines", label: "Plaines de Miltiar" }, + K11: { type: "cite", label: "Cité Tonnerre" }, + L11: { type: "collines", label: "Collines de Kol" }, + M11: { type: "cite", label: "Cité Crapaud" }, - A13: { type: "fleuve", label: "Fleuve"}, - B13: { type: "gouffre", label: "Gouffre des Litiges"}, - C13: { type: "desert", label: "Désert de Neige"}, - D13: { type: "cite", label: "Cité Sordide"}, - E13: { type: "plaines", label: "Plaines de Xnez"}, - F13: { type: "foret", label: "Forêt des Cris"}, - G13: { type: "plaines", label: "Plaines Calcaires"}, - H13: { type: "desolation", label: "Désolation de Demain"}, - I13: { type: "monts", label: "Monts Bigleux"}, - J13: { type: "gouffre", label: "Gouffre de Gromph"}, - K13: { type: "foret", label: "Forêt de Kluth"}, - L13: { type: "monts", label: "Monts Dormants"}, - M13: { type: "plaines", label: "Plaines d’Anjou"}, + A12: { type: "plaines", label: "Plaines Sages" }, + B12: { type: "fleuve", label: "Fleuve de l'Oubli" }, + C12: { type: "lac", label: "Lac de Fricassa" }, + D12: { type: "collines", label: "Collines d’Huaï" }, + E12: { type: "monts", label: "Monts Ajourés" }, + F12: { type: "necropole", label: "Nécropole de Troat" }, + G12: { type: "plaines", label: "Plaines de Lufmil" }, + H12: { type: "collines", label: "Collines de Tooth" }, + I12: { type: "gouffre", label: "Gouffre Abimeux" }, + J12: { type: "cite", label: "Cité Folle" }, + K12: { type: "desolation", label: "Désolation de Demain" }, + L12: { type: "plaines", label: "Plaines Venteuses" }, + M12: { type: "collines", label: "Collines Révulsantes" }, - A14: { type: "collines", label: "Collines de Stolis"}, - B14: { type: "necropole", label: "Nécropole de Gorlo"}, - C14: { type: "foret", label: "Forêt de Bissam"}, - D14: { type: "sanctuaire", label: "Sanctuaire Plat"}, - E14: { type: "monts", label: "Monts de Quath"}, - F14: { type: "plaines", label: "Plaines Brisées"}, - G14: { type: "desert", label: "Désert de Sek"}, - H14: { type: "plaines", label: "Plaines Blanches"}, - I14: { type: "cite", label: "Cité Destituée"}, - J14: { type: "desert", label: "Désert de Sank"}, - K14: { type: "necropole", label: "Nécropole d’Antinéar"}, - L14: { type: "plaines", label: "Plaines de Jislith"}, - M14: { type: "desolation", label: "Désolation de Demain"}, + A13: { type: "fleuve", label: "Fleuve de l'Oubli" }, + B13: { type: "gouffre", label: "Gouffre des Litiges" }, + C13: { type: "desert", label: "Désert de Neige" }, + D13: { type: "cite", label: "Cité Sordide" }, + E13: { type: "plaines", label: "Plaines de Xnez" }, + F13: { type: "foret", label: "Forêt des Cris" }, + G13: { type: "plaines", label: "Plaines Calcaires" }, + H13: { type: "desolation", label: "Désolation de Demain" }, + I13: { type: "monts", label: "Monts Bigleux" }, + J13: { type: "gouffre", label: "Gouffre de Gromph" }, + K13: { type: "foret", label: "Forêt de Kluth" }, + L13: { type: "monts", label: "Monts Dormants" }, + M13: { type: "plaines", label: "Plaines d’Anjou" }, - A15: { type: "cite", label: "Cité de Mielh"}, - C15: { type: "plaines", label: "Plaines de Toué"}, - E15: { type: "foret", label: "Forêt des Furies"}, - G15: { type: "plaines", label: "Plaines des Soupirs"}, - I15: { type: "monts", label: "Monts des Dragées"}, - K15: { type: "collines", label: "Collines Pourpres"}, - M15: { type: "cite", label: "Cité de Klana"} - } + A14: { type: "collines", label: "Collines de Stolis" }, + B14: { type: "necropole", label: "Nécropole de Gorlo" }, + C14: { type: "foret", label: "Forêt de Bissam" }, + D14: { type: "sanctuaire", label: "Sanctuaire Plat" }, + E14: { type: "monts", label: "Monts de Quath" }, + F14: { type: "plaines", label: "Plaines Brisées" }, + G14: { type: "desert", label: "Désert de Sek" }, + H14: { type: "plaines", label: "Plaines Blanches" }, + I14: { type: "cite", label: "Cité Destituée" }, + J14: { type: "desert", label: "Désert de Sank" }, + K14: { type: "necropole", label: "Nécropole d’Antinéar" }, + L14: { type: "plaines", label: "Plaines de Jislith" }, + M14: { type: "desolation", label: "Désolation de Demain" }, -export const TMRType = { - cite: "cité", - sanctuaire: "sanctuaire", - plaines: "plaines", - pont: "pont", - collines: "collines", - foret: "forêt", - monts: "monts", - desert: "désert", - fleuve: "fleuve", - lac: "lac", - marais: "marais", - gouffre: "gouffre", - necropole: "nécropole", - desolation: "désolation" + A15: { type: "cite", label: "Cité de Mielh" }, + C15: { type: "plaines", label: "Plaines de Toué" }, + E15: { type: "foret", label: "Forêt des Furies" }, + G15: { type: "plaines", label: "Plaines des Soupirs" }, + I15: { type: "monts", label: "Monts des Dragées" }, + K15: { type: "collines", label: "Collines Pourpres" }, + M15: { type: "cite", label: "Cité de Klana" } +} + +export const TMRType = { + cite: { name: "cité", genre: "f" }, + sanctuaire: { name: "sanctuaire" }, + plaines: { name: "plaines", genre: "p" }, + pont: { name: "pont", genre: "m" }, + collines: { name: "collines", genre: "p" }, + foret: { name: "forêt", genre: "f" }, + monts: { name: "monts", genre: "p" }, + desert: { name: "désert", genre: "m" }, + fleuve: { name: "fleuve", genre: "m" }, + lac: { name: "lac", genre: "m" }, + marais: { name: "marais", genre: "m" }, + gouffre: { name: "gouffre", genre: "m" }, + necropole: { name: "nécropole", genre: "f" }, + desolation: { name: "désolation", genre: "f" } } /* -------------------------------------------- */ -const caseSpecificModes = [ "attache", "trounoir", "debordement", "reserve_extensible", "maitrisee" ]; +const caseSpecificModes = ["attache", "trounoir", "debordement", "reserve_extensible", "maitrisee"]; /* -------------------------------------------- */ -const tmrRandomMovePatten = - [ { name: 'top', x: 0, y: -1 }, - { name: 'topright', x: 1, y: -1 }, - { name: 'botright', x: 1, y: 1 }, - { name: 'bot', x: 0, y: 1 }, - { name: 'botleft', x: -1, y: 1 }, - { name: 'topleft', x: -1, y: -1 } - ] +const tmrRandomMovePatten = + [{ name: 'top', x: 0, y: -1 }, + { name: 'topright', x: 1, y: -1 }, + { name: 'botright', x: 1, y: 1 }, + { name: 'bot', x: 0, y: 1 }, + { name: 'botleft', x: -1, y: 1 }, + { name: 'topleft', x: -1, y: -1 } + ] /* -------------------------------------------- */ export const tmrConstants = { @@ -246,79 +247,116 @@ export const tmrConstants = { cellw: 55, cellh: 55, gridx: 28, - gridy: 28 + gridy: 28, + // tailles + third: 18, + half: 27.5, + twoThird: 36, + full: 55, + // decallages + center: { x: 0, y: 0 }, + top: { x: 0, y: -11.5 }, + topLeft: { x: -11.5, y: -11.5 }, + left: { x: -11.5, y: 0 }, + bottomLeft: { x: -11.5, y: 11.5 }, + bottom: { x: 0, y: 11.5 }, + bottomRight: { x: 11.5, y: 11.5 }, + right: { x: 11.5, y: 0 }, + topRight: { x: 11.5, y: -11.5 }, } +// couleurs +export const tmrColors = { + sort: 0xFF8800, + tetes: 0xA000FF, + souffle: 0x804040, + trounoir: 0x401060, + demireve: 0x00FFEE, + rencontre: 0xFF0000, + casehumide: 0x1050F0, +} + + /* -------------------------------------------- */ /* -------------------------------------------- */ -export class TMRUtility { +export class TMRUtility { static init() { for (let coord in TMRMapping) { TMRMapping[coord].coord = coord; } + let tmrByType = Misc.classify(Object.values(TMRMapping)); + for (const [type, list] of Object.entries(tmrByType)) { + TMRType[type].list = list; + } } /* -------------------------------------------- */ - static convertToTMRCoord( x, y ) - { - y = y + 1 - let letterX = String.fromCharCode(65+x); - return letterX+y + static convertToTMRCoord(pos) { + let letterX = String.fromCharCode(65 + (pos.x)); + return letterX + (pos.y + 1) } /* -------------------------------------------- */ - static verifyTMRCoord( coord ) { + static verifyTMRCoord(coord) { let TMRregexp = new RegExp(/([A-M])(\d+)/g); - let res = TMRregexp.exec( coord ); + let res = TMRregexp.exec(coord); if (res && res[1] && res[2]) { if (res[2] > 0 && res[2] < 16) { return true; } } return false; - } + } /* -------------------------------------------- */ - static convertToCellCoord( coordTMR ) - { + static convertToCellPos(coordTMR) { let x = coordTMR.charCodeAt(0) - 65; let y = coordTMR.substr(1) - 1; - return {x: x, y: y} + return { x: x, y: y } } - + /* -------------------------------------------- */ - static getTMR( coordTMR) - { + static getTMR(coordTMR) { return TMRMapping[coordTMR]; } - + static isCaseHumide(tmr) { + return tmr.type == 'fleuve' || tmr.type == 'lac' || tmr.type == 'marais'; + } + /* -------------------------------------------- */ /** Some debug functions */ - static async setForceRencontre( index, force = undefined ) { - this.prochaineRencontre = TMRRencontres.getRencontre( index ); - if (this.prochaineRencontre ) { + static async setForceRencontre(index, force = undefined) { + this.prochaineRencontre = TMRRencontres.getRencontre(index); + if (this.prochaineRencontre) { if (force) { this.prochaineRencontre.force = force; } - else{ + else { await TMRRencontres.evaluerForceRencontre(this.prochaineRencontre) } console.log("La prochaine rencontre sera:", this.prochaineRencontre.name, " force:", this.prochaineRencontre.force); } else { - ui.notifications.warn("Pas de prochaine rencontre valide pour "+index); + ui.notifications.warn("Pas de prochaine rencontre valide pour " + index); } } + /* -------------------------------------------- */ static isForceRencontre() { - return this.prochaineRencontre + return this.prochaineRencontre; + } + /* -------------------------------------------- */ + static utiliseForceRencontre() { + const rencontre = this.prochaineRencontre; + this.prochaineRencontre = undefined; + return rencontre; } /* -------------------------------------------- */ static getDirectionPattern() { - let roll = new Roll("1d"+tmrRandomMovePatten.length).evaluate().total; - return tmrRandomMovePatten[roll -1]; + let roll = new Roll("1d" + tmrRandomMovePatten.length).evaluate().total; + return tmrRandomMovePatten[roll - 1]; } static deplaceTMRAleatoire(coord) { @@ -326,103 +364,66 @@ export class TMRUtility { } /* -------------------------------------------- */ - static deplaceTMRSelonPattern( coord, direction, nTime ) { - for (let i=0; i it.coord); + static filterTMR(filter) { + return Object.values(TMRMapping).filter(filter); + } + + static filterTMRCoord(filter) { + return TMRUtility.filterTMR(filter).map(it => it.coord); + } + + static getTMRAleatoire(filter = undefined) { + let list = TMRUtility.filterTMR(filter); + let index = new Roll("1d" + list.length).evaluate().total - 1; + return list[index]; } /* -------------------------------------------- */ - static getTMRAleatoire(terrain=undefined) - { - if (terrain) { - let list = TMRUtility.getListTMR(terrain); - let index = new Roll("1d" + list.length).evaluate().total - 1; - return list[index]; - } - let num = new Roll("1d15").roll().total; - let letter, letterValue; - if ( num == 15) { - letterValue = new Roll( "1d7").roll().total; - letter = String.fromCharCode( 65 + ((parseInt(letterValue)-1)*2) ); - } else { - letterValue = new Roll( "1d13 + 64" ).roll().total; - letter = String.fromCharCode( letterValue ); - } - let caseIndex = letter+num; - ChatMessage.create( { content: "Case aléatoire : " + letter+num + " - " + TMRMapping[caseIndex].label , - whisper: ChatMessage.getWhisperRecipients("GM") } ); - return caseIndex; - } - - /* -------------------------------------------- */ - static _checkTMRCoord( x, y ) { - if (x >= 0 && x < 13 && y >= 0 && y < 14 ) return true; - if (x >= 0 && x < 13 && x%2 == 0 && y == 14 ) return true; + static _checkTMRCoord(x, y) { + if (x >= 0 && x < 13 && y >= 0 && y < 14) return true; + if (x >= 0 && x < 13 && x % 2 == 0 && y == 14) return true; return false; } /* -------------------------------------------- */ - static computeRealPictureCoordinates( coordXY, tmrConstants ) { + static computeRealPictureCoordinates(coordXY, tmrConstants) { let decallagePairImpair = (coordXY.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; - return { + return { x: tmrConstants.gridx + (coordXY.x * tmrConstants.cellw), y: tmrConstants.gridy + (coordXY.y * tmrConstants.cellh) + decallagePairImpair } } /* -------------------------------------------- */ - static getSortReserveList( reserveList, coordTMR ) { + static getSortReserveList(reserveList, coordTMR) { // TODO : Gérer les têtes spéciales réserve! let sortReserveList let tmrDescr = this.getTMR(coordTMR); //console.log("Sort réserve : ", tmrDescr); - if ( tmrDescr.type == 'fleuve') { // Gestion de la reserve en Fleuve - sortReserveList = reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve' ); + if (tmrDescr.type == 'fleuve') { // Gestion de la reserve en Fleuve + sortReserveList = reserveList.filter(it => TMRUtility.getTMR(it.coord).type == 'fleuve'); } else { // Reserve sur un case "normale" - sortReserveList = reserveList.filter(it => it.coord == coordTMR); + sortReserveList = reserveList.filter(it => it.coord == coordTMR); } //console.log("Sort réserve : ", tmrDescr, sortReserve, reserveList); return sortReserveList; @@ -432,22 +433,22 @@ export class TMRUtility { /** Returns a list of case inside a given distance * */ - static getTMRPortee(coord, portee) { - return TMRUtility.getTMRArea(coord, portee, tmrConstants); + static getTMRPortee(centerCoord, portee) { + return TMRUtility.getTMRArea(centerCoord, portee, tmrConstants); } - static getTMRArea( coord, distance, tmrConstants ) { - let pos = this.convertToCellCoord( coord ); - let posPic = this.computeRealPictureCoordinates( pos, tmrConstants ); + static getTMRArea(centerCoord, distance, tmrConstants) { + let centerPos = this.convertToCellPos(centerCoord); + let posPic = this.computeRealPictureCoordinates(centerPos, tmrConstants); let caseList = []; - for (let x=pos.x-distance; x<=pos.x+distance; x++ ) { // Loop thru lines - for (let y=pos.y-distance; y<=pos.y+distance; y++ ) { // Loop thru lines - //console.log("Parsing position", x, y); - if ( this._checkTMRCoord(x, y) ) { // Coordinate is valie - let posPicNow = this.computeRealPictureCoordinates( {x: x, y: y}, tmrConstants ); - let dist = Math.sqrt(Math.pow(posPicNow.x - posPic.x,2) + Math.pow(posPicNow.y - posPic.y, 2)) / tmrConstants.cellw; - if ( dist < distance+0.5) { - caseList.push( this.convertToTMRCoord(x, y) ); // Inside the area + for (let dx = -distance; dx <= distance; dx++) { // Loop thru lines + for (let dy = -distance; dy <= distance; dy++) { // Loop thru lines + const currentPos = { x: centerPos.x + dx, y: centerPos.y + dy }; + if (this._checkTMRCoord(currentPos.x, currentPos.y)) { // Coordinate is valie + let posPicNow = this.computeRealPictureCoordinates(currentPos, tmrConstants); + let dist = Math.sqrt(Math.pow(posPicNow.x - posPic.x, 2) + Math.pow(posPicNow.y - posPic.y, 2)) / tmrConstants.cellw; + if (dist < distance + 0.5) { + caseList.push(this.convertToTMRCoord(currentPos)); // Inside the area } } } diff --git a/module/tmr/carte-tmr.js b/module/tmr/carte-tmr.js new file mode 100644 index 00000000..7b2d10d9 --- /dev/null +++ b/module/tmr/carte-tmr.js @@ -0,0 +1,20 @@ +import { Draconique } from "./draconique.js"; + +export class CarteTmr extends Draconique { + + constructor() { + super(); + } + + type() { return '' } + match(item) { return false; } + manualMessage() { return false } + async onActorCreateOwned(actor, item) { } + + code() { return 'tmr' } + img() { return 'systems/foundryvtt-reve-de-dragon/styles/img/ui/tmp_main_r1.webp' } + + _createSprite(pixiTMR) { + return pixiTMR.carteTmr(this.code()); + } +} diff --git a/module/tmr/debordement.js b/module/tmr/debordement.js new file mode 100644 index 00000000..c4c257b5 --- /dev/null +++ b/module/tmr/debordement.js @@ -0,0 +1,31 @@ +import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class Debordement extends Draconique { + + constructor() { + super(); + } + + type() { return 'souffle' } + match(item) { return Draconique.isSouffleDragon(item) && item.name.toLowerCase().includes('trou noir'); } + manualMessage() { return false } + async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } + + code() { return 'debordement' } + tooltip(linkData) { return `Débordement en ${TMRUtility.getTMR(linkData.data.coord).label}` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/wave.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), + { + color: tmrColors.casehumide, alpha: 0.5, taille: tmrConstants.twoThird, decallage: tmrConstants.bottom + }); + } + + async _creerCaseTmr(actor) { + const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); + const tmr = TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord))); + await this.createCaseTmr(actor, 'Debordement: ' + tmr.label, tmr); + } +} diff --git a/module/tmr/demi-reve.js b/module/tmr/demi-reve.js new file mode 100644 index 00000000..e84c7d88 --- /dev/null +++ b/module/tmr/demi-reve.js @@ -0,0 +1,27 @@ +import { tmrColors, tmrConstants } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class DemiReve extends Draconique { + + constructor() { + super(); + } + + type() { return '' } + match(item) { return false; } + manualMessage() { return false } + async onActorCreateOwned(actor, item) { } + + code() { return 'demi-reve' } + tooltip(linkData) { return `Demi-rêve` } + img() { return 'icons/svg/sun.svg' } + + _createSprite(pixiTMR) { + const sprite = pixiTMR.sprite(this.code(), { + color: tmrColors.demireve, + taille: (tmrConstants.full * 0.7) + }); + pixiTMR.animate(pixiApp => pixiApp.ticker.add((delta) => sprite.rotation -= 0.01 * delta)); + return sprite; + } +} diff --git a/module/tmr/draconique.js b/module/tmr/draconique.js new file mode 100644 index 00000000..0dacd3c3 --- /dev/null +++ b/module/tmr/draconique.js @@ -0,0 +1,118 @@ +import { PixiTMR } from "./pixi-tmr.js"; + +const registeredEffects = [ +] + +/** + * Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR + */ +export class Draconique +{ + static isCaseTMR(element) { return element.type == 'casetmr'; } + static isQueueDragon(element) { return element.type == 'queue' || element.type == 'ombre'; } + static isSouffleDragon(element) { return element.type == 'souffle'; } + static isTeteDragon(element) { return element.type == 'tete'; } + static isQueueSouffle(it) { return Draconique.isQueueDragon(it) || Draconique.isSouffleDragon(it); } + + static register(draconique) { + registeredEffects[draconique.code()] = draconique; + if (draconique.img()) { + PixiTMR.register(draconique.code(), draconique.img()) + } + return draconique; + } + + static all() { + return Object.values(registeredEffects); + } + static get(code) { + return registeredEffects[code]; + } + + /** + * @param item un Item quelconque + * @returns true si l'item correspond + */ + match(item) { + return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item) || Draconique.isTeteDragon(item); + } + + /** + * @returns un message à afficher si la draconique doit être gérée manuellement. + */ + manualMessage() { + return false; + } + + /** + * Méthode responsable de gérer une draconique (par exemple, ajouter des casetmr pour la fermeture des cités). + * @param actor auquel la draconique est ajoutée + */ + async onActorCreateOwned(actor) { + return false; + } + async onActorDeleteOwned(actor) { + return false; + } + /** + * @return le code interne utilisé pour les casetmr correpondant + */ + code() { return undefined } + + /** + * @param {*} linkData données associées au token pixi (une casetmr, un sort en réserve, une rencontre en attente) + * @returns un tooltip à afficher au dessus du token + */ + tooltip(linkData) { return undefined } + + /** + * @param {*} img l'url du fichier image à utiliser pour le token. Si indéfini (et si createSprite n'est pas surchargé), + * un disque est utilisé. + */ + img() { return undefined } + + /** + * factory d'élément graphique PIXI correpsondant à l'objet draconique + * @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks. + */ + token(pixiTMR, linkData, coordTMR, type = undefined) { + const token = { + sprite: this._createSprite(pixiTMR), + coordTMR: coordTMR + }; + token[type ?? this.code()] = linkData; + pixiTMR.addTooltip(token.sprite, this.tooltip(linkData)); + return token; + + return sprite; + } + /** + * factory d'élément graphique PIXI correpsondant à l'objet draconique + * @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks. + */ + _createSprite(pixiTMR) { + if (this.img()) { + return pixiTMR.sprite(this.code()); + } + else{ + return pixiTMR.circle() + } + } + + /** + * + * @param {*} it un item à tester + * @param {*} coord les coordonnées d'une case. Si undefined toute case du type correspondra, + */ + isCase(it, coord = undefined) { + return Draconique.isCaseTMR(it) && it.data.specific == this.code() && (coord ? it.data.coord == coord : true); + } + + async createCaseTmr(actor, label, tmr) { + await actor.createOwnedItem({ + name: label, type: 'casetmr', img: this.img(), _id: randomID(16), + data: { coord: tmr.coord, specific: this.code() } + }); + } + +} \ No newline at end of file diff --git a/module/tmr/effets-draconiques.js b/module/tmr/effets-draconiques.js new file mode 100644 index 00000000..cec1edb3 --- /dev/null +++ b/module/tmr/effets-draconiques.js @@ -0,0 +1,152 @@ +import { Debordement } from "./debordement.js"; +import { FermetureCites } from "./fermeture-cites.js"; +import { QueteEaux } from "./quete-eaux.js"; +import { TerreAttache } from "./terre-attache.js"; +import { ReserveExtensible } from "./reserve-extensible.js"; +import { DemiReve } from "./demi-reve.js"; +import { TrouNoir } from "./trou-noir.js"; +import { Rencontre } from "./rencontre.js"; +import { SortReserve } from "./sort-reserve.js"; +import { CarteTmr } from "./carte-tmr.js"; +import { PontImpraticable } from "./pont-impraticable.js"; +import { Draconique } from "./draconique.js"; +import { PresentCites } from "./present-cites.js"; + + + +export class EffetsDraconiques { + static carteTmr = new CarteTmr(); + static demiReve = new DemiReve(); + static rencontre = new Rencontre(); + static sortReserve = new SortReserve(); + static debordement = new Debordement(); + static presentCites = new PresentCites(); + static fermetureCites = new FermetureCites(); + static queteEaux = new QueteEaux(); + static reserveExtensible = new ReserveExtensible(); + static terreAttache = new TerreAttache(); + static trouNoir = new TrouNoir(); + static pontImpraticable = new PontImpraticable(); + + static init() { + Draconique.register(EffetsDraconiques.carteTmr); + Draconique.register(EffetsDraconiques.demiReve); + Draconique.register(EffetsDraconiques.rencontre); + Draconique.register(EffetsDraconiques.sortReserve); + Draconique.register(EffetsDraconiques.debordement); + Draconique.register(EffetsDraconiques.fermetureCites); + Draconique.register(EffetsDraconiques.queteEaux); + Draconique.register(EffetsDraconiques.reserveExtensible); + Draconique.register(EffetsDraconiques.terreAttache); + Draconique.register(EffetsDraconiques.trouNoir); + Draconique.register(EffetsDraconiques.pontImpraticable); + Draconique.register(EffetsDraconiques.presentCites); + } + + /* -------------------------------------------- */ + static isCaseInondee(caseTMR, coord) { + return EffetsDraconiques.debordement.isCase(caseTMR, coord) || EffetsDraconiques.pontImpraticable.isCase(caseTMR, coord); + } + + static isCaseTrouNoir(caseTMR, coord) { + return EffetsDraconiques.trouNoir.isCase(caseTMR, coord); + } + + static isReserveExtensible(caseTMR, coord) { + return EffetsDraconiques.reserveExtensible.isCase(caseTMR, coord); + } + + static isTerreAttache(caseTMR, coord) { + return EffetsDraconiques.terreAttache.isCase(caseTMR, coord); + } + + static isCiteFermee(caseTMR, coord) { + return EffetsDraconiques.fermetureCites.isCase(caseTMR, coord); + } + + static isPresentCite(caseTMR, coord) { + return EffetsDraconiques.presentCites.isCase(caseTMR, coord); + } + /* -------------------------------------------- */ + static isMauvaiseRencontre(element) { + return EffetsDraconiques.isMatching(element, it => Draconique.isQueueSouffle(it) && it.name.toLowerCase().includes('mauvaise rencontre')); + } + + static isMonteeLaborieuse(element) { + return EffetsDraconiques.isMatching(element, it => Draconique.isQueueSouffle(it) && it.name.toLowerCase().includes('montée laborieuse')); + } + + static isFermetureCite(element) { + /* -------------------------------------------- */ + return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.fermetureCites.match(it)); + } + + static isPontImpraticable(element) { + return EffetsDraconiques.isMatching(element, it => EffetsDraconiques.pontImpraticable.match(it)); + } + + static isDoubleResistanceFleuve(element) { + return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase().includes('résistance du fleuve')); + } + + static isPeage(element) { + return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase().includes('péage')); + } + + static isPeriple(element) { + // TODO + return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && ir.name.toLowerCase() == 'périple'); + } + + static isDesorientation(element) { + // TODO + return EffetsDraconiques.isMatching(element, it => Draconique.isSouffleDragon(it) && it.name.toLowerCase() == 'désorientation'); + } + + /* -------------------------------------------- */ + static isConquete(element) { + // TODO + return EffetsDraconiques.isMatching(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase() == 'conquête'); + } + + static isPelerinage(element) { + return EffetsDraconiques.isMatching(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase() == 'pélerinage'); + } + + static countInertieDraconique(element) { + return EffetsDraconiques.count(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase().includes('inertie draconique')); + } + + static isUrgenceDraconique(element) { + return EffetsDraconiques.isMatching(element, it => Draconique.isQueueDragon(it) && it.name.toLowerCase() == 'urgence draconique'); + } + + /* -------------------------------------------- */ + static isDonDoubleReve(element) { + return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name == 'Don de double-rêve'); + } + + static isConnaissanceFleuve(element) { + return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes('connaissance du fleuve')); + } + + static isReserveEnSecurite(element) { + return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes(' en sécurité')); + } + + static isDeplacementAccelere(element) { + return EffetsDraconiques.isMatching(element, it => Draconique.isTeteDragon(it) && it.name.toLowerCase().includes(' déplacement accéléré')); + } + + static isMatching(element, matcher) { + return EffetsDraconiques.toItems(element).find(matcher); + } + static count(element, matcher) { + return EffetsDraconiques.toItems(element).filter(matcher).length; + } + + static toItems(element) { + return (element?.entity === 'Actor') ? element.data.items : (element?.entity === 'Item') ? [element] : []; + } + +} \ No newline at end of file diff --git a/module/tmr/fermeture-cites.js b/module/tmr/fermeture-cites.js new file mode 100644 index 00000000..dc95bc37 --- /dev/null +++ b/module/tmr/fermeture-cites.js @@ -0,0 +1,33 @@ +import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class FermetureCites extends Draconique { + + constructor() { + super(); + } + + type() { return 'souffle' } + match(item) { return Draconique.isSouffleDragon(item) && item.name.toLowerCase() == 'fermeture des cités'; } + manualMessage() { return false } + async onActorCreateOwned(actor, item) { await this._fermerLesCites(actor); } + + code() { return 'fermeture' } + tooltip(linkData) { return `La ${TMRUtility.getTMR(linkData.data.coord).label} est fermée` } + img() { return 'icons/svg/door-closed.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), + { + color: tmrColors.souffle, alpha: 0.9, taille: tmrConstants.full, decallage: { x: 2, y: 0 } + }); + } + + async _fermerLesCites(actor) { + let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); + let ouvertes = TMRUtility.filterTMR(it => it.type == 'cite' && !existants.includes(it.coord)); + for (let tmr of ouvertes) { + await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr); + } + } +} diff --git a/module/tmr/pixi-tmr.js b/module/tmr/pixi-tmr.js new file mode 100644 index 00000000..40cdbe67 --- /dev/null +++ b/module/tmr/pixi-tmr.js @@ -0,0 +1,148 @@ +import { tmrConstants } from "../tmr-utility.js"; + +const tooltipStyle = new PIXI.TextStyle({ + fontFamily: 'CaslonAntique', + fontSize: 18, + fill: '#FFFFFF', + stroke: '#000000', + strokeThickness: 3 +}); + + +export class PixiTMR { + + static textures = [] + + constructor(tmrObject, pixiApp) { + this.tmrObject = tmrObject; + this.pixiApp = pixiApp ?? tmrObject.pixiApp; + this.callbacksOnAnimate = []; + } + + load(onLoad = (loader, resources) => {}) { + let loader = this.pixiApp.loader; + for (const [name, img] of Object.entries(PixiTMR.textures)) { + loader = loader.add(name, img); + } + loader.load((loader, resources) => { + onLoad(loader, resources); + for (let onAnimate of this.callbacksOnAnimate) { + onAnimate(); + } + }); + } + + static register(name, img) { + PixiTMR.textures[name] = img; + } + + animate(animation = pixiApp=>{}) + { + this.callbacksOnAnimate.push(() => animation(this.pixiApp)); + } + + carteTmr(code) { + const carteTmr = new PIXI.Sprite(PIXI.utils.TextureCache[code]); + // Setup the position of the TMR + carteTmr.x = 0; + carteTmr.y = 0; + carteTmr.width = 720; + carteTmr.height = 860; + // Rotate around the center + carteTmr.anchor.set(0); + carteTmr.interactive = true; + carteTmr.buttonMode = true; + carteTmr.tmrObject = this; + // atténue les couleurs des TMRs + const tmrColorFilter = new PIXI.filters.ColorMatrixFilter(); + tmrColorFilter.contrast(1); + tmrColorFilter.brightness(0.2); + tmrColorFilter.saturate(-0.5); + carteTmr.filters = [tmrColorFilter]; + if (!this.tmrObject.viewOnly) { + carteTmr.on('pointerdown', event => this.onClickBackground(event)); + } + this.pixiApp.stage.addChild(carteTmr); + return carteTmr; + } + + sprite(code, options = {}) { + const texture = PIXI.utils.TextureCache[code]; + if (!texture) { + console.error("Texture manquante", code) + return; + } + let sprite = new PIXI.Sprite(texture); + sprite.width = options.taille ?? tmrConstants.half; + sprite.height = options.taille ?? tmrConstants.half; + sprite.anchor.set(0.5); + sprite.tint = options.color ?? 0x000000; + sprite.alpha = options.alpha ?? 0.75; + sprite.decallage = options.decallage ?? tmrConstants.center; + this.pixiApp.stage.addChild(sprite); + return sprite; + } + + circle(name, options = {}) { + let sprite = new PIXI.Graphics(); + sprite.beginFill(options.color, options.opacity); + sprite.drawCircle(0, 0, (options.taille ?? 12) / 2); + sprite.endFill(); + sprite.decallage = options.decallage ?? tmrConstants.topLeft; + this.pixiApp.stage.addChild(sprite); + return sprite; + } + + addTooltip(sprite, text) { + if (text) { + sprite.tooltip = new PIXI.Text(text, tooltipStyle); + sprite.isOver = false; + sprite.interactive = true; + sprite.on('pointerdown', event => this.onClickBackground(event)) + .on('pointerover', () => this.onShowTooltip(sprite)) + .on('pointerout', () => this.onHideTooltip(sprite)); + } + } + + + onClickBackground(event) { + this.tmrObject.onClickTMR(event) + } + + onShowTooltip(sprite) { + if (sprite.tooltip) { + + if (!sprite.isOver) { + sprite.tooltip.x = sprite.x; + sprite.tooltip.y = sprite.y; + this.pixiApp.stage.addChild(sprite.tooltip); + } + sprite.isOver = true; + } + } + + onHideTooltip(sprite) { + if (sprite.tooltip) { + if (sprite.isOver) { + this.pixiApp.stage.removeChild(sprite.tooltip); + } + sprite.isOver = false; + } + } + + setPosition( sprite, pos) { + let decallagePairImpair = (pos.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; + let dx = (sprite.decallage == undefined) ? 0 : sprite.decallage.x; + let dy = (sprite.decallage == undefined) ? 0 : sprite.decallage.y; + sprite.x = tmrConstants.gridx + (pos.x * tmrConstants.cellw) + dx; + sprite.y = tmrConstants.gridy + (pos.y * tmrConstants.cellh) + dy + decallagePairImpair; + } + + getCaseRectangle(pos) { + let decallagePairImpair = (pos.x % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y; + let x = tmrConstants.gridx + (pos.x * tmrConstants.cellw) - (tmrConstants.cellw / 2); + let y = tmrConstants.gridy + (pos.y * tmrConstants.cellh) - (tmrConstants.cellh / 2) + decallagePairImpair; + return { x: x, y: y, w: tmrConstants.cellw, h: tmrConstants.cellh }; + } + +} \ No newline at end of file diff --git a/module/tmr/pont-impraticable.js b/module/tmr/pont-impraticable.js new file mode 100644 index 00000000..f9251742 --- /dev/null +++ b/module/tmr/pont-impraticable.js @@ -0,0 +1,40 @@ +import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class PontImpraticable extends Draconique { + + constructor() { + super(); + } + + type() { return 'souffle' } + match(item) { return Draconique.isSouffleDragon(item) && item.name.toLowerCase().includes('impraticabilité des ponts'); } + + async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } + async onActorDeleteOwned(actor, item) { await this._supprimerCaseTmr(actor); } + + code() { return 'pont-impraticable' } + tooltip(linkData) { return `${TMRUtility.getTMR(linkData.data.coord).label} impraticable` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/wave.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), + { + color: tmrColors.casehumide, alpha: 0.5, taille: tmrConstants.twoThird, decallage: tmrConstants.bottom + }); + } + + async _creerCaseTmr(actor) { + const ponts = TMRUtility.getListTMR('pont'); + for (let tmr of ponts) { + await this.createCaseTmr(actor, 'Pont impraticable: ' + tmr.label, tmr); + } + } + + async _supprimerCaseTmr(actor) { + const existants = actor.data.items.filter(it => this.isCase(it)); + for (let caseTMR of existants) { + await actor.deleteOwnedItem(caseTMR._id); + } + } +} diff --git a/module/tmr/present-cites.js b/module/tmr/present-cites.js new file mode 100644 index 00000000..105f7bba --- /dev/null +++ b/module/tmr/present-cites.js @@ -0,0 +1,42 @@ +import { ChatUtility } from "../chat-utility.js"; +import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class PresentCites extends Draconique { + + constructor() { + super(); + } + + type() { return 'tete' } + match(item) { return Draconique.isTeteDragon(item) && item.name.toLowerCase() == 'présent des cités'; } + manualMessage() { return false } + async onActorCreateOwned(actor, item) { await this._ajouterPresents(actor); } + + code() { return 'present-cites' } + tooltip(linkData) { return `La ${TMRUtility.getTMR(linkData.data.coord).label} a un présent` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/svg/gift.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), + { + color: tmrColors.tetes, alpha: 0.7, taille: tmrConstants.third, decallage:tmrConstants.topRight + }); + } + + async _ajouterPresents(actor) { + let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); + if (existants.length >0 ) { + ChatMessage.create({ + whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user), + content: "Vous avez encore des présents dans des cités, vous devrez tirer une autre tête pour remplacer celle ci!" + }) + } + else{ + let cites = TMRUtility.filterTMR(it => it.type == 'cite'); + for (let tmr of cites) { + await this.createCaseTmr(actor, 'Présent: ' + tmr.label, tmr); + } + } + } +} diff --git a/module/tmr/quete-eaux.js b/module/tmr/quete-eaux.js new file mode 100644 index 00000000..481502c9 --- /dev/null +++ b/module/tmr/quete-eaux.js @@ -0,0 +1,25 @@ +import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class QueteEaux extends Draconique { + constructor() { + super(); + } + + type() { return 'tete' } + match(item) { return Draconique.isTeteDragon(item) && item.name.toLowerCase().includes("quête des eaux"); } + manualMessage() { return "Vous devrez re-configurer votre Quête des Eaux une fois un lac ou marais vaincu" } + async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } + + code() { return 'maitrisee' } + tooltip(linkData) { return `Quête des eaux, le ${TMRUtility.getTMR(linkData.data.coord).label} est maîtrisé` } + img() { return 'icons/svg/bridge.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), { color: tmrColors.tetes, decallage: tmrConstants.topRight }); + } + + async _creerCaseTmr(actor) { + await this.createCaseTmr(actor, "Quête des eaux à déterminer", {coord:'A0'}); + } +} diff --git a/module/tmr/rencontre.js b/module/tmr/rencontre.js new file mode 100644 index 00000000..3c6c4ab8 --- /dev/null +++ b/module/tmr/rencontre.js @@ -0,0 +1,22 @@ +import { tmrColors, tmrConstants } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class Rencontre extends Draconique { + + constructor() { + super(); + } + + type() { return '' } + match(item) { return false; } + manualMessage() { return false } + async onActorCreateOwned(actor, item) { } + + code() { return 'rencontre' } + tooltip(linkData) { return `${linkData.name} de force ${linkData.force}` } + img() { return 'systems/foundryvtt-reve-de-dragon/icons/heures/hd06.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), { color: tmrColors.rencontre, taille: tmrConstants.full, decallage: { x: 2, y: 2 } }); + } +} diff --git a/module/tmr/reserve-extensible.js b/module/tmr/reserve-extensible.js new file mode 100644 index 00000000..7fbce50f --- /dev/null +++ b/module/tmr/reserve-extensible.js @@ -0,0 +1,28 @@ +import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class ReserveExtensible extends Draconique { + constructor() { + super(); + } + + type() { return 'tete' } + match(item) { return Draconique.isTeteDragon(item) && item.name.toLowerCase().includes("réserve extensible"); } + manualMessage() { return "Vous pouvez re-configurer votre Réserve extensible" } + async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } + + code() { return 'reserve_extensible' } + tooltip(linkData) { return `Réserve extensible en ${TMRUtility.getTMR(linkData.data.coord).label} !` } + img() { return 'icons/svg/chest.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), { color: tmrColors.tetes, decallage: tmrConstants.left}); + } + + async _creerCaseTmr(actor) { + const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); + const tmr = TMRUtility.getTMRAleatoire(it => !(it.type == 'fleuve' || existants.includes(it.coord))); + await this.createCaseTmr(actor, "Nouvelle Réserve extensible", tmr); + } + +} diff --git a/module/tmr/sort-reserve.js b/module/tmr/sort-reserve.js new file mode 100644 index 00000000..4b1ee48b --- /dev/null +++ b/module/tmr/sort-reserve.js @@ -0,0 +1,22 @@ +import { tmrColors, tmrConstants } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class SortReserve extends Draconique { + + constructor() { + super(); + } + + type() { return '' } + match(item) { return false; } + manualMessage() { return false } + async onActorCreateOwned(actor, item) { } + + code() { return 'sort' } + tooltip(linkData) { return `${linkData.name}, r${linkData.data.ptreve_reel}` } + img() { return 'icons/svg/book.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), { color: tmrColors.sort, decallage: tmrConstants.right }); + } +} diff --git a/module/tmr/terre-attache.js b/module/tmr/terre-attache.js new file mode 100644 index 00000000..34416fec --- /dev/null +++ b/module/tmr/terre-attache.js @@ -0,0 +1,25 @@ +import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class TerreAttache extends Draconique { + constructor() { + super(); + } + + type() { return 'tete' } + match(item) { return Draconique.isTeteDragon(item) && item.name.toLowerCase().includes("terre d'attache"); } + manualMessage() { return "Vous pouvez re-configurer votre Terre d'Attache" } + async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } + + code() { return 'attache' } + tooltip(linkData) { return `Terre d'attache en ${TMRUtility.getTMR(linkData.data.coord).label} !` } + img() { return 'icons/svg/anchor.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), { color: tmrColors.tetes, decallage: tmrConstants.topLeft }); + } + + async _creerCaseTmr(actor) { + await this.createCaseTmr(actor, "Terre d'attache à déterminer", {coord:'A0'}); + } +} diff --git a/module/tmr/trou-noir.js b/module/tmr/trou-noir.js new file mode 100644 index 00000000..02637da1 --- /dev/null +++ b/module/tmr/trou-noir.js @@ -0,0 +1,30 @@ +import { tmrColors, tmrConstants, TMRUtility } from "../tmr-utility.js"; +import { Draconique } from "./draconique.js"; + +export class TrouNoir extends Draconique { + constructor() { + super(); + } + + type() { return 'souffle' } + match(item) { return Draconique.isSouffleDragon(item) && item.name.toLowerCase().includes('trou noir'); } + manualMessage() { return false } + async onActorCreateOwned(actor, item) { await this._creerCaseTmr(actor); } + + code() { return 'trounoir' } + tooltip(linkData) { return `Trou noir en ${TMRUtility.getTMR(linkData.data.coord).label} !` } + img() { return 'icons/svg/explosion.svg' } + + _createSprite(pixiTMR) { + return pixiTMR.sprite(this.code(), + { + color: tmrColors.trounoir, alpha: 1, taille: tmrConstants.full, decallage: { x: 2, y: 2 }, + }); + } + + async _creerCaseTmr(actor) { + const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); + const tmr = TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord))); + await this.createCaseTmr(actor, 'Trou noir: ' + tmr.label, tmr); + } +} diff --git a/packs/animaux.db b/packs/animaux.db index 12497af5..af4836c4 100644 --- a/packs/animaux.db +++ b/packs/animaux.db @@ -25,6 +25,7 @@ {"_id":"eGvgsF9uiR4vKLB2","name":"Quileurbist","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"creature","data":{"carac":{"taille":{"type":"number","value":"14","label":"Taille","xp":0,"derivee":false},"constitution":{"type":"number","value":"14","label":"Constitution","xp":0,"derivee":false},"force":{"type":"number","value":"18","label":"Force","xp":0,"derivee":false},"perception":{"type":"number","value":"10","label":"Perception","xp":0,"derivee":false},"volonte":{"type":"number","value":"10","label":"Volonté","xp":0,"derivee":false},"reve":{"type":"number","value":"10","label":"Rêve","xp":0,"derivee":false}},"sante":{"vie":{"type":"number","max":14,"value":14,"label":"Vie","derivee":false},"endurance":{"type":"number","max":28,"value":28,"label":"Endurance","derivee":false},"sonne":{"value":false,"label":"Sonné"}},"blessures":{"legeres":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"graves":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"critiques":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]}},"attributs":{"plusdom":{"type":"number","value":"+3","label":"+dom","derivee":true},"vitesse":{"type":"string","value":"14/28","label":"Vitesse","derivee":true},"encombrement":{"type":"number","value":"0","label":"Encombrement","derivee":false},"protection":{"type":"number","value":"5","label":"Protection","derivee":false}},"compteurs":{"etat":{"value":0,"label":"Etat général"},"surenc":{"value":0,"label":"Sur-encombrement"}},"description":"

    Description

    \n

    Le quileurbist est une créature simiesque recouverte d’une carapace d’écailles hérissées de piquants. Sa tête plate et triangulaire est dotée d’une large mâchoire plantée de crocs, et ses bras plutôt longs se terminent par des pattes plantées de griffes acérées. Comme les grands singes, il se tient en position semi-verticale. Son cri, rauque et guttural, ressemble à la syllabe kill, d’où, d’après Paranos le Moindre, l’origine de son nom. Il fait en moyenne 1m85 pour 100 kg.

    \n

    Mœurs

    \n

    Le quileurbist n’a pas d’habitat spécifique, encore qu’on le rencontre surtout dans les collines rocheuses et peu boisées, mais vagabond itinérant, il change souvent de lieu. Il faut dire que partout où se trouve un quileurbist, la région se dépeuple de toute autre vie animale. La créature semble en effet n’avoir qu’une vocation\" : tuer, déchirer, éventrer, massacrer toutes les autres formes de vie. Le quileurbist résiste automatiquement au sort de Non-Agressivité d’Hypnos. En combat, ses réussites particulières sont toujours passées en rapidité.

    ","notesmj":"Notes du MJ","competencecreature[0]":{"data":{"carac_value":"12"}},"competencecreature[0]]":{"data":{"dommages":"+0"}},"competencecreature[1]":{"data":{"carac_value":"15"}},"competencecreature[1]]":{"data":{"dommages":"+0"}},"competencecreature[2]":{"data":{"carac_value":"12"}},"competencecreature[2]]":{"data":{"dommages":"+0"}},"competencecreature[3]":{"data":{"carac_value":"15"}},"competencecreature[3]]":{"data":{"dommages":"+2"}},"competencecreature[4]":{"data":{"carac_value":"10"}},"competencecreature[4]]":{"data":{"dommages":"+0"}},"competencecreature[5]":{"data":{"carac_value":"15"}},"competencecreature[5]]":{"data":{"dommages":"+0"}}},"sort":100001,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/creatures/quileurbist.svg","token":{"flags":{},"name":"Quileurbist","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/creatures/quileurbist.svg","tint":null,"width":1,"height":1,"scale":1,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightAlpha":1,"lightAnimation":{"speed":5,"intensity":5},"actorId":"eGvgsF9uiR4vKLB2","actorLink":false,"disposition":-1,"displayBars":0,"bar1":{},"bar2":{},"randomImg":false},"items":[{"_id":"shsUV8UpU18c0RJK","name":"Course","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":12,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":400000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.png","effects":[]},{"_id":"4GmpkphbsmQjvVVK","name":"Escalade","type":"competencecreature","data":{"categorie_parade":"","niveau":5,"default_diffLibre":0,"carac_value":15,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":800000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_escalade.png","effects":[]},{"_id":"CYpxxf1uTa78NWR9","name":"Esquive","type":"competencecreature","data":{"categorie_parade":"","niveau":5,"default_diffLibre":0,"carac_value":12,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":850000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.png","effects":[]},{"_id":"BjqRrGtHtTzuNpZB","name":"Griffes et Crocs","type":"competencecreature","data":{"categorie_parade":"","niveau":5,"default_diffLibre":0,"carac_value":15,"iscombat":true,"isparade":false,"dommages":2,"description":""},"sort":900000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.png","effects":[]},{"_id":"lzEdMrKXbOYrWG5S","name":"Vigilance","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":10,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":1800000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]},{"_id":"8O8e3Msr2KPZqwkY","name":"Saut","type":"competencecreature","data":{"categorie_parade":"","niveau":5,"default_diffLibre":0,"carac_value":15,"iscombat":false,"isparade":false,"dommages":0,"description":null},"sort":1900000,"flags":{"core":{"sourceId":"Item.JZDgJ7ySiV84llkK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.png","effects":[]}],"effects":[]} {"_id":"f31jeCsQgw3hWjk6","name":"Furlong","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"creature","data":{"carac":{"taille":{"type":"number","value":"7","label":"Taille","xp":0,"derivee":false},"constitution":{"type":"number","value":"12","label":"Constitution","xp":0,"derivee":false},"force":{"type":"number","value":"11","label":"Force","xp":0,"derivee":false},"perception":{"type":"number","value":"13","label":"Perception","xp":0,"derivee":false},"volonte":{"type":"number","value":"10","label":"Volonté","xp":0,"derivee":false},"reve":{"type":"number","value":"10","label":"Rêve","xp":0,"derivee":false}},"sante":{"vie":{"type":"number","max":10,"value":10,"label":"Vie","derivee":false},"endurance":{"type":"number","max":22,"value":22,"label":"Endurance","derivee":false},"sonne":{"value":false,"label":"Sonné"}},"blessures":{"legeres":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"graves":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"critiques":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]}},"attributs":{"plusdom":{"type":"number","value":"+0","label":"+dom","derivee":true},"vitesse":{"type":"string","value":"12/30","label":"Vitesse","derivee":true},"encombrement":{"type":"number","value":"0","label":"Encombrement","derivee":false},"protection":{"type":"number","value":"0","label":"Protection","derivee":false}},"compteurs":{"etat":{"value":0,"label":"Etat général"},"surenc":{"value":0,"label":"Sur-encombrement"}},"description":"

    Description

    \n

    Le furlong est un carnassier des forêts, au corps très allongé, presque serpentin, pourvu de huit pattes. Hormis ce nombre de pattes curieusement excédentaire (4 de chaque côté), qui lui donne l’air d’une chenille à fourrure, il pourrait ressembler à un long, très long vison. Adulte, il mesure en moyenne 2 m du museau au bout de la queue, pour un poids de 50 kg.

    \n

    Mœurs

    \n

    Très bon grimpeur, le furlong vit essentiellement dans les arbres où il se coule de branche en branche avec la rapidité et l’efficacité d’un serpent. Ses proies de prédilection sont les oiseaux et les rongeurs, mais poussé par la faim, il peut s’attaquer à des animaux aussi gros que les chevreuils, voire aux humains isolés. La fourrure de furlong est très recherchée.

    ","notesmj":"Notes du MJ","competencecreature[0]":{"data":{"carac_value":"10"}},"competencecreature[0]]":{"data":{"dommages":"+0"}},"competencecreature[1]":{"data":{"carac_value":"14"}},"competencecreature[1]]":{"data":{"dommages":"+0"}},"competencecreature[2]":{"data":{"carac_value":"14"}},"competencecreature[2]]":{"data":{"dommages":"+0"}},"competencecreature[3]":{"data":{"carac_value":"12"}},"competencecreature[3]]":{"data":{"dommages":"+0"}},"competencecreature[4]":{"data":{"carac_value":"12"}},"competencecreature[4]]":{"data":{"dommages":"+1"}},"competencecreature[5]":{"data":{"carac_value":"13"}},"competencecreature[5]]":{"data":{"dommages":"+0"}}},"sort":100001,"flags":{"core":{"sheetClass":"wfrp4e.RdDActorCreatureSheet"}},"img":"systems/foundryvtt-reve-de-dragon/icons/creatures/furlong.svg","token":{"flags":{},"name":"Furlong","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/creatures/furlong.svg","tint":null,"width":1,"height":1,"scale":1,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightAlpha":1,"lightAnimation":{"speed":5,"intensity":5},"actorId":"f31jeCsQgw3hWjk6","actorLink":false,"disposition":-1,"displayBars":0,"bar1":{},"bar2":{},"randomImg":false},"items":[{"_id":"shsUV8UpU18c0RJK","name":"Course","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":10,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":100000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.png","effects":[]},{"_id":"yDHZfK4RmwQW4YaW","name":"Discrétion","type":"competencecreature","data":{"categorie_parade":"","niveau":5,"default_diffLibre":0,"carac_value":14,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":200000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.png","effects":[]},{"_id":"4GmpkphbsmQjvVVK","name":"Escalade","type":"competencecreature","data":{"categorie_parade":"","niveau":5,"default_diffLibre":0,"carac_value":14,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":300000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_escalade.png","effects":[]},{"_id":"CYpxxf1uTa78NWR9","name":"Esquive","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":12,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":400000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.png","effects":[]},{"_id":"6DK46pyO0hzEuuUg","name":"Morsure","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":12,"iscombat":true,"isparade":false,"dommages":1,"description":""},"sort":500000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.png","effects":[]},{"_id":"lzEdMrKXbOYrWG5S","name":"Vigilance","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":13,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":600000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]}],"effects":[]} {"_id":"f6wzOaOzdwy51prt","name":"Goule","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"creature","data":{"carac":{"taille":{"type":"number","value":"11","label":"Taille","xp":0,"derivee":false},"constitution":{"type":"number","value":"14","label":"Constitution","xp":0,"derivee":false},"force":{"type":"number","value":"13","label":"Force","xp":0,"derivee":false},"perception":{"type":"number","value":"10","label":"Perception","xp":0,"derivee":false},"volonte":{"type":"number","value":"7","label":"Volonté","xp":0,"derivee":false},"reve":{"type":"number","value":"10","label":"Rêve","xp":0,"derivee":false}},"sante":{"vie":{"type":"number","max":13,"value":13,"label":"Vie","derivee":false},"endurance":{"type":"number","max":27,"value":27,"label":"Endurance","derivee":false},"sonne":{"value":false,"label":"Sonné"}},"blessures":{"legeres":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"graves":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"critiques":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]}},"attributs":{"plusdom":{"type":"number","value":"+1","label":"+dom","derivee":true},"vitesse":{"type":"string","value":"12/24","label":"Vitesse","derivee":true},"encombrement":{"type":"number","value":"0","label":"Encombrement","derivee":false},"protection":{"type":"number","value":"0","label":"Protection","derivee":false}},"compteurs":{"etat":{"value":0,"label":"Etat général"},"surenc":{"value":0,"label":"Sur-encombrement"}},"description":"

    Description

    \n

    Créature anthropomorphe, bipède et verticale, la goule ressemble à un cadavre décharné. Sa taille est celle d’un homme. Son cri, un hurlement rauque, glace le sang. Ses griffes sont particulièrement puissantes.

    \n

    Mœurs

    \n

    La goule est un charognard ayant une prédilection pour la chair humaine. Elle hante nécropoles, cimetières et champs de bataille, déterrant les cadavres dont elle se nourrit. Paranos le Moindre affirme qu’elle possède la faculté thanataire de pouvoir jeûner des mois entiers, voire des années, en n’absorbant qu’un peu de terre. Cela ne l’empêche pas de désirer ardemment de la chair, bien au contraire. Et si elle est lâche isolée, elle est très agressive en bande. Pour corser le tout, sa morsure inocule un venin qui paralyse.

    \n

    Venin

    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    Malignité6
    Périodicité1 round
    Dommages1 ligne de fatigue
    Antidotes-4 \\ Floume-dhu +16
    \n

    La paralysie intervient quand toutes les lignes de fatigue sont pleines et dure 6 heures.

    \n

    Le floume-dhu est obtenu en mélangeant en quantités égales gelée de floumette et lait humain (pour une dose\": une demi-mesure de chaque). Puis chauffer le mélange jusqu’à couleur bleu-sangue (-2).

    ","notesmj":"Notes du MJ","competencecreature[0]":{"data":{"carac_value":"10"}},"competencecreature[0]]":{"data":{"dommages":"+0"}},"competencecreature[1]":{"data":{"carac_value":"10"}},"competencecreature[1]]":{"data":{"dommages":"+0"}},"competencecreature[2]":{"data":{"carac_value":"10"}},"competencecreature[2]]":{"data":{"dommages":"+0"}},"competencecreature[3]":{"data":{"carac_value":"13"}},"competencecreature[3]]":{"data":{"dommages":"+1"}},"competencecreature[4]":{"data":{"carac_value":"10"}},"competencecreature[4]]":{"data":{"dommages":"+0"}}},"sort":100001,"flags":{},"img":"icons/svg/mystery-man.svg","token":{"flags":{},"name":"Goule","displayName":0,"img":"icons/svg/mystery-man.svg","tint":null,"width":1,"height":1,"scale":1,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightAlpha":1,"lightAnimation":{"speed":5,"intensity":5},"actorId":"f6wzOaOzdwy51prt","actorLink":false,"disposition":-1,"displayBars":0,"bar1":{},"bar2":{},"randomImg":false},"items":[{"_id":"shsUV8UpU18c0RJK","name":"Course","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":10,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":100000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.png","effects":[]},{"_id":"yDHZfK4RmwQW4YaW","name":"Discrétion","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":10,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":200000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.png","effects":[]},{"_id":"CYpxxf1uTa78NWR9","name":"Esquive","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":10,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":300000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.png","effects":[]},{"_id":"BjqRrGtHtTzuNpZB","name":"Griffes et Crocs","type":"competencecreature","data":{"categorie_parade":"","niveau":4,"default_diffLibre":0,"carac_value":13,"iscombat":true,"isparade":false,"dommages":1,"description":""},"sort":400000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.png","effects":[]},{"_id":"lzEdMrKXbOYrWG5S","name":"Vigilance","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":10,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":500000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]}],"effects":[]} +{"_id":"i7pvn7kgTwIdKYtP","name":"Mule","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"creature","data":{"carac":{"taille":{"type":"number","value":"23","label":"Taille","xp":0,"derivee":false},"constitution":{"type":"number","value":"17","label":"Constitution","xp":0,"derivee":false},"force":{"type":"number","value":"17","label":"Force","xp":0,"derivee":false},"perception":{"type":"number","value":"12","label":"Perception","xp":0,"derivee":false},"volonte":{"type":"number","value":"12","label":"Volonté","xp":0,"derivee":false},"reve":{"type":"number","value":"12","label":"Rêve","xp":0,"derivee":false}},"sante":{"vie":{"type":"number","max":20,"value":20,"label":"Vie","derivee":false},"endurance":{"type":"number","max":40,"value":40,"label":"Endurance","derivee":false},"sonne":{"value":false,"label":"Sonné"}},"blessures":{"legeres":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":"","loc":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":"","loc":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":"","loc":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":"","loc":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":"","loc":""}]},"graves":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":"","loc":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":"","loc":""}]},"critiques":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":"","loc":""}]}},"attributs":{"plusdom":{"type":"number","value":"+4","label":"+dom","derivee":true},"vitesse":{"type":"string","value":"12/40","label":"Vitesse","derivee":true},"encombrement":{"type":"number","value":"18","label":"Encombrement","derivee":false},"protection":{"type":"number","value":"1","label":"Protection","derivee":false}},"compteurs":{"etat":{"value":0,"label":"Etat général"},"surenc":{"value":0,"label":"Sur-encombrement"}},"description":"

    Description

    \n

    La mule est une le croisement entre un cheval et une ânesse. Adulte, la mule pèse 300 kg pour 1m65 au garrot.

    ","notesmj":"Notes du MJ","competencecreature[0]":{"data":{"carac_value":"12","niveau":"+3"}},"competencecreature[0]]":{"data":{"dommages":"+0"}},"competencecreature[1]":{"data":{"carac_value":"8","niveau":"+3"}},"competencecreature[1]]":{"data":{"dommages":"+0"}},"competencecreature[2]":{"data":{"carac_value":"12","niveau":"+2"}},"competencecreature[2]]":{"data":{"dommages":"+1"}},"competencecreature[3]":{"data":{"carac_value":"12","niveau":"+0"}},"competencecreature[3]]":{"data":{"dommages":"+0"}},"competencecreature[4]":{"data":{"carac_value":"13","niveau":"+3"}},"competencecreature[4]]":{"data":{"dommages":"+3"}}},"sort":100001,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/creatures/mule.svg","token":{"flags":{},"name":"Mule","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/creatures/mule.svg","tint":"","width":2,"height":2,"scale":1,"mirrorX":false,"mirrorY":false,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightColor":"","lightAlpha":1,"lightAnimation":{"type":"","speed":5,"intensity":5},"actorId":"i7pvn7kgTwIdKYtP","actorLink":false,"disposition":0,"displayBars":0,"bar1":{"attribute":""},"bar2":{"attribute":""},"randomImg":false},"items":[{"_id":"shsUV8UpU18c0RJK","name":"Course","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":12,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":100000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.png","effects":[]},{"_id":"CYpxxf1uTa78NWR9","name":"Esquive","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":8,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":200000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.png","effects":[]},{"_id":"6DK46pyO0hzEuuUg","name":"Morsure","type":"competencecreature","data":{"categorie_parade":"","niveau":2,"default_diffLibre":0,"carac_value":12,"iscombat":true,"isparade":false,"dommages":1,"description":""},"sort":300000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.png","effects":[]},{"_id":"lzEdMrKXbOYrWG5S","name":"Vigilance","type":"competencecreature","data":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":12,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":400000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]},{"_id":"3MgAaUHeKGBcbyr5","name":"Coup de pied","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":13,"iscombat":true,"isparade":false,"dommages":3,"description":null},"sort":500000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Zpl2Bi451vB3r91W"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-coup_de_pied.png","effects":[]}],"effects":[]} {"_id":"icS4ht40EGkUbUus","name":"Rananècre","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"creature","data":{"carac":{"taille":{"type":"number","value":"10","label":"Taille","xp":0,"derivee":false},"constitution":{"type":"number","value":"10","label":"Constitution","xp":0,"derivee":false},"force":{"type":"number","value":"10","label":"Force","xp":0,"derivee":false},"perception":{"type":"number","value":"10","label":"Perception","xp":0,"derivee":false},"volonte":{"type":"number","value":"10","label":"Volonté","xp":0,"derivee":false},"reve":{"type":"number","value":"10","label":"Rêve","xp":0,"derivee":false}},"sante":{"vie":{"type":"number","max":10,"value":10,"label":"Vie","derivee":false},"endurance":{"type":"number","max":10,"value":10,"label":"Endurance","derivee":false},"sonne":{"value":false,"label":"Sonné"}},"blessures":{"legeres":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"graves":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"critiques":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]}},"attributs":{"plusdom":{"type":"number","value":"0","label":"+dom","derivee":true},"vitesse":{"type":"string","value":"0","label":"Vitesse","derivee":true},"encombrement":{"type":"number","value":"0","label":"Encombrement","derivee":false},"protection":{"type":"number","value":"0","label":"Protection","derivee":false}},"compteurs":{"etat":{"value":0,"label":"Etat général"},"surenc":{"value":0,"label":"Sur-encombrement"}},"description":"

    Description

    \n

    Le rananècre est un rat géant de la taille d’un chien, au pelage gris moisi, pesant en moyenne 35 kg. Sa morsure inocule une horrible maladie : la nécrophase.

    \n

    Mœurs

    \n

    Le rananècre vit dans les désolations, les anciennes ruines, partout où les courants lourds du cauchemar ont laissé leur empreinte. Sa présence s’accompagne souvent d’entités de cauchemar non incarnées (haines, désespoirs).

    \n

    Nécrophase

    \n

    Tout autour de la blessure, la chair s’enfle, vire au noir et se putréfie, puis l’ensemble du corps est gagné peu à peu. Si la mort survient, elle donne naissance à une entité de cauchemar non incarnée ayant le même nombre de points de rêve que la caractéristique RÊVE de la victime. Tirer 1d2 : 1 = haine ; 2 = désespoir.

    \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    Malignité7
    Périodicité1 heure
    Dommages-2 points de vie
    Antidotes-4 \\ Tournegraisse +16, Huile de Sélikanthe +6
    \n

     

    ","notesmj":"Notes du MJ","competencecreature[0]":{"data":{"carac_value":"11","niveau":"+3"}},"competencecreature[0]]":{"data":{"dommages":"+1"}},"competencecreature[1]":{"data":{"carac_value":"10","niveau":"+2"}},"competencecreature[1]]":{"data":{"dommages":"+0"}},"competencecreature[2]":{"data":{"carac_value":"11","niveau":"+3"}},"competencecreature[2]]":{"data":{"dommages":"+0"}},"competencecreature[3]":{"data":{"carac_value":"10","niveau":"+3"}},"competencecreature[3]]":{"data":{"dommages":"+0"}},"competencecreature[4]":{"data":{"carac_value":"10","niveau":"+3"}},"competencecreature[4]]":{"data":{"dommages":"+0"}}},"sort":100001,"flags":{},"img":"icons/svg/mystery-man.svg","token":{"flags":{},"name":"Quileurbist","displayName":0,"img":"icons/svg/mystery-man.svg","tint":null,"width":1,"height":1,"scale":1,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightAlpha":1,"lightAnimation":{"speed":5,"intensity":5},"actorId":"icS4ht40EGkUbUus","actorLink":false,"disposition":-1,"displayBars":0,"bar1":{},"bar2":{},"randomImg":false},"items":[{"_id":"0z35nbSeViandim4","name":"Morsure (maladie)","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":11,"iscombat":true,"isparade":false,"dommages":1,"description":""},"sort":100000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.6DK46pyO0hzEuuUg"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.png","effects":[]},{"_id":"w1BjJ6evq83ZMieY","name":"Esquive","type":"competencecreature","data":{"categorie_parade":"","niveau":2,"default_diffLibre":0,"carac_value":10,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":200000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.CYpxxf1uTa78NWR9"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.png","effects":[]},{"_id":"dv9QLfHGa5ZwDN7l","name":"Course","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":11,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":300000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.shsUV8UpU18c0RJK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.png","effects":[]},{"_id":"VdLbNp5bz8hU6KDl","name":"Discrétion","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":10,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":400000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yDHZfK4RmwQW4YaW"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.png","effects":[]},{"_id":"TXC25fwUDxF6Qp5A","name":"Vigilance","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":10,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":500000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.lzEdMrKXbOYrWG5S"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]}],"effects":[]} {"_id":"igtHarwizNIUhd8M","name":"Glipzouk","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"creature","data":{"carac":{"taille":{"type":"number","value":"6","label":"Taille","xp":0,"derivee":false},"constitution":{"type":"number","value":"10","label":"Constitution","xp":0,"derivee":false},"force":{"type":"number","value":"9","label":"Force","xp":0,"derivee":false},"perception":{"type":"number","value":"14","label":"Perception","xp":0,"derivee":false},"volonte":{"type":"number","value":"11","label":"Volonté","xp":0,"derivee":false},"reve":{"type":"number","value":"12","label":"Rêve","xp":0,"derivee":false}},"sante":{"vie":{"type":"number","max":8,"value":8,"label":"Vie","derivee":false},"endurance":{"type":"number","max":18,"value":18,"label":"Endurance","derivee":false},"sonne":{"value":false,"label":"Sonné"}},"blessures":{"legeres":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"graves":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"critiques":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]}},"attributs":{"plusdom":{"type":"number","value":"-1","label":"+dom","derivee":true},"vitesse":{"type":"string","value":"12/26","label":"Vitesse","derivee":true},"encombrement":{"type":"number","value":"0","label":"Encombrement","derivee":false},"protection":{"type":"number","value":"0","label":"Protection","derivee":false}},"compteurs":{"etat":{"value":0,"label":"Etat général"},"surenc":{"value":0,"label":"Sur-encombrement"}},"description":"

    Manque

    \n

    Saut

    \n

    Description

    \n

    Le glipzouk, ou singe vert, a la morphologie générale du ouistiti, membres minces et longue queue préhensile, avec un pelage uniformément vert amande, sauf le museau et le ventre qui sont blancs. Des épaules à la naissance de la queue, il mesure 1 m en moyenne, la queue pouvant, elle, atteindre le double. Ses quatre mains sont extrêmement habiles, et comme tous les singes, il est d’une agilité diabolique. Le glipzouk doit son nom à son «langage». On dirait presque un véritable parler, avec des syllabes articulées et une intonation générale, sauf que glip et zouk sont les seuls phonèmes qu’il emploie, en les prononçant sur tous les tons et en les mélangeant en d’infinies variations.

    \n

    Mœurs

    \n

    Paisibles, les colonies de glipzouks vivent en milieu boisé, se nourrissant de pousses et de fruits. Très bon observateur et non moins excellent imitateur, le glipzouk est un voleur et un pickpocket né. Il vaut mieux éviter de laisser traîner ses a!aires quand on voyage dans une région peuplée de glipzouks, et la nuit, être particulièrement vigilant en montant la garde. Non agressif, le glipzouk ne se bat que s’il est acculé sans pouvoir fuir.

    ","notesmj":"Notes du MJ","competencecreature[0]":{"data":{"carac_value":"10"}},"competencecreature[0]]":{"data":{"dommages":"+1"}},"competencecreature[1]":{"data":{"carac_value":"15"}},"competencecreature[1]]":{"data":{"dommages":"+0"}},"competencecreature[2]":{"data":{"carac_value":"14"}},"competencecreature[2]]":{"data":{"dommages":"+0"}},"competencecreature[3]":{"data":{"carac_value":"14"}},"competencecreature[3]]":{"data":{"dommages":"+0"}},"competencecreature[4]":{"data":{"carac_value":"14"}},"competencecreature[4]]":{"data":{"dommages":"+0"}},"competencecreature[5]":{"data":{"carac_value":"15"}},"competencecreature[5]]":{"data":{"dommages":"+0"}},"competencecreature[6]":{"data":{"carac_value":"15"}},"competencecreature[6]]":{"data":{"dommages":"+0"}}},"sort":100001,"flags":{"core":{"sheetClass":"wfrp4e.RdDActorCreatureSheet"}},"img":"systems/foundryvtt-reve-de-dragon/icons/creatures/glipzouk.svg","token":{"flags":{},"name":"Glipzouk","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/creatures/glipzouk.svg","tint":null,"width":1,"height":1,"scale":1,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightAlpha":1,"lightAnimation":{"speed":5,"intensity":5},"actorId":"igtHarwizNIUhd8M","actorLink":false,"disposition":-1,"displayBars":0,"bar1":{},"bar2":{},"randomImg":false},"items":[{"_id":"bwJZ6nTLX9hohV7Q","name":"Morsure","type":"competencecreature","data":{"categorie_parade":"","niveau":1,"default_diffLibre":0,"carac_value":10,"iscombat":true,"isparade":false,"dommages":1,"description":""},"sort":100000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.6DK46pyO0hzEuuUg"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.png","effects":[]},{"_id":"7td0EmFMtpwNyWwo","name":"Esquive","type":"competencecreature","data":{"categorie_parade":"","niveau":6,"default_diffLibre":0,"carac_value":15,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":200000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.CYpxxf1uTa78NWR9"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.png","effects":[]},{"_id":"d2yxJ5c57vMatAQV","name":"Discrétion","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":14,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":300000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yDHZfK4RmwQW4YaW"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.png","effects":[]},{"_id":"aGm8xRr55CPUo5rM","name":"Pickpocket","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":14,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":400000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.sUdXhpuVVOAlcVpo"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_pickpocket.png","effects":[]},{"_id":"bL7lL688cp1s1Vke","name":"Vigilance","type":"competencecreature","data":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":14,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":500000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.lzEdMrKXbOYrWG5S"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]},{"_id":"Fu61NMCeLxi9nfSD","name":"Course","type":"competencecreature","data":{"categorie_parade":"","niveau":6,"default_diffLibre":0,"carac_value":15,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":600000,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.shsUV8UpU18c0RJK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.png","effects":[]},{"_id":"uW9fTmhw6GBnf1e9","name":"Saut","type":"competencecreature","data":{"categorie_parade":"","niveau":6,"default_diffLibre":0,"carac_value":15,"iscombat":false,"isparade":false,"dommages":0,"description":null},"sort":700000,"flags":{"core":{"sourceId":"Item.JZDgJ7ySiV84llkK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.png","effects":[]}],"effects":[]} {"_id":"kPDswxsWVnSYitfL","name":"Drakkule","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"creature","data":{"carac":{"taille":{"type":"number","value":"4","label":"Taille","xp":0,"derivee":false},"constitution":{"type":"number","value":"10","label":"Constitution","xp":0,"derivee":false},"force":{"type":"number","value":"8","label":"Force","xp":0,"derivee":false},"perception":{"type":"number","value":"12","label":"Perception","xp":0,"derivee":false},"volonte":{"type":"number","value":"7","label":"Volonté","xp":0,"derivee":false},"reve":{"type":"number","value":"7","label":"Rêve","xp":0,"derivee":false}},"sante":{"vie":{"type":"number","max":7,"value":7,"label":"Vie","derivee":false},"endurance":{"type":"number","max":17,"value":17,"label":"Endurance","derivee":false},"sonne":{"value":false,"label":"Sonné"}},"blessures":{"legeres":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"graves":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""},{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]},"critiques":{"liste":[{"active":false,"premiers_soins":0,"soins_complets":0,"jours":0,"localisation":""}]}},"attributs":{"plusdom":{"type":"number","value":"-1","label":"+dom","derivee":true},"vitesse":{"type":"string","value":"12/38","label":"Vitesse","derivee":true},"encombrement":{"type":"number","value":"0","label":"Encombrement","derivee":false},"protection":{"type":"number","value":"-3","label":"Protection","derivee":false}},"compteurs":{"etat":{"value":0,"label":"Etat général"},"surenc":{"value":0,"label":"Sur-encombrement"}},"description":"

    Manque

    \n

    Contre, Esquive Vol

    \n

    Description

    \n

    Le drakkule, également surnommé chauve- souris dragon, est un énorme chiroptère vampire pouvant atteindre 20 kg pour 4 m d’envergure. Paranos le Moindre suggère que son surnom vient sûrement de ce que les mythiques Dragons du Premier Âge étaient censés posséder les mêmes grandes ailes membraneuses et le même goût du sang. Serions-nous alors dans un rêve de chauve-souris ? Je suppose que c’est encore une de vos plaisanteries, cher Paranos !

    \n

    Mœurs

    \n

    Comme les chauves-souris, les drakkules sont nocturnes, repliés le jour dans des cavernes ou autres lieux sombres, pour ne sortir chasser qu’à la tombée de la nuit. Comme pour la plupart des grands prédateurs, l’homme est pour eux une proie comme les autres.

    \n

    En combat, quand un drakkule réussit une particulière et cause au moins une blessure légère, il reste accroché à sa victime qui perd alors automatiquement 1d6 points d’endurance par round sous l’effet de la saignée. Quand l’endurance tombe à zéro, le drakkule continue à la vider de son sang à raison de 1d6 points de vie par round. Le drakkule ne se détache que blessé gravement ou sonné. Pour se dégager, la victime ne peut utiliser que Corps à corps (totaliser 2 points d’empoignade) ou une dague. Tant qu’il est accroché, le drakkule ne joue plus de jet d’attaque, puisqu’il cause des dommages automatiques, mais peut contrer empoignade ou attaque de dague par le battement de ses ailes.

    ","notesmj":"Notes du MJ","competencecreature[0]":{"data":{"carac_value":"10"}},"competencecreature[0]]":{"data":{"dommages":"+0"}},"competencecreature[1]":{"data":{"carac_value":"10"}},"competencecreature[1]]":{"data":{"dommages":"+0"}},"competencecreature[2]":{"data":{"carac_value":"10"}},"competencecreature[2]]":{"data":{"dommages":"+0"}}},"sort":100001,"flags":{"core":{"sheetClass":"wfrp4e.RdDActorCreatureSheet"}},"img":"systems/foundryvtt-reve-de-dragon/icons/creatures/drakkule.svg","token":{"flags":{},"name":"Drakkule","displayName":0,"img":"systems/foundryvtt-reve-de-dragon/icons/creatures/drakkule.svg","tint":null,"width":1,"height":1,"scale":1,"lockRotation":false,"rotation":0,"vision":false,"dimSight":0,"brightSight":0,"dimLight":0,"brightLight":0,"sightAngle":360,"lightAngle":360,"lightAlpha":1,"lightAnimation":{"speed":5,"intensity":5},"actorId":"kPDswxsWVnSYitfL","actorLink":false,"disposition":-1,"displayBars":0,"bar1":{},"bar2":{},"randomImg":false},"items":[{"_id":"CYpxxf1uTa78NWR9","name":"Esquive","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":10,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":900000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.png","effects":[]},{"_id":"6DK46pyO0hzEuuUg","name":"Morsure","type":"competencecreature","data":{"categorie_parade":"","niveau":2,"default_diffLibre":0,"carac_value":10,"iscombat":true,"isparade":false,"dommages":0,"description":""},"sort":1150000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.png","effects":[]},{"_id":"Kt7WlB5Ui97X211z","name":"Vol","type":"competencecreature","data":{"categorie_parade":"","niveau":3,"default_diffLibre":0,"carac_value":10,"iscombat":false,"isparade":false,"dommages":0,"description":""},"sort":1900000,"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-vol.png","effects":[]}],"effects":[]} diff --git a/packs/equipement.db b/packs/equipement.db index 59a2070e..8fe186ed 100644 --- a/packs/equipement.db +++ b/packs/equipement.db @@ -1,13 +1,13 @@ {"_id":"0Vgscex1VV4ybSUQ","name":"Bonnet de laine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.05,"equipe":false,"resistance":0,"qualite":0,"cout":0.06},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bonnet_laine.webp","effects":[]} {"_id":"0ylGrNMzulUaKFP9","name":"Boralm","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"ingredient","data":{"description":"

    Poudre brune apparaissant sur les parois des grottes.

    \n

    VUE/Alchimie à -1.

    ","niveau":0,"encombrement":0.001,"base":0,"quantite":1,"milieu":"Cavernes","rarete":"","categorie":"Alchimie","cout":0.03},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/boralm.webp","effects":[]} {"_id":"1Dc4KzZageae7lhI","name":"Balles de jongleur","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":4,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.32},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/balle_jongleur.webp","effects":[]} -{"_id":"1O7IJiQSDYxJ5VsD","name":"Bouclier moyen","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"0","force":"11","resistance":15,"competence":"Bouclier","cout":6,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"boucliers","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_moyen.webp","effects":[]} +{"_id":"1O7IJiQSDYxJ5VsD","name":"Bouclier moyen","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"0","force":"11","resistance":15,"competence":"Bouclier","cout":6,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"boucliers","penetration":0,"magique":false,"resistance_magique":null,"ecaille_efficacite":null,"initpremierround":"hast"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_moyen.webp","effects":[]} {"_id":"2y61gBIFbATQaKDl","name":"1 m2 de laine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/tissu_laine.webp","effects":[]} {"_id":"3DJePXhrDWQxbUeM","name":"Dé à jouer en os","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/des_en_os.webp","effects":[]} -{"_id":"3Wk5dzp3M7Das6wh","name":"Épée dragonne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    C’est une épée longue, plus robuste que l’esparlongue, pouvant également frapper de taille.

    ","quantite":1,"encombrement":2,"equipe":false,"dommages":"3","force":"11","resistance":12,"competence":"Epée à 1 main","cout":20,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"categorie_parade":"epees-longues","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_dragonne.webp","effects":[]} {"_id":"3cn9nWtY0Vb1PLTx","name":"Dague de jet","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    Chaque point de force au dessus de 10 augmente les portées de 1m.

    \n

    Chaque point de force en dessous de 9 diminue les portées de 1m.

    ","quantite":1,"encombrement":0.5,"equipe":false,"dommages":"1","force":"0","resistance":0,"competence":"Dague de jet","cout":3,"portee_courte":3,"portee_moyenne":8,"portee_extreme":15,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/dagues.webp","effects":[]} {"_id":"3mHSocNVPyWkmGBR","name":"Nartha","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"ingredient","data":{"description":"

    Poudre noire obtenue par disruption alchimique du minerai appelé narthalide, sorte de marne.

    \n

    VUE/Alchimie à -3

    ","niveau":0,"encombrement":0.001,"base":0,"quantite":1,"milieu":"","rarete":"","categorie":"Alchimie","cout":0.4},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/nartha.webp","effects":[]} {"_id":"3t0NhMC0cFQyCZGH","name":"Soufflet","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.4},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/soufflet.webp","effects":[]} +{"name":"Maillet","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"","description":"","quantite":1,"encombrement":0.1,"equipe":false,"dommages":"1","penetration":0,"force":"7","resistance":7,"competence":"Masse à 1 main","cout":0.05,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"initpremierround":"masse"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/maillet.webp","effects":[],"_id":"3uWCDH1NOjHJpVo1"} {"_id":"4GeV81qoJrjHIgzR","name":"Tournegraisse","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"potion","data":{"description":"

    Crème sirupeuse blanchâtre.

    ","quantite":1,"encombrement":0.1,"rarete":"","categorie":"Alchimie","cout":2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/tournegraisse.webp","effects":[]} {"_id":"4LFXefT0HFpaXQLx","name":"Briquet à silex","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.08,"equipe":false,"resistance":0,"qualite":0,"cout":0.4},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/briquet.webp","effects":[]} {"_id":"4qPaCKONcrsK6JbQ","name":"Pichet de grès (1 litre)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.5,"encombrement":0.3,"equipe":false,"qualite":0,"contenu":[],"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/pichet.webp","effects":[]} @@ -17,21 +17,20 @@ {"_id":"69vN8bRlnCrRHQCm","name":"Obbadion","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"ingredient","data":{"description":"

    Poudre bleuâtre obtenue par disruption alchimique du minerai appelé obbadine,  sorte de tourbe.

    \n

    VUE/Alchimie à -2

    ","niveau":0,"encombrement":0.001,"base":0,"quantite":1,"milieu":"Lieux humides","rarete":"","categorie":"Alchimie","cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/l_obbadion.webp","effects":[]} {"_id":"6MVWA3DYbpw8122A","name":"Entonnoir de fer","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.15},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/entonnoir.webp","effects":[]} {"_id":"6fW8gPkxgeBCKA59","name":"Premier Chant Dérisoire","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"livre","data":{"description":"

    Les Chants Dérisoires de Yester l’Ancien ont été peu retranscrits, probablement à cause de leur ineptie fondamentale. En dénicher un exemplaire n’est donc déjà pas chose aisée. Le premier chant, cependant, peut être source de révélation pour les haut-rêvants. La découverte de ce sens caché demande un minimum de +4 en voie d’Hypnos et permet la synthèse du sort de Dérision. Sans son assimilation préalable, la synthèse de ce sort est totalement inenvisageable. Sa difficulté de lecture est de -5, son assimilation requiert 16 points de tâche, périodicité 1 heure.

    ","auteur":"Yester l’Ancien","quantite":1,"difficulte":-5,"points_de_tache":16,"encombrement":0,"xp":"","cout":0,"competence":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.png","effects":[]} -{"_id":"6s5QjArwz9w9JIGL","name":"Double dragonne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    Apparue vers la fin du Second Âge, c’était une grande épée à deux mains. Encombrante et prohibant le bouclier, c’était avant tout une épée de duel et de frime.

    ","quantite":1,"encombrement":4,"equipe":false,"dommages":"5","force":"13","resistance":13,"competence":"Epée à 2 mains","cout":50,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false,"categorie_parade":"epees-lourdes","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/double_dragonne.webp","effects":[]} -{"_id":"7B9sKLf4ipRyyEjF","name":"Bouclier lourd","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"0","force":"13","resistance":20,"competence":"Bouclier","cout":8,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"boucliers","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_grand.webp","effects":[]} +{"_id":"6s5QjArwz9w9JIGL","name":"Double dragonne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    Apparue vers la fin du Second Âge, c’était une grande épée à deux mains. Encombrante et prohibant le bouclier, c’était avant tout une épée de duel et de frime.

    ","quantite":1,"encombrement":4,"equipe":false,"dommages":"5","force":"13","resistance":13,"competence":"Epée à 2 mains","cout":50,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false,"categorie_parade":"epees-lourdes","penetration":0,"magique":false,"resistance_magique":null,"ecaille_efficacite":null,"initpremierround":"hast"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/double_dragonne.webp","effects":[]} +{"_id":"7B9sKLf4ipRyyEjF","name":"Bouclier lourd","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"0","force":"13","resistance":20,"competence":"Bouclier","cout":8,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"boucliers","penetration":0,"magique":false,"resistance_magique":null,"ecaille_efficacite":null,"initpremierround":"hast"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_grand.webp","effects":[]} {"_id":"7YuWWsFIuZgakGUS","name":"Mortier en marbre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.3,"equipe":false,"resistance":0,"qualite":0,"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/mortier.webp","effects":[]} {"_id":"7c7CO626TCo4lg8b","name":"Petite scie cadre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"resistance":0,"qualite":0,"cout":6},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/scie.webp","effects":[]} {"_id":"7u9yAlaFhKcVdEC6","name":"Matériel de chirurgie","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"

    (pincettes, lancette, crin, aiguille)

    ","quantite":1,"encombrement":0.06,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/materiel_chirurgie.webp","effects":[]} -{"_id":"7xFe41JZIVNMLv1U","name":"Masse lourde","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"3/4","force":"12/11","resistance":10,"competence":"Masse à 1 main","cout":4,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true,"categorie_parade":"masses","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/masse_lourde.webp","effects":[]} {"_id":"8bwP6zncdFP0O9ew","name":"Corde (10 m)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/corde.webp","effects":[]} +{"name":"Massette","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"","description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","penetration":0,"force":"9","resistance":8,"competence":"Masse à 1 main","cout":2,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"initpremierround":"masse"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/massette.webp","effects":[],"_id":"92GDNmNVa2u0gzpx"} {"_id":"9cLkTDugz84gpHUB","name":"Bitume de Camphre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"potion","data":{"description":"

    Crème sirupeuse grisâtre.

    ","quantite":1,"encombrement":0.1,"rarete":"","categorie":"Alchimie","cout":2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bitume_de_camphre.webp","effects":[]} -{"_id":"9jbjDpbddL2Ep09s","name":"Hache de bataille","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"3/4","force":"12/11","resistance":8,"competence":"Hache à 1 main","cout":15,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true,"categorie_parade":"haches","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/hache_bataille.webp","effects":[]} {"_id":"A3jx5dPkk5IeXSXn","name":"Lait de lune","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"potion","data":{"description":"

    Fluide.

    \n

    Lait de laie.

    ","quantite":1,"encombrement":0.1,"rarete":"","categorie":"Alchimie","cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/lait_de_lune.webp","effects":[]} {"_id":"A9nMgTyEwYzdA0zT","name":"Manteau de velours","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"resistance":0,"qualite":0,"cout":10},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/manteau_velours.webp","effects":[]} {"_id":"AOQsKTjIbcy8NV9t","name":"Pierre à aiguiser","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/pierre_a_aiguiser.webp","effects":[]} {"_id":"As5kYvyOrWrr8KJm","name":"Etui à luth de cuir","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":1,"encombrement":0.2,"equipe":false,"qualite":0,"contenu":[],"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/etui_luth.webp","effects":[]} {"_id":"B2BhuxveVKMnD8fe","name":"Bottes de cuir souple","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.4,"equipe":false,"resistance":0,"qualite":0,"cout":2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bottes_de_cuir.webp","effects":[]} -{"_id":"CGYOJbaKtYvF2qa9","name":"Dague","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":0.5,"equipe":false,"dommages":"1","force":"7","resistance":8,"competence":"Dague","cout":3,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"categorie_parade":"dagues","penetration":0},"flags":{"core":{"sheetClass":""}},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/dague.webp","effects":[]} +{"name":"Couteau de cuisine","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"dagues","description":"","quantite":1,"encombrement":0.2,"equipe":false,"dommages":"1","penetration":0,"force":"0","resistance":6,"competence":"Dague","cout":1,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"initpremierround":"dague"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/couteau-cuisine.webp","effects":[],"_id":"BQPhNy9AUCpEGgFg"} {"_id":"CMtQM06J3BZsHHxH","name":"Sandales","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/sandales.webp","effects":[]} {"_id":"CQSxJv1mgmIeMCbM","name":"Grappin","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.5,"equipe":false,"resistance":0,"qualite":0,"cout":2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/grappin.webp","effects":[]} {"_id":"D5Z3FaUv91B8eCOP","name":"Obyssum vert","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"ingredient","data":{"description":"

    Poudre verdâtre apparaissant sur les tiges de certains roseaux.

    \n

    VUE/Alchimie à -2

    ","niveau":0,"encombrement":0.001,"base":0,"quantite":1,"milieu":"Lieux humides","rarete":"","categorie":"Alchimie","cout":0.05},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/l_obyssum_vert.webp","effects":[]} @@ -47,39 +46,38 @@ {"_id":"GGiwmc4sjGW3GS6K","name":"Provisions non-cuites (1 sust)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"

    légumes secs, viande salée

    ","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.01},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp","effects":[]} {"_id":"GiquTnEsiVZn7m6Y","name":"Bas de soie","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0,"equipe":false,"resistance":0,"qualite":0,"cout":3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bas_soie.webp","effects":[]} {"_id":"Gp9ZrwXkqZbJoVVT","name":"1 m² de toile de voile","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/voile.webp","effects":[]} -{"_id":"HRLrRhAF4Hkfbqjh","name":"Fléau lourd","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"4","force":"13","resistance":10,"competence":"Fléau","cout":15,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":true,"categorie_parade":"","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/fleau_lourd.webp","effects":[]} +{"_id":"HdciYu5J2SrJO8e3","name":"Épée gnome","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"epees-courtes","description":"

    C’est une épée courte, essentiellement fabriquée et portée par les Gnomes au Second Âge.

    ","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","penetration":0,"force":"8","resistance":12,"competence":"Epée à 1 main","cout":12,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"initpremierround":"epeegnome"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.webp","effects":[]} +{"name":"Rasoir","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"dagues","description":"","quantite":1,"encombrement":0.1,"equipe":false,"dommages":"1","penetration":0,"force":"0","resistance":0,"competence":"Dague","cout":2,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"initpremierround":"dague"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/rasoir.webp","effects":[],"_id":"HjbB4f1CDz96Hv88"} {"_id":"HsIJSPQ46cec22Y2","name":"Couverture de laine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.6,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/couverture_laine.webp","effects":[]} {"_id":"Ig9qIzaZ5SveXLF7","name":"Pelle","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/pelle.webp","effects":[]} -{"_id":"IlA16EWR1x5ZBckA","name":"Épée demi-dragonne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":null,"quantite":1,"encombrement":1.5,"equipe":false,"dommages":"2","force":"10","resistance":10,"competence":"Epée à 1 main","cout":15,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"categorie_parade":"epees-longues","penetration":0},"flags":{"core":{"sourceId":"Item.ErwaSLcGryAbYjkm"}},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/demi_dragonne.webp","effects":[]} {"_id":"InTxnjInfBYHsqcR","name":"Poêle à frire (40 cm)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.5,"encombrement":0.3,"equipe":false,"qualite":0,"contenu":[],"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/poele.webp","effects":[]} -{"_id":"J4PpWO4OZ6JPaAUB","name":"Fléau léger","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"3","force":"12","resistance":10,"competence":"Fléau","cout":12,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":true,"categorie_parade":"","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/fleau_leger.webp","effects":[]} {"_id":"JXMef7FXVOG1XYWO","name":"Elixir des gnomes","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"potion","data":{"description":"

    Fluide.

    \n

    Liqueur violette.

    ","quantite":1,"encombrement":0.1,"rarete":"","categorie":"Alchimie","cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/elixir_des_gnomes.webp","effects":[]} {"_id":"JfxFBlokIegRWTDo","name":"Torche 1/2 heure (60 min)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.3,"equipe":false,"resistance":0,"qualite":0,"cout":0.02},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/torche.webp","effects":[]} {"_id":"JhQZDbsmFZBLRcln","name":"Sac en jute (20 litres)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":10,"encombrement":0.05,"equipe":false,"qualite":0,"contenu":[],"cout":0.04},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/sac_jute_20.webp","effects":[]} -{"_id":"K1ssvF9alBaIwrSu","name":"Maillet","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"dommages":"1","force":"7","resistance":7,"competence":"Masse à 1 main","cout":0.05,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"masses","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/maillet.webp","effects":[]} {"_id":"K4n2JuDnoHDUPCZG","name":"Bouilloire de fer (2 litres)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":1,"encombrement":0.5,"equipe":false,"qualite":0,"contenu":[],"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bouilloire.webp","effects":[]} {"_id":"KQZIK8ltQ3sQiDGe","name":"Mailles de Fer","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"

    Grand haubert de mailles avec capuche À enfiler sur une cotte de cuir souple ou de drap matelassé) + bottes de cuir / métal.

    \n

     

    ","quantite":1,"encombrement":6,"equipe":false,"protection":5,"deterioration":null,"malus":-4,"cout":50},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/mailles.webp","effects":[]} {"_id":"KlydiUbayqBgJB6J","name":"Tablette de cire","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/tablette_cire.webp","effects":[]} -{"_id":"KmfftnkUsPQD6fV0","name":"Épée bâtarde","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    Comme son nom l’indique, c’est une bâtarde de l'épée longue et de l'épée sorde, à la fois longue et large, pouvant s’utiliser à une ou deux mains.

    ","quantite":1,"encombrement":3,"equipe":false,"dommages":"4/5","force":"13/12","resistance":14,"competence":"Epée à 1 main","cout":30,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true,"categorie_parade":"epees-lourdes","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_batarde.webp","effects":[]} {"_id":"KvzSNxISkWDoilO8","name":"Gemme Inconnue","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":null,"equipe":false,"resistance":0,"qualite":0,"cout":0},"flags":{"core":{"sourceId":"Item.V3V3wUXNCG6gzJFB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/gemmes/seliphane.webp","effects":[]} {"_id":"LZPEdSIv3KywCwdk","name":"Liquide","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"munition","data":{"description":"

    1 mesure (20cl) d'un liquide.

    \n

    (à modifier/compléter)

    ","quantite":1,"encombrement":0.1,"equipe":false,"qualite":0,"cout":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/liquides/liquide_neutre.webp","effects":[]} {"_id":"LaAP5tsP1Sc43hKO","name":"Lanterne à huile","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.3,"encombrement":1,"equipe":false,"qualite":0,"contenu":[],"cout":5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/lanterne_huile.webp","effects":[]} {"_id":"LkE8EjPfao9m6Rn7","name":"Huile de Sélikanthe","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"potion","data":{"description":"

    Fluide.

    \n

    Liquide légèrement huileux.

    ","quantite":1,"encombrement":0.1,"rarete":"","categorie":"Alchimie","cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/huile_de_selikanthe.webp","effects":[]} {"_id":"Lz4dA2NwxdSZ3FZK","name":"Lime, Râpe","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/lime.webp","effects":[]} {"_id":"M1RgJDuQUvxjqJVV","name":"Chandelle de suif (1 heure)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.02},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/chandelle.webp","effects":[]} +{"name":"Masse lourde","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"","description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"3/4","penetration":0,"force":"12/11","resistance":10,"competence":"Masse à 1 main","cout":4,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true,"initpremierround":"masse"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/masse_lourde.webp","effects":[],"_id":"MGvyXFQJpv6nNynl"} +{"name":"Épée bâtarde","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"epees-lourdes","description":"

    Comme son nom l’indique, c’est une bâtarde de l'épée longue et de l'épée sorde, à la fois longue et large, pouvant s’utiliser à une ou deux mains.

    ","quantite":1,"encombrement":3,"equipe":false,"dommages":"4/5","penetration":0,"force":"13/12","resistance":14,"competence":"Epée à 1 main","cout":30,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true,"initpremierround":"epeebatarde"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_batarde.webp","effects":[],"_id":"MQxgfYTEQEUhG116"} {"_id":"Mbh2M8JS1Rf0vxEX","name":"Harpe","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"resistance":0,"qualite":0,"cout":5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/harpe.webp","effects":[]} +{"name":"Dague","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"dagues","description":"","quantite":1,"encombrement":0.5,"equipe":false,"dommages":"1","penetration":0,"force":"7","resistance":8,"competence":"Dague","cout":3,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"initpremierround":"dague"},"flags":{"core":{"sheetClass":""}},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/dague.webp","effects":[],"_id":"NCp2kdTKmQGyAh1U"} {"_id":"NNLhxjFsoJVdFuit","name":"Bouteille de verre (1 litre)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.5,"encombrement":0.2,"equipe":false,"qualite":0,"contenu":[],"cout":0.7},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bouteille_verre.webp","effects":[]} {"_id":"OXFFRZOqlhZDJas3","name":"Béret de velours","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.05,"equipe":false,"resistance":0,"qualite":0,"cout":3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/beret_velours.webp","effects":[]} {"_id":"OYWzXiQUFsjU5AF2","name":"Perles de Bjwal","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"potion","data":{"description":"

    Petits granulés translucides.

    ","quantite":1,"encombrement":0.1,"rarete":"","categorie":"Alchimie","cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/perles_bjwal.webp","effects":[]} {"_id":"P0yc6QfgKVmM0fpu","name":"Ecuelle de grès","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/ecuelle_gres.webp","effects":[]} {"_id":"PH2J4zR0hwXSg0vc","name":"Charbon de bois 1 kg","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.04,"equipe":false,"resistance":0,"qualite":0,"cout":0.06},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/charbon.webp","effects":[]} +{"name":"Lance courte","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"lances","description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"2","penetration":0,"force":"8","resistance":5,"competence":"Lance","cout":3,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"initpremierround":"lance"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/lance.webp","effects":[],"_id":"PSc92VlQCdNnbPlg"} {"_id":"PaJoTirnA6h4F3pH","name":"Hameçon","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/hame%C3%A7on.webp","effects":[]} -{"_id":"PdrW7Zejz8H04zf8","name":"Couteau de cuisine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"dommages":"1","force":"0","resistance":6,"competence":"Dague","cout":1,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"dagues","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/couteau-cuisine.webp","effects":[]} {"_id":"PkDJ36j7mS3Kfetp","name":"Bouteille de grès (1 litre)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.5,"encombrement":0.3,"equipe":false,"qualite":0,"contenu":[],"cout":0.4},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bouteille_gres.webp","effects":[]} -{"_id":"PoTI2z0Wr4hxiLpQ","name":"Gourdin","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"1","force":"7","resistance":8,"competence":"Masse à 1 main","cout":0,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"categorie_parade":"masses","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/gourdin.webp","effects":[]} {"_id":"PrnJrG50u1UPdlJN","name":"Liqueur de Bagdol","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"potion","data":{"description":"

    Fluide. Liquide noir et odorant.

    ","quantite":1,"encombrement":0.1,"rarete":"","categorie":"Alchimie","cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp","effects":[]} {"_id":"PuuPn6WGfU8uBAyb","name":"Robe de soie","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0,"equipe":false,"resistance":0,"qualite":0,"cout":10},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/robe_soie.webp","effects":[]} -{"_id":"Q5jpA4N2vEdh2Qga","name":"Marteau","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":0.3,"equipe":false,"dommages":"2","force":"7","resistance":8,"competence":"Masse à 1 main","cout":1,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"masses","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/marteau.webp","effects":[]} +{"name":"Bâton","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"","description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"1","penetration":0,"force":"9","resistance":8,"competence":"Masse à 2 mains","cout":0.5,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false,"initpremierround":"baton"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/baton.webp","effects":[],"_id":"Qh4Tp7lZ6wLnX4w0"} {"_id":"RC1co7jmHMDqlJGy","name":"Deniers (pièces d'étain)","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.005,"equipe":false,"resistance":0,"qualite":0,"cout":0.01},"flags":{},"img":"icons/commodities/currency/coins-assorted-mix-platinum.webp","effects":[]} {"_id":"RGdDQ3yJYMkSuA5G","name":"Provisions cuites (1 sust)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"

    pain, fromage, viande séchée...

    ","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.02},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/provision_cuite.webp","effects":[]} {"_id":"RKr1ZhTvC6poiNa1","name":"Gros Clou","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.05},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/gros_clou.webp","effects":[]} @@ -96,18 +94,20 @@ {"_id":"SrV0r5hnGdKeSIHR","name":"Cuillère de bois","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.03,"equipe":false,"resistance":0,"qualite":0,"cout":0.03},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/cuillere_bois.webp","effects":[]} {"_id":"SsnGNjTekvB50uWa","name":"Chapeau de cuir souple","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.08,"equipe":false,"resistance":0,"qualite":0,"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/chapeau_cuir.webp","effects":[]} {"_id":"T9UiLcJonuHmGNwq","name":"Sols (pièces d'argent)","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.005,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"icons/commodities/currency/coins-assorted-mix-silver.webp","effects":[]} +{"name":"Hache de bataille","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"haches","description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"3/4","penetration":0,"force":"12/11","resistance":8,"competence":"Hache à 1 main","cout":15,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true,"initpremierround":"hachebataille"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/hache_bataille.webp","effects":[],"_id":"TKsUXJq9w7ezcFGQ"} {"_id":"TY6Ft8a6WfxD6pD9","name":"Bobineau de fil","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bobineau.webp","effects":[]} -{"_id":"U6qli6TPbzj8tUdH","name":"Arme d’hast","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":4,"equipe":false,"dommages":"4","force":"12","resistance":8,"competence":"Dague","cout":10,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false,"categorie_parade":"hast","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/hast.webp","effects":[]} {"_id":"UDmq6CY3NsttcHe4","name":"Peigne en corne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.04,"equipe":false,"resistance":0,"qualite":0,"cout":0.4},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/peigne.webp","effects":[]} +{"name":"Arme d’hast","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"hast","description":"","quantite":1,"encombrement":4,"equipe":false,"dommages":"4","penetration":0,"force":"12","resistance":8,"competence":"Armes d'hast","cout":10,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false,"initpremierround":"hast"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/hast.webp","effects":[],"_id":"UE79xKWXTwYAn70K"} {"_id":"UICiMF3wBeLsqm8L","name":"Pipe en bois","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.04,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/pipe.webp","effects":[]} {"_id":"UMfXFhVhdoVQVEKy","name":"Fronde","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    Peut tirer tous les rounds.

    ","quantite":1,"encombrement":0.08,"equipe":false,"dommages":"1","force":"0","resistance":0,"competence":"Fronde","cout":0.6,"portee_courte":8,"portee_moyenne":15,"portee_extreme":25,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/fronde.webp","effects":[]} {"_id":"UYXXggulNwnodaOt","name":"Chope de fer (20 cl)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.1,"encombrement":0.08,"equipe":false,"qualite":0,"contenu":[],"cout":0.15},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/chope_fer.webp","effects":[]} {"_id":"UczsYTAoP9koA2SL","name":"Bourse, sachet de tissu","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.3,"encombrement":0.01,"equipe":false,"qualite":0,"contenu":[],"cout":0.05},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bourse_sachet.webp","effects":[]} +{"name":"Esparlongue","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"epees-longues","description":"

    C’est une épée semblable à la rapière, longue et ne frappant uniquement d’estoc. Elle doit son nom à ce qu’elle était particulièrement en vogue, au Second Âge, dans la cité d’Esparlongue. En ce début du Troisième Âge, toutefois, on lui substitue le plus souvent la demi-dragonne, épée très voisine, ne frappant pareillement que d’estoc, mais plus résistante (résistance 10) et moins coûteuse (15 sols) ; son bonus aux dommages (+2) est identique.

    ","quantite":1,"encombrement":1.5,"equipe":false,"dommages":"2","penetration":0,"force":"10","resistance":9,"competence":"Epée à 1 main","cout":20,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"initpremierround":"esparlongue"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/esparlongue.webp","effects":[],"_id":"UsyV9n0byCeYirNC"} {"_id":"Uxk2tvEqtrmYScjK","name":"Pot à braise","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/pot_a_braise.webp","effects":[]} {"_id":"VsjRwh9Z9PMpFKdI","name":"Craie 1 bâton","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":0.01},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/craie.webp","effects":[]} {"_id":"WC1jMDKcxEJQWGOR","name":"Burette de fer blanc (40 cl)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.2,"encombrement":0.2,"equipe":false,"qualite":0,"contenu":[],"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/burette.webp","effects":[]} {"_id":"WTHZdtgf6lHUSKDx","name":"Fouet","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    Provoque des dégâts \"non mortels\".

    \n

    Les armures sont majorées de 2.

    \n

    Si la protection atteint une valeur de 5 ou plus, le fouet ne peut causer de dégât.

    ","quantite":1,"encombrement":0.5,"equipe":false,"dommages":"1","force":"0","resistance":0,"competence":"Fouet","cout":1,"portee_courte":2,"portee_moyenne":null,"portee_extreme":null,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/fouet.webp","effects":[]} -{"_id":"WurdjqJ8zMiXNdiW","name":"Épée gnome","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    C’est une épée courte, essentiellement fabriquée et portée par les Gnomes au Second Âge.

    ","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","force":"8","resistance":12,"competence":"Epée à 1 main","cout":12,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"categorie_parade":"epees-courtes","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.webp","effects":[]} +{"name":"Hachette","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"haches","description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","penetration":0,"force":"8","resistance":6,"competence":"Hache à 1 main","cout":4,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"initpremierround":"dague"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/hachette.webp","effects":[],"_id":"WTWXZeoK5HpCrGFy"} {"_id":"XTZVrcMNofAviP63","name":"Cire d'abeille 500g","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.15},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/cire.webp","effects":[]} {"_id":"XlKp5BvZX8A03fUg","name":"Sac à dos de cuir","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":25,"encombrement":0.4,"equipe":false,"qualite":0,"contenu":[],"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/sac_a_dos.webp","effects":[]} {"_id":"XoslLyWIJYY2RGzz","name":"Fiole de verre (20 cl)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.1,"encombrement":0.06,"equipe":false,"qualite":0,"contenu":[],"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/fiole_verre.webp","effects":[]} @@ -115,6 +115,7 @@ {"_id":"YHPrUuGGGTGZMNAg","name":"Bière","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"munition","data":{"description":"

    1 mesure (20cl) de bière.

    ","quantite":1,"encombrement":0.1,"equipe":false,"qualite":0,"cout":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/liquides/liquide_biere.webp","effects":[]} {"_id":"YNHDt4EerstJvx5l","name":"Le Principe Drachromatique","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"livre","data":{"description":"

    Cet ouvrage de profonde érudition sur l’origine des couleurs et leur signification onirique est foncièrement incompréhensible, à moins de posséder un minimum de +4 en voie d’Oniros. Il permet d’envisager la synthèse des sorts d’Invulnérabilité Chromatique et de Transmutation Chromatique. Sans son assimilation préalable, la synthèse de ces sorts est totalement inenvisageable. Sa difficulté de lecture est de -4, son assimilation requiert 26 points de tâche, périodicité 1 heure.

    ","auteur":"Anonyme","quantite":1,"difficulte":-4,"points_de_tache":26,"encombrement":0,"xp":"","cout":0,"competence":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_oniros.png","effects":[]} {"_id":"YNbbSGLnexiXNyXU","name":"Manteau de laine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.8,"equipe":false,"resistance":0,"qualite":0,"cout":0.6},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/manteau_laine.webp","effects":[]} +{"name":"Gourdin","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"","description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"1","penetration":0,"force":"7","resistance":8,"competence":"Masse à 1 main","cout":0,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"initpremierround":"gourdin"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/gourdin.webp","effects":[],"_id":"Yh7VGX3BikmIjVQH"} {"_id":"Yyn39VDRnO6oA3Uq","name":"Echecs draconics en bois","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.5,"equipe":false,"resistance":0,"qualite":0,"cout":2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/echecs.webp","effects":[]} {"_id":"Z0ij7qpoYeWMVocP","name":"Ceinturon de cuir","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":6,"encombrement":0.1,"equipe":false,"qualite":0,"contenu":[],"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/ceinturon.webp","effects":[]} {"_id":"ZLda3pfrbiKucSea","name":"Cornebouffe","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"objet","data":{"description":null,"quantite":1,"encombrement":null,"equipe":false,"resistance":0,"qualite":0,"cout":2},"flags":{"core":{"sourceId":"Item.yXOePj4twuchMblc"}},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/cornebouffe.webp","effects":[]} @@ -124,25 +125,26 @@ {"_id":"beQ9d4QQwZDQl5NA","name":"Flûte à bec","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.09,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/flute_bec.webp","effects":[]} {"_id":"bgkEBYUEFLvAaeVf","name":"Luth, viole","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"resistance":0,"qualite":0,"cout":7},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/luth.webp","effects":[]} {"_id":"bxDITKRhXiyvLhMz","name":"Candique","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"ingredient","data":{"description":"

    Poudre blanche apparaissant sous l’écorce de nombreux arbres,

    \n

    VUE/Alchimie à 0.

    ","niveau":0,"encombrement":0.001,"base":0,"quantite":1,"milieu":"Forêts","rarete":"","categorie":"Alchimie","cout":0.02},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/candique.webp","effects":[]} -{"_id":"cFnFQrQIPgyZRWdo","name":"Épée sorde","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    C’est une épée plus courte que la dragonne, mais plus large. Elle peut s’utiliser à une ou deux mains. Sa grande solidité en fait l’épée de prédilection des gardes et des soldats.

    \n

    C’est probablement à elle que le Guerrier Sorde doit son nom (à moins que ce ne soit l’inverse).

    ","quantite":1,"encombrement":2,"equipe":false,"dommages":"3/4","force":"12/11","resistance":15,"competence":"Epée à 1 main","cout":20,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true,"penetration":null,"categorie_parade":"epees-lourdes"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_sord.webp","effects":[]} {"_id":"cVZbnh5cYxBx6P5b","name":"Burin, gouge, ciseau","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/gouge.webp","effects":[]} {"_id":"ckKnviu9SHvWgya0","name":"Bougie de cire (2 heures)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.05},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bougie.webp","effects":[]} {"_id":"cobfvOmFpti5lJuK","name":"Chemise de lin","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/chemise_lin.webp","effects":[]} {"_id":"dBR6KXvfmjjIcwsc","name":"Pilon en marbre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/pilon.webp","effects":[]} -{"_id":"eK28jEeQiJdd93L3","name":"Bouclier léger","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"0","force":"8","resistance":13,"competence":"Bouclier","cout":4,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"boucliers","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_petit.webp","effects":[]} +{"name":"Épée dragonne","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"epees-longues","description":"

    C’est une épée longue, plus robuste que l’esparlongue, pouvant également frapper de taille.

    ","quantite":1,"encombrement":2,"equipe":false,"dommages":"3","penetration":0,"force":"11","resistance":12,"competence":"Epée à 1 main","cout":20,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"initpremierround":"epeedragonne"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_dragonne.webp","effects":[],"_id":"dLiMJO6aUkh0EuIZ"} +{"_id":"eK28jEeQiJdd93L3","name":"Bouclier léger","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"0","force":"8","resistance":13,"competence":"Bouclier","cout":4,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"boucliers","penetration":0,"magique":false,"resistance_magique":null,"ecaille_efficacite":null,"initpremierround":"hast"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_petit.webp","effects":[]} {"_id":"fAzYb7kkW6QxG6i6","name":"Graisse à Bottes 500g","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/graisse_a_cuir.webp","effects":[]} {"_id":"fDwsTMuug0Z5BdaA","name":"Cuir / Metal","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"

    Cuir épais clouté, ou petites plaquettes, écailles ou anneaux de fer cousus sur le cuir. Pectoral ou cotte de cuir/métal + jupon ou cuissards de cuir / métal sur culottes de cuir souple + bottes de cuir / métal + casque de métal.

    \n

     

    ","quantite":1,"encombrement":4,"equipe":false,"protection":"4","deterioration":0,"malus":-2,"cout":20},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_metal.webp","effects":[]} {"_id":"fLKFTvLWoj7juxQE","name":"Flèche, carreau","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/fleche.webp","effects":[]} {"_id":"gYFprGGUUVG1Apcf","name":"Carquois","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":2,"encombrement":0.1,"equipe":false,"qualite":0,"contenu":[],"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/carquois.webp","effects":[]} {"_id":"gfU7oZL1JYqF3lAW","name":"Robe de lin","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.6},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/robe_lin.webp","effects":[]} {"_id":"gmBC6SO3F5d64Vpl","name":"Miroir en cuivre poli 20 cm","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/miroir.webp","effects":[]} +{"name":"Fléau léger","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"","description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"3","penetration":0,"force":"12","resistance":10,"competence":"Fléau","cout":12,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":true,"initpremierround":"fleau"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/fleau_leger.webp","effects":[],"_id":"godMVR796aSUVjLu"} {"_id":"hEPimS3H8jihDuUS","name":"Crayon à mine de plomb","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.02,"equipe":false,"resistance":0,"qualite":0,"cout":0.3},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/crayon_plomb.webp","effects":[]} {"_id":"hVgd4APvAW8sbXf0","name":"Grande hache","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"4","force":"13","resistance":8,"competence":"Hache à 2 mains","cout":15,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false,"categorie_parade":"haches","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/grande_hache.webp","effects":[]} {"_id":"hjsIxUmanyz5otLJ","name":"Marmite de fer (3 litres)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":1.5,"encombrement":0.6,"equipe":false,"qualite":0,"contenu":[],"cout":0.6},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/marmite.webp","effects":[]} +{"name":"Fléau lourd","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"","description":"","quantite":1,"encombrement":3,"equipe":false,"dommages":"4","penetration":0,"force":"13","resistance":10,"competence":"Fléau","cout":15,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":true,"initpremierround":"fleau"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/fleau_lourd.webp","effects":[],"_id":"htaHjhHwVhlBnZjv"} {"_id":"huvZ4dMPpn9gk9km","name":"Sel","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":null},"flags":{"core":{"sourceId":"Item.fLEyryhRi8Nw37SP"}},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/sel.webp","effects":[]} {"_id":"iCvphbPdxUcfqetd","name":"Aumônière","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"conteneur","data":{"description":"

    Comme une bourse, mais sous forme d'une coque en cuir rigide.

    ","capacite":0.25,"encombrement":0,"equipe":false,"qualite":0,"cout":0.2,"contenu":[]},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/aumoniere.webp","effects":[]} {"_id":"iGHudg5kBOfYWgwV","name":"Arc","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    Nie jusqu'à 2 points d'armure.

    \n

    Rechargement 1/2 round (s'il tire en début de round, il pourra recharger durant le reste du round pour tirer de nouveau au début du round suivant).

    ","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","force":"0","resistance":0,"competence":"Arc","cout":10,"portee_courte":10,"portee_moyenne":20,"portee_extreme":50,"penetration":2,"rapide":false,"deuxmains":false,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/arc.webp","effects":[]} -{"_id":"ijCebH1Pr3LmzdOj","name":"Épée cyane","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    Long cimeterre à l’acier bleuté, exclusivement fabriqué par les Cyans ou Hommes bleus.

    ","quantite":1,"encombrement":2,"equipe":false,"dommages":"3","force":"11","resistance":12,"competence":"Epée à 1 main","cout":25,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"categorie_parade":"epees-lourdes","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_cyane.webp","effects":[]} {"_id":"iq8ZZgphxOUgC1bi","name":"Flûte traversière de roseau","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.08,"equipe":false,"resistance":0,"qualite":0,"cout":0.12},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/flute_traversiere.webp","effects":[]} {"_id":"iss7ARW8oRoe1umi","name":"Eau","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"munition","data":{"description":"

    1 mesure (20cl) d'eau.

    ","quantite":1,"encombrement":0.1,"equipe":false,"qualite":0,"cout":0},"flags":{"core":{"sourceId":"Item.LsTGq00Wf30rzDsF"}},"img":"systems/foundryvtt-reve-de-dragon/icons/liquides/liquide_eau.webp","effects":[]} {"_id":"iuSOVPBsK8Zg6hoY","name":"1 m² de bâche","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.5,"equipe":false,"resistance":0,"qualite":0,"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bache.webp","effects":[]} @@ -167,11 +169,11 @@ {"_id":"ncpONCxPPNZ9YbBr","name":"Chramaelium","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"ingredient","data":{"description":"

    Poudre rouge obtenue par disruption alchimique de la chramaele, minerai ayant l’apparence de la glaise.

    \n

    VUE/Alchimie à -4

    ","niveau":0,"encombrement":0.001,"base":0,"quantite":1,"milieu":"","rarete":"","categorie":"Alchimie","cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/chramaelium.webp","effects":[]} {"_id":"nl9cICrauIOEXwFP","name":"Cordelette (10 m)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/cordelette.webp","effects":[]} {"_id":"nqMyaOqBfTxdP9tg","name":"Cor en corne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.6},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/cor_corne.webp","effects":[]} +{"name":"Épée sorde","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"epees-lourdes","description":"

    C’est une épée plus courte que la dragonne, mais plus large. Elle peut s’utiliser à une ou deux mains. Sa grande solidité en fait l’épée de prédilection des gardes et des soldats.

    \n

    C’est probablement à elle que le Guerrier Sorde doit son nom (à moins que ce ne soit l’inverse).

    ","quantite":1,"encombrement":2,"equipe":false,"dommages":"3/4","penetration":null,"force":"12/11","resistance":15,"competence":"Epée à 1 main","cout":20,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":true,"initpremierround":"epeesorde"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_sord.webp","effects":[],"_id":"oXpPZ9LS1nsU0nGT"} {"_id":"of2LbmmB4EtlSwte","name":"Sac en jute (50 litres)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":25,"encombrement":0.1,"equipe":false,"qualite":0,"contenu":[],"cout":0.08},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/sac_jute_50.webp","effects":[]} {"_id":"orpj8CumQ39xMOHy","name":"Brosse à cheveux","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.06,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/Brosse.webp","effects":[]} {"_id":"oyAyc3tp1JrIFfos","name":"L'Oniricon","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"livre","data":{"description":"

    Cet abécédaire draconic permet de gagner jusqu’à 80 points d’expérience en voie d’Oniros, jusqu’à concurrence du niveau +1. C’est un livre pour débutants, inutile aux haut-rêvants confirmés. Sa difficulté de lecture est de -2, son assimilation requiert 20 points de tâche, périodicité une heure. Le gain final est de 4d10+40 points d’expérience en voie d’Oniros.

    ","auteur":"anonyme","quantite":1,"difficulte":-2,"points_de_tache":0,"encombrement":0,"xp":"4d10+40","cout":0,"competence":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/icone_parchement_vierge.svg","effects":[]} {"_id":"phfgVizT4ekUwqFq","name":"Selle et harnais","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":25,"encombrement":4,"equipe":false,"qualite":0,"contenu":[],"cout":5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/selle.webp","effects":[]} -{"_id":"q3gHw08c5fYONo2h","name":"Rasoir","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"dommages":"1","force":"0","resistance":0,"competence":"Dague","cout":2,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"dagues","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/rasoir.webp","effects":[]} {"_id":"qCLTOjlIOvlj0uo7","name":"Chaperon de laine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/chaperon_laine.webp","effects":[]} {"_id":"qWhl9EfdnJx4KFTZ","name":"Bas de laine","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/bas_laine.webp","effects":[]} {"_id":"sSgPT3aKDOZ25svO","name":"Porte plume en bois","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.02,"equipe":false,"resistance":0,"qualite":0,"cout":0.05},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/porte_plume2.webp","effects":[]} @@ -181,8 +183,8 @@ {"name":"Sang","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"munition","data":{"description":"

    1 mesure (20cl) de sang.

    ","quantite":1,"encombrement":0.1,"equipe":false,"qualite":0,"cout":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/liquides/liquide_sang.webp","effects":[],"_id":"slusKo2nVCtFwDkN"} {"_id":"snupUovwaPAe46aD","name":"Fiole en grès (20 cl)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":0.1,"encombrement":0.1,"equipe":false,"qualite":0,"contenu":[],"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/fiole_gres.webp","effects":[]} {"_id":"szOThadvQvFcS79R","name":"Cuir Epais","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"

    Cuir très épais comme le cuir de botte. Pectoral de cuir épais + jupon de bandes ou de tresses de cuir ou cuissards de cuir épais sur culottes de cuir souple + bottes dures + casque de cuir.

    \n

     

    ","quantite":1,"encombrement":2,"equipe":false,"protection":3,"deterioration":0,"malus":-1,"cout":10},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_epais.webp","effects":[]} -{"_id":"t3LZDSaQ6AiloImA","name":"Esparlongue","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"

    C’est une épée semblable à la rapière, longue et ne frappant uniquement d’estoc. Elle doit son nom à ce qu’elle était particulièrement en vogue, au Second Âge, dans la cité d’Esparlongue. En ce début du Troisième Âge, toutefois, on lui substitue le plus souvent la demi-dragonne, épée très voisine, ne frappant pareillement que d’estoc, mais plus résistante (résistance 10) et moins coûteuse (15 sols) ; son bonus aux dommages (+2) est identique.

    ","quantite":1,"encombrement":1.5,"equipe":false,"dommages":"2","force":"10","resistance":9,"competence":"Epée à 1 main","cout":20,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"categorie_parade":"epees-longues","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/esparlongue.webp","effects":[]} {"_id":"tBFt4h3jqINsOxLI","name":"Outre (2 litres)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":1,"encombrement":0.08,"equipe":false,"qualite":0,"contenu":[],"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/outre.webp","effects":[]} +{"name":"Marteau","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"","description":"","quantite":1,"encombrement":0.3,"equipe":false,"dommages":"2","penetration":0,"force":"7","resistance":8,"competence":"Masse à 1 main","cout":1,"portee_courte":0,"magique":false,"ecaille_efficacite":0,"resistance_magique":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"initpremierround":"masse"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/marteau.webp","effects":[],"_id":"tMWzePiuMtiCQnAU"} {"_id":"tY3shj5FA8nwMgxX","name":"Vin","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"munition","data":{"description":"

    1 mesure (20cl) de vin.

    ","quantite":1,"encombrement":0.1,"equipe":false,"qualite":0,"cout":0},"flags":{"core":{"sourceId":"Item.QNNWTG5yqQKmcpJ7"}},"img":"systems/foundryvtt-reve-de-dragon/icons/liquides/liquide_vin.webp","effects":[]} {"_id":"tZWQCuRr1ic3S0pL","name":"Souliers","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.8},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/souliers.webp","effects":[]} {"_id":"tswamwK2oKNARhjA","name":"Verre grossissant","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.02,"equipe":false,"resistance":0,"qualite":0,"cout":2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/verre_grossissant.webp","effects":[]} @@ -190,18 +192,16 @@ {"_id":"ueJnUMLK1vpL8xOB","name":"Stylet de bronze","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.02,"equipe":false,"resistance":0,"qualite":0,"cout":0.12},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/stylet_de_bronze.webp","effects":[]} {"_id":"uwwunMSrJoUYTDkG","name":"Seau de bois ferré (10 litres)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":5,"encombrement":1,"equipe":false,"qualite":0,"contenu":[],"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/seau_ferre.webp","effects":[]} {"_id":"vQ494sD9FgFI08kZ","name":"Drap Matelassé","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"

    Deux épaisseurs de drap surpiquées, avec rembourrage de laine.

    \n

    Pourpoint ou cotte de drap matelassé + culottes de drap matelassé + bottes de cuir souple. Le pourpoint est une sorte de veste ; la cotte est une sorte de tunique, lacée sur la poitrine, et descendant jusqu’aux genoux, façon Robin des Bois.

    \n

     

    ","quantite":1,"encombrement":0,"equipe":false,"protection":1,"deterioration":0,"malus":0,"cout":4},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/drap_matelasse.webp","effects":[]} -{"_id":"viHilj5hAHZqWuli","name":"Lance courte","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"2","force":"8","resistance":5,"competence":"Lance","cout":3,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"categorie_parade":"lances","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/lance.webp","effects":[]} -{"_id":"wK5sGduzSvY3XxMF","name":"Massette","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","force":"9","resistance":8,"competence":"Masse à 1 main","cout":2,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"categorie_parade":"masses","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/massette.webp","effects":[]} +{"name":"Épée demi-dragonne","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"epees-longues","description":null,"quantite":1,"encombrement":1.5,"equipe":false,"dommages":"2","penetration":0,"force":"10","resistance":10,"competence":"Epée à 1 main","cout":15,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"initpremierround":"epeedragonne"},"flags":{"core":{"sourceId":"Item.ErwaSLcGryAbYjkm"}},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/demi_dragonne.webp","effects":[],"_id":"vnlRGjt7X6yQRObA"} +{"name":"Épée cyane","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"arme","data":{"categorie_parade":"epees-lourdes","description":"

    Long cimeterre à l’acier bleuté, exclusivement fabriqué par les Cyans ou Hommes bleus.

    ","quantite":1,"encombrement":2,"equipe":false,"dommages":"3","penetration":0,"force":"11","resistance":12,"competence":"Epée à 1 main","cout":25,"portee_courte":0,"magique":false,"ecaille_efficacite":null,"resistance_magique":null,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true,"initpremierround":"epeecyane"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_cyane.webp","effects":[],"_id":"wPE64RRcuLlvuPrY"} {"_id":"wcW5KcideGi8EY67","name":"Gants de cuir","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.05,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/gants_de_cuir.webp","effects":[]} {"_id":"wpWaqe96x3cvqTXy","name":"Robe de laine","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.2,"equipe":false,"resistance":0,"qualite":0,"cout":0.4},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/robe_laine.webp","effects":[]} {"_id":"wwWRn95ByBD08eGQ","name":"Le Paradoxe de l’Immobilité Rapide","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"livre","data":{"description":"

    Ce texte de pure logique ne peut être assimilé que si l’on possède un minimum de +4 en voie d’Hypnos. Il permet d’envisager la synthèse du sort de Concentration. (Sans son assimilation préalable, la synthèse de ce sort est totalement inenvisageable.) Sa difficulté de lecture est de -5, son assimilation requiert 12 points de tâche, périodicité 1 heure.

    ","auteur":"Wanister de Bravo","quantite":1,"difficulte":-5,"points_de_tache":12,"encombrement":0,"xp":"","cout":0,"competence":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.png","effects":[]} -{"_id":"wyiy7aLaP8jnzkFn","name":"Bâton","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":2,"equipe":false,"dommages":"1","force":"9","resistance":8,"competence":"Masse à 2 mains","cout":0.5,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false,"categorie_parade":"masses","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/baton.webp","effects":[]} {"_id":"x4g6bDu3eUllSSSJ","name":"Eponge de mer","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.04,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/eponge.webp","effects":[]} {"_id":"xfdeDEyMK8YtBpzC","name":"Huile 20 cl (4 heures)","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.04},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/huile.webp","effects":[]} {"_id":"xuk60njqtrSZusSX","name":"Chemise de laine","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.1,"equipe":false,"resistance":0,"qualite":0,"cout":0.2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/chemise_laine.webp","effects":[]} {"_id":"yILNvELKbsz2OOln","name":"Ecritoire","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"resistance":0,"qualite":0,"cout":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/ecritoire.webp","effects":[]} {"_id":"yO9Vx7tqF8qbZoYw","name":"Besace de cuir","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"conteneur","data":{"description":"","capacite":10,"encombrement":0.2,"equipe":false,"qualite":0,"contenu":[],"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/besace.webp","effects":[]} -{"_id":"yd4XGzrOMEo4fmiZ","name":"Hachette","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"2","force":"8","resistance":6,"competence":"Hache à 1 main","cout":4,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":false,"unemain":false,"categorie_parade":"haches","penetration":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/hachette.webp","effects":[]} {"_id":"z3xiBzZBZXlaRVzZ","name":"Le Grand Iris","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"livre","data":{"description":"

    Cette judicieuse réflexion sur les sorts d’illusion visuelle d’Hypnos ne peut être assimilée que si l’on possède au minimum zéro en voie d’Hypnos. Il confère un bonus de synthèse de +2 et de 12 points de sorts aux trois yeux d’Hypnos : Invisibilité, Transfiguration, Métamorphose. Sa difficulté de lecture est de -3, son assimilation requiert 16 points de tâche, périodicité une heure.

    ","auteur":"Khrachtchoum le Problémeux","quantite":1,"difficulte":-3,"points_de_tache":16,"encombrement":0,"xp":"0","cout":0,"competence":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.png","effects":[]} {"_id":"zQWlnUsd8bPySujd","name":"Aiguille à coudre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"objet","data":{"description":"","quantite":1,"encombrement":0.01,"equipe":false,"resistance":0,"qualite":0,"cout":0.1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/aiguille.webp","effects":[]} {"_id":"zYI8mDiysWtmsSyy","name":"Carquois","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"conteneur","data":{"description":"","capacite":2,"encombrement":0.1,"equipe":false,"qualite":0,"cout":0.5},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/objets/carquois.webp","effects":[]} diff --git a/packs/sorts-narcos.db b/packs/sorts-narcos.db index 4a07ee81..3fd33b85 100644 --- a/packs/sorts-narcos.db +++ b/packs/sorts-narcos.db @@ -1,26 +1,26 @@ -{"_id":"0N6ILL5RMgmShyM8","name":"Dague de Force","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Même principe que la @Item[r9onPANmiK5E5Jnw]{Flèche de Feu}. Une dague ainsi modifiée a un +dom de +4.

    \n

    La dague de force a une résistance absolue tant que dure l’effet du sort et ne peut être brisée. Les dommages éventuellement reçus sont néanmoins comptabilisés et appliqués au double à l’expiration du sort. Par ailleurs, si la dague modifiée a touché ou été touchée (qu’elle ait blessé, paré, ou été parée), elle perd automatiquement 1 point de résistance à expiration du sort.

    ","draconic":"narcos","duree":"HN","JR":"Il n’y a aucun JR pour les objets ordinaires. Les objets magiques (enchantés) résistent automatiquement, le sort se dissipant sans effet, les points de rêve étant néanmoins dépensés","cible":"Une dague","difficulte":"-5","portée":"","caseTMR":"monts","caseTMRspeciale":"","ptreve":"3","xp":0,"portee":"","isrituel":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/competence_narcos.svg","effects":[]} -{"_id":"1KMBCeC1qPZTfxle","name":"Gourdin-Dragon","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Il s’agit d’une transformation radicale. Sous l’effet du sort, le gourdin devient une véritable épée dragonne, d’une résistance normale (12), d’un +dom de +3 et d’un encombrement standard de 2. Utilisée ou non, l’arme devient un tas de copeaux  déchiquetés à l’expiration du sort.

    ","draconic":"narcos","duree":"HN","JR":"Il n’y a aucun JR pour les objets ordinaires. Les objets magiques (enchantés) résistent automatiquement, le sort se dissipant sans effet, les points de rêve étant néanmoins dépensés","cible":"Un gourdin, morceau de bois, branche ou autre, de la taille et du diamètre approximatifs d’une épée dragonne","difficulte":"-7","portée":"","caseTMR":"foret","caseTMRspeciale":"","ptreve":"7","xp":0,"isrituel":false,"portee":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/competence_narcos.svg","effects":[]} -{"_id":"4ShhmXKmsIbwoZcG","name":"Maîtrise","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Ce rituel établit le lien qui unira l'objet à son utilisateur, permettant à ce dernier d'en établir la maîtrise. Antinomique du rituel d'Autonomie, réservé à de très spécifiques Grandes Écailles de Narcos, le rituel de Maîtrise est obligatoire pour toutes les écailles courantes : efficacité, activité, protection.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-7","portée":"","caseTMR":"fleuve","caseTMRspeciale":"","ptreve":"7","portee":"","isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"5NZnTt0mvfPorSHG","name":"Écailles de Protection contre le venin *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection confère un bons de +1 au jet de CONSTITUTION contre toutes les sortes de venin et de poison, augmentant ainsi les chances de leur résister.

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"foret","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"74XSU8DqNBXGFn3R","name":"Dragonne Lame","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Même principe que la@Item[r9onPANmiK5E5Jnw]{Flèche de Feu} et la @Item[8BJ9kn3AWLFDwvez]{Dague de Force}, y compris la détérioration automatique de 1 point de résistance. Une épée dragonne ainsi modi$ée a un +dom de +6.

    ","draconic":"narcos","duree":"HN","JR":"Il n’y a aucun JR pour les objets ordinaires. Les objets magiques (enchantés) résistent automatiquement, le sort se dissipant sans effet, les points de rêve étant néanmoins dépensés","cible":"Une épée Dragonne (exclusivement)","difficulte":"6","portée":"","caseTMR":"desolation","caseTMRspeciale":"","ptreve":"4","xp":0,"isrituel":false,"portee":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/competence_narcos.svg","effects":[]} -{"_id":"AIBLH8EduhfUQscn","name":"Écaille d'Efficacité *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Les écailles d'efficacité servent à rendre un objet plus efficace, mais uniquement dans sa fonction normale. Une arme magiquement efficace permettra de toucher plus facilement un adversaire ; un bouclier de mieux parer ; un instrument de musique de jouer mieux à moindre effort ; mais un balai magique permettre de mieux balayer et non de voler. Les écailles d'efficacité n'ont de pertinence que sur les objets pouvant être utilisés activement, armes, instruments, outils. Les objets passifs, meubles, contenants, vêtements, armures, ne peuvent pas être rendus plus efficaces.

    \n

    En terme de jeu, chaque écaille d'efficacité possédée par l'objet confère un bonus de +1 sur la table de Résolution lors de son utilisation. S'il s'agit d'une arme, chaque écaille d'efficacité augmente également de 1 le facteur d'initiative, ainsi que le +dom de l'arme, mais jusqu'au maximum du double normal de ce dernier. Soit une épée dragonne (+dom +3) possédant 5 écailles d'efficacité. Son utilisateur bénéficie d'un bonus de +5 à l'initiative, de +5 à l'attaque et à la parade, mais d'un +dom de +6 seulement (le double du +dom normal) et non pas de +8. Ne pas oublier néanmoins de rajouter le +dom personnel dû à la taille et à la force. Cette règle s'applique également aux armes de jet (dague, javelot, fouet). En ce qui concerne les armes de tir (arbalète, arc et fronde), l'efficacité ne s'applique qu'aux dommages  (toujours pour un maximum du double du +dom normal) et non au toucher. Pour qu'un archer bénéficie d'un bonus d'efficacité au toucher et aux dommages, il doit avoir à la fois un arc magique et une flèche magique.

    \n

    Le nombre maximum d'écailles d'efficacité pouvant être posées sur un objet est égal à l'enchantabilité de sa gemme, mais avec un maximum de 7 quelle que soit cette dernière. Pour obtenir des armes magiques d'un bonus supérieur à +7, il faut avoir recours à une éventuelle Grande Écaille de Narcos spécifique.

    \n

    La pose de chaque écaille d'efficacité coûte un point de seuil. Mais il n'y a aucune limite de temps entre la pose de chacune, l'objet pouvant être utilisé dans l'intervalle. Par exemple, on peut se contenter provisoirement d'une épée +1 (une écaille), s'en servir plusieurs fois en combat, et plus tard, rajouter une se conde écaille pour obtenir une épée +2. Toutefois, si entretemps l'objet a été maîtrisé par quelqu'un d'autre, il faut effectuer une Lecture d'Aura complète avant de pouvoir reposer une écaille. Si cette précaution est négligée, on aboutit à un cas de magie impossible. L'utilisation d'un objet magiquement efficace coûte un point de rêve par heure quel que soit le nombre d'écailles.

    \n

    Si plusieurs gemmes sont alliées à un même objet grâce à Individualité et reçoivent toutes des écailles d'efficacité, leurs bonus ne s'ajoutent pas, on ne considère que le meilleur. Des gemmes différentes sont faites pour des pouvoirs entièrement différents.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"monts","caseTMRspeciale":"","ptreve":"7","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"BibuJdKmaQJm3kFw","name":"Annulation de magie","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Ce rituel permet d’annuler un effet magique, que celui-ci ait été accompli par soi-même ou par un autre haut-rêvant. On peut annuler l’effet d’un sort, de zone ou individuel, d’un rituel d’enchantement, d’une invocation, etc.

    \n

    Le haut-rêvant doit se trouver dans la case spécifique des TMR d’où la magie a été accomplie. Le jet de RÊVE qu’il doit réussir a alors la même difficulté que celui ayant permis la magie, avec une dépense de points de rêve pareillement identique.

    \n

    Pour annuler une invocation, le rituel d’Annulation doit être ciblé sur la créature invoquée. Quand la magie est le résultat conjoint de plusieurs rituels, ce qui est notamment le cas des objets magiques, chacun doit être annulé tour à tour, en commençant toujours par le dernier à avoir été accompli chronologiquement. D’une manière générale, ce sont les mêmes opérations qui doivent être répétées à l’envers. Quand un rituel coûte des points de seuil, son annulation en coûte également (le même nombre). Annulation de Magie sert également à exorciser les entités de cauchemar non incarnées. La difficulté d’un exorcisme est toujours R-7, et le coût en points de rêve égal au RÊVE de l’entité. Le ciblage doit être fait sur la créature possédée.

    \n

    Avant d’accomplir une Annulation de Magie, les paramètres de la magie à annuler (case des TMR, R-, r) peuvent être découverts au moyen du rituel Lecture d’Aura.

    \n

    Pour la synthèse d’Annulation de Magie, considérer que ce rituel est de difficulté R-7. Il peut être utilisé indifféremment par Oniros, Hypnos ou Narcos (mais jamais Thanatos), quelle que soit la voie ayant servi à accomplir la magie à annuler.

    ","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"Effet magique","difficulte":"variable","portée":"","caseTMR":"special","caseTMRspeciale":"variable","ptreve":"variable","xp":0,"isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]} -{"_id":"FpwaK1qJxKGs9HgS","name":"Permanence *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    C'est par ce rituel que le haut-rêvant stabilise les points de rêve d'une potion ou d'un objet, afin d'en prévenir l'évaporation quotidienne. Facultatif pour les potions, le rituel de Permanence est obligatoire pour tous les autres objets magiques.  Son accomplissement diminue de 1 point le seuil de rêve du haut-rêvant.

    ","draconic":"narcos","duree":"Instantanée","JR":"","cible":"","difficulte":"-5","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"5","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"KW2VZhuEGJGglGcW","name":"Restauration *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Restauration est un rituel secondaire nullement obligatoire. Son seul usage est de redonner des points de rêve actifs à une amulette de protection. Il est en effet impossible d'utiliser le simple Enchantement une fois le rituel de Permanence accompli. Restauration fonctionne de façon semblable à un Enchantement, sauf que son accomplissement coûte chaque fois un point de seuil. On peut  restaurer les points de rêve d'une amulette en plusieurs fois en intercalant un rituel de Purifcation entre chaque rituel de Restauration (qui coûte chaque fois un point de seuil). Il est possible de redonner plus de points de rêve actifs à l'objet qu'il n'en avait au départ, jusqu'à concurrence du maximum possible. Le nombre maximum de points de rêve actifs qu'un objet puisse posséder est égal à 7 fois l'enchantabilité de sa gemme.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"1+","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"P9jMT8pl4pgKEoEW","name":"Écailles de Protection contre le feu *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection diminue de 1 point le jet d'encaissement de tout dommage dû au feu, jouant le rôle d'une \"armure ignifugée\". Soit un personnage possédant une telle amulette dotée de 5 écailles, et se retrouvant dans une zone d'Air en Feu. Au lieu de jouer un jet d'encaissement à +10, il ne la joue qu'à +5. La protection de l'amulette est en plus de la protection physique qu'il peut avoir, laquelle ne peut être - rappelons-le - que d'un maximum de 2 points.

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"desert","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"SUrdOuvvelLtiZMy","name":"Écailles de Protection contre les projectiles *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection diminue de 1 point le jet d'encaissement de tout dommage dû à un projectile, flèche, carreau, pierre de fronde, dague, javelot, fouet. La protection de l'amulette est en plus de l'armure véritable du personnage. Soit un personnage vêtu de cuir épais (prot. 3), possédant une amulette de 3 écailles, et recevant une flèche (+dom +2). Face à une flèche, le cuir épais ne vaut plus que 1, mais on y rajoute les 3 écailles de l'amulette, pour un jet d'encaissement final de -2 au lieu de +1.

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"gouffre","caseTMRspeciale":"","ptreve":"6","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"TSDY6o00ri2ktlVM","name":"Puits de rêve *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Le Puits de rêve permet de stocker des points de rêve et de les y puiser à volonté, c'est en quelque sorte une tirelire de points de rêve. Le Puits de rêve peut avoir la forme de n'importe quel objet et même se contenter d'être une gemme seule. Pour y stocker des points de rêve, l'utilisateur doit le tenir dans sa main nue et se concentrer pendant un round. Il perd autant de points de rêve que souhaité, points qui sont instantanément transvasés dans le Puits de rêve. Aucune montée en TMR ni jets de dés ne sont nécessaires. Pareillement, pour puiser des points de rêve dans le Puits, il suffit de le tenir dans sa main nue au moment de lancer un sort. Au lieu de dépenser ses propres points, l'utilisateur les puise dans le Puits de rêve. Les points puisés ne peuvent avoir qu'un seul usage : alimenter un sort, lancé naturellement ou via une écaille d'activité, ou alimenter un rituel. Rien d'autre. Il ne peuvent pas servir à payer un coût de maîtrise ni un coût d'objet efficace, ni un coût d'amulette de protection. La dépense de points de rêve doit provenir intégralement de l'une ou l'autre source, utilisateur ou Puits de rêve, on ne peut pas partager. On ne peut pas non plus les récupérer pour les \"remettre dans sa tête\".

    \n

    La gemme destinée à recevoir un Puits de rêve n'a pas besoin de points actifs ; si elle en a lors de l'accomplissement de Permanence, ils sont purement et simplement ignorés (annulés). La gemme peut recevoir autant de Grandes Écailles de Puits de rêve que son enchantibilité jusqu'à un maximum de 7. Chaque Grande Écaille permet de stocker jusqu'à 7 points de rêve. Soit une gemme d'enchantabilité 6 possédant 6 Grandes Écailles de Puits de rêve, on peut y stocker jusqu'à 42 points de rêve. Un Puits de rêve n'a jamais besoin d'être entièrement plein et peut pareillement rester vide sans en souffrir. Face à une grosse dépense, on peut le vider entièrement d'un seul coup.

    \n

    Un Puits de rêve peut être posé (avec Individualité) sur une seconde gemme d'un objet possédant une écaille d'activité. Lors de l'utilisation de l'objet, les points de rêve de coût de sort pourront être dépensés par le Puits de rêve ou par l'utilisateur au choix de ce dernier. Un Puits de rêve changeant de main doit être maîtrisé selon la règle normale. La maîtrise a lieu soit au moment où l'on stocke, soit où l'on puise, le premier des deux, et coûte 1 point de rêve par Grande Écaille. Note  : les points dépensés pour la maîtrise ne vont pas dans le Puis de rêve, sils ont perdus.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"8","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"TjhnUMh6UL04k0k8","name":"Purification","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Purification est un rituel secondaire, mais néanmoins obligatoire. A moins de disposer d'une énorme quantité de points de rêve, il est vain d'espérer enchanter l'objet en une seule fois. Purifcation doit toujours s'intercaler entre deux rituels identiques : entre deux Enchantements, mais également entre deux écailles, d'activité ou de protection. Sauter cette étape aboutit à un cas de magie impossible.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"necropole","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"WUYaL4yvr0wFRLjk","name":"Enchantement","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    C'est le rituel de base e tout enchantement, c'est par lui que le haut-rêvant confère des points de rêve à la gemme ou à la potion. Le nombre de points conférés, paramétré au lancer du sort, est à son entière discrétion. Entre deux Enchantements de la même potion ou de la même gemme doit être accompli un rituel de Purificiation.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"1+","portee":"","isrituel":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"X8yMNrnbFIwTB6oL","name":"Écailles de Protection contre griffes et crocs *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection diminue de 1 point le jet d'encaissement de tout dommage dû aux armes naturelles des animaux, griffes, crocs, mais également piétinement, cornes, tentacules, etc. Elle protège également des dommages au corps à corps de pugilat, coups de poing, coups de pied, mais ne s'applique pas à l'empoignade. La protection est en plus de l'armure véritable du personnage. 

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-10","portée":"","caseTMR":"marais","caseTMRspeciale":"","ptreve":"8","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Les rituels de Lecture d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.

    \n

    Ce rituel permet d’approfondir les informations fournies par Détection d’Aura. Pratiquer Lecture d’Aura quand il n’y a pas d’aura revient à demander une magie impossible et crée immédiatement une déchirure du rêve.

    \n

    Lecture d’Aura est effectuée en plusieurs étapes, toutes étant de difficulté R-3 et coûtant 3 points de rêve. La première a toujours lieu dans un sanctuaire et ne fait que révéler dans quel(s) autre(s) genre(s) de case(s) le haut-rêvant doit se rendre pour continuer sa lecture. Là, il apprend quel genre de magie a été produit ou à quel type de rêve il a a!aire, de même que les cases spécifiques concernées. Enfin dans les cases spécifiques, le haut-rêvant peut apprendre la force du rêve ou de la magie en cours, c’est-à-dire pratiquement la difficulté et le nombre de points de rêve impliqués, information indispensable dans l’optique d’une annulation de magie.

    \n

    Lecture d’Aura révèle également la couleur de l’aura (fixe ou pulsative) comme Détection d’Aura. Pour les créatures vivantes, on peut donc sauter l’étape de Détection d’Aura et commencer directement par la lecture, puisqu’on est sûr de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la détection si, en l’absence finale d’une aura, on ne veut pas créer de magie impossible. Effectuée sur une créature non soumise à un effet magique ni sous l’emprise d’une entité, Lecture d’Aura indique toujours le Fleuve. Là, dans n’importe quelle case du Fleuve, le haut-rêvant se contente d’apprendre qu’il a a!aire à une créature vivante et douée de rêve.

    ","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire / variable","ptreve":"3","xp":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]} -{"_id":"asVUMvyZ0OocReY6","name":"Individualité","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Rituel secondaire, Individualité est néanmoins obligatoire pour les objets possédant plusieurs pouvoirs distincts. Il doit être accompli sur toute nouvelle gemme, enchantée d’au moins un point de rêve actif, avant le rituel d’Alliance. Lors, c’est uniquement à cette nouvelle gemme que s’adresseront les points de rêve et les écailles. Vis à vis d’une nouvelle gemme, le matériau re-possède toute son inertie et doit à nouveau être saturé. Quand un objet a plusieurs gemmes, toutes ont dû recevoir Individualité sauf la première. Les pouvoirs d’un objet doivent être élaborés l’un après l’autre. Dès que l’on a commencé une nouvelle gemme, on ne peut plus revenir sur les précédentes.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"desert","caseTMRspeciale":"","ptreve":"4","xp":0,"isrituel":true,"portee":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/competence_narcos.svg","effects":[]} -{"_id":"ckH9xONcfsffpRVr","name":"Écailles de Protection contre la magie *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection rajoute un +1 à tous les jets de résistance contre les sorts d'illusion-suggestion d'Hypnos ainsi que les rituels de Possession et les sorts et griffes de Thanatos. L'amulette n'est pas spécifique à un sort, elle protège de tous. Soit un personnage possédant une amulette de 4 écailles et devant jouer une JR r-8, il ne joue en réalité qu'un JR r-4, augmentant considérablement ses chances de résister à la magie. La protection ne s'applique qu'à la magie autorisant un JR.

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"6","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"hWAoVheMfyLIMKZy","name":"Alliance","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"sort","data":{"description":"

    Ce rituel unit magiquement la gemme, seul véritable réceptacle du rêve,au reste de l’objet, en sorte que son pouvoir puisse s’étendre à lui. Ce qui s’applique à la gemme s’applique désormais à l’objet, et inversement. La forme de l’objet participe maintenant à la magie. C’est pourquoi il doit être utilisé comme l’exige sa fonction normale (bague au doigt, etc.) et pourquoi sa forme doit être en analogie avec le ciblage. Pratiquement, une gemme seule ne peut être utilisée que pour une écaille d’activité lançant un sort sur l’utilisateur lui-même (la gemme ne lui permettant pas d’autre ciblage). Une gemme seule pourrait être une amulette de protection, mais il faudrait la tenir sans cesse dans le creux de la main (seule façon d’utiliser une gemme seule). En revanche, on peut s’en contenter pour la Grande Écaille de Narcos Puits de rêve.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"pont","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true},"flags":{"core":{"sourceId":"Item.5UQMurs8lNa8eBr0"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"hunCnz9KW1gc5ab7","name":"Autonomie **","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Le rituel d'Autonomie doit obligatoirement être utilisé à la place du rituel de Maîtrise pour les objets autonomes, c'est-à-dire fonctionnant uniquement à partir d'une certaine programmation, sans l'intervention d'un utilisateur. Chaque cas d'objet autonome correspond à une Grande Écaille de Narcos spécifique. Il s'agit  usuellement de dispositifs se mettant automatiquement à fonctionner en présence d'un signal prévu dans leur programmation : piège magique qui se déclenche au moindre bruit, statue qui répète un message quand on passe devant elle, feu ou torche qui s'allume dès qu'on frappe dans ses mains, etc. Les objets autonomes étaient la grande passion des hauts-rêvants du Second Âge, qui les agençaient souvent en de grandioses mises en scène. Pratiquement, un objet autonome dépense ses points de rêve actifs pour obtenir son effet, tout comme un haut-rêvant dépense les siens. Autonomie permet de les récupérer tout seul, à raison de 3 points par heure complète de non-utilisation, sans pouvoir dépasser le nombre de points actifs initial. L'accomplissement du rituel d'Autonomie coûte 2 points de seuil.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-10","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"10","portee":"","isrituel":true,"coutseuil":2},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"lq3jQDJsAflJ2PEy","name":"Flèche de Feu","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    L’intitulé de ce sort n’est que métaphorique. Le sort ne rend pas la flèche ignée, mais augmente son tranchant et son pouvoir de pénétration. Un projectile ainsi modifié (quelle que soit l’arme, flèche ou carreau) a un +dom de +5 et annule 5 points d’armure au lieu de 2 (armure véritable et non pas protection naturelle).

    \n

    Si le projectile n’est pas utilisé, il est retrouvé intact à expiration du sort. Inversement, qu’il ait atteint ou non une cible, sa pointe devient inutilisable, le métal ayant fondu et coulé comme sous l’effet d’une intense chaleur.

    ","draconic":"narcos","duree":"HN","JR":"Il n’y a aucun JR pour les objets ordinaires. Les objets magiques (enchantés) résistent automatiquement, le sort se dissipant sans effet, les points de rêve étant néanmoins dépensés","cible":"Une flèche d'arc ou un carreau d'arbalète","difficulte":"-4","portée":"","caseTMR":"foret","caseTMRspeciale":"","ptreve":"2","xp":0,"isrituel":false,"portee":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/competence_narcos.svg","effects":[]} -{"_id":"mh9JjaKckzz1eAoe","name":"Écailles de Protection contre la maladie* ","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection confère un bons de +1 au jet de CONSTITUTION contre toutes les maladies, augmentant ainsi les chances de leur résister.

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"mzAV6EdQlGkVkWEN","name":"Écailles de Protection contre les lames *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection diminue de 1 point le jet d'encaissement de tout dommage dû à une arme de mêlée (dague, épée, hache, lance, masse, fléeau, arme d'hast), mais ni les projectiles ni les dommages au corps à corps. La protection est en plus de l'armure véritable du personnage. 

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-10","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"8","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"sEBhR48HagKNbkob","name":"Écaille d'activité *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Le rituel d'Écaille d'Activité confère à l'objet magique le pouvoir de lancer un sort. Ce peut être un sort de zone d'Oniros, un sort d'illusion-suggestion ou d'illusion sensorielle d'Hypnos, ou un sort de Thanatos, mais ne peut en aucun cas être un rituel d'aucune des quatre voies. Ayant posé l'écaille d'activité sur l'objet (\"poser\" est le terme consacré à l'accomplissement des rituels d'Écaille), le Haut-Rêvant y lance le sort de son choix et l'objet devient capable de le lancer à son tour. Pratiquement, le haut-rêvant effectue toutes les opérations nécessaires au lancer d'un sort, y compris son paramétrage précis, puis le lance normalement en dépensant les points de rêve du coût. Toutefois, au lieu de cibler comme l'exige le ciblage normal du sort, il touche l'objet possédant l'écaille d'activité. En résultat, aucun effet ne se produit, mais le sort est maintenant enregistré dans la \"mémoire\" de la gemme. Il suffit ensuite à l'utilisateur de se concentrer mentalement sur l'effet voulu (dont il doit avoir une idée) pour que l'objet lance le sort. Il pourra le lancer indéfiniment.

    \n

    A la fin du round de concentration, l'utilisateur doit être capable de dépenser les points de rêve exigés par le coût du sort tel qu'il est paramétéré. S'il n'en a pas assez, il ne dépense rien, mais l'objet ne fonctionne pas. Puis cela étant fait, le sort opère au tout début du round suivant, selon le ciblage voulu par l'utilisateur, fonction de la forme de l'objet et de la façon dont il est utilisé. Pour que le sort puisse être ciblé ailleurs que sur l'utilisateur lui-même, l'objet doit avoir une forme oblongue, analogue au doigt pointé d'un haut-rêvant. Le sort enregistré dans la gemme est paramétré une fois pour toutes. Un objet lançant un sort de Sommeil de 5 rounds lancera toujours un sort de Sommeil de 5 rounds, ni plus ni moins. Un objet lançant une illusion visuelle ne lancera toujours que la même illusion au moindre détail près. La portée est celle de l'EMPATHIE du 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.

    \n

    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 soi-même, mais évite la montée en TMR, les rencontres, et confère la certitude que le sort partira à coup sûr. L'effet d'un sort lancé par un objet peut être annulé par Annulatrion de Magie, mais pas par Annulation de ses Propres Zones ni Annulation de ses Propres Illusions.

    \n

    Chaque gemme d'un objet ne peut recevoir qu'une seule écaille d'activité, et la pose de cette dernière coûte un point de seuil. Une écaille d'activité ne peut enregistrer et lancer q'un seul sort. Mais un même objet peut avoir plusieurs gemmes, grâce à Individualité, chacune possédant une écaille d'activité pour lancer un sort différent.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-9","portée":"","caseTMR":"desolation","caseTMRspeciale":"","ptreve":"7","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} -{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Les rituels de Détection d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.

    \n

    Toutes les créatures vivantes animées (humains, humanoïdes, animaux) ont une caractéristique RÊVE. Les objets enchantés possèdent des points de rêve, de même que les produits de magie naturelle, comme certaines pierres de chance. Les entités de cauchemar, incarnées ou non, en ont également. Quelle qu’elle soit, la présence de rêve émet une aura, laquelle est détectable par Détection d’Aura. Parallèlement, toute cible d’un sort ou d’un rituel, émet une aura propre, quand bien même ladite cible ne possède pas de points de rêve (centre de zone, objet ou plante soumis à une illusion d’Hypnos). Cette aura est également détectable par Détection d’Aura.

    \n

    L’aura de présence de rêve se traduit par un halo bleuté constant ; l’aura résultant d’un effet magique par un halo parcouru de pulsations. Quand les deux auras sont présentes conjointement, le halo est pulsatif et d’un bleu plus foncé. On peut toujours effectuer Détection d’Aura sans aucun risque, il y a toujours une réponse. Soit une aura est perçue, constante ou pulsative, et l’on peut tenter une Lecture d’Aura pour en savoir plus ; soit aucune aura n’est perçue et il s’agit de matière inerte, sans rêve, non soumise à un sort.

    ","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]} -{"_id":"zT72qy3Xb8ye9YKb","name":"Bouilloire de Mélimnod *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    La Grande Écaille Bouilloire de Mélimnod, du nom d'un célèbre haut-rêvant du Second Âge, est un exemple abordable d'objet autonome. Elle doit être posée sur une bouilloire ou un petit chaudron intégralement fait d'argent, de cuivre ou d'étain, à l'exclusion de tout autre métal, d'une capacité de 2 mesures (40 centilitres). La gemme peut être incrustée dans le fond du récipient ou participer à son alliage. A la fin de l'enchantement, avant l'accomplissement de Permanence, elle doit posséder au minimum 1 point de rêve actif. (Le maximum étant comme toujours 7 fois son enchantabilité.) Puis, à la place de Maîtrise, il est obligatoire d'accomplir le rituel d'Autonomie (qui coûte 2 points de seuil). La Grande Écaille peut alors être posée. Il n'en est besoin que d'une seule.

    \n

    Dès que la bouilloire se retrouve pleine d'eau (2 mesures), ou d'un liquide appartenant à l'élément Eau, elle se met à chauffer spontanément et porte le liquide à ébullition ern l'espace d'un seul round. Au bout d'un second round, le liquide est réduit de moitié (une mesure). Puis la bouilloire le fait refroidir, et il se retrouve tout juste tiède au bout d'un troisième round. Il peut alors demeurer indéfiniment dans la bouilloire ou être transvasé, mais dès que la bouilloire se retrouve intégralement pleine, le processus recommence. Chaque chauffe lui coûte un de ses points de rêve actifs. Le rituel d'Autonomie les lui fait récupérer à raison de 3 par heure de complète non-utilisation.

    \n

    Il est bien entendu possible de mettre des herbes de soin dans la bouilloire avant d'y verser l'eau, de façon à obtenir une décoction en un temps record. Etant autonome, la Bouilloire de Mélimnod n'a pas être maîtrisée. La pose de la Grande Écaille coûte 1 point de seuil.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-9","portée":"","caseTMR":"special","caseTMRspeciale":"Monts Brûlants E5","ptreve":"9","portee":"","isrituel":true,"coutseuil":1},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"0N6ILL5RMgmShyM8","name":"Dague de Force","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Même principe que la @Item[r9onPANmiK5E5Jnw]{Flèche de Feu}. Une dague ainsi modifiée a un +dom de +4.

    \n

    La dague de force a une résistance absolue tant que dure l’effet du sort et ne peut être brisée. Les dommages éventuellement reçus sont néanmoins comptabilisés et appliqués au double à l’expiration du sort. Par ailleurs, si la dague modifiée a touché ou été touchée (qu’elle ait blessé, paré, ou été parée), elle perd automatiquement 1 point de résistance à expiration du sort.

    ","draconic":"narcos","duree":"HN","JR":"Il n’y a aucun JR pour les objets ordinaires. Les objets magiques (enchantés) résistent automatiquement, le sort se dissipant sans effet, les points de rêve étant néanmoins dépensés","cible":"Une dague","difficulte":"-5","portée":"","caseTMR":"monts","caseTMRspeciale":"","ptreve":"3","xp":0,"portee":"","isrituel":false,"bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/competence_narcos.svg","effects":[]} +{"_id":"1KMBCeC1qPZTfxle","name":"Gourdin-Dragon","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Il s’agit d’une transformation radicale. Sous l’effet du sort, le gourdin devient une véritable épée dragonne, d’une résistance normale (12), d’un +dom de +3 et d’un encombrement standard de 2. Utilisée ou non, l’arme devient un tas de copeaux  déchiquetés à l’expiration du sort.

    ","draconic":"narcos","duree":"HN","JR":"Il n’y a aucun JR pour les objets ordinaires. Les objets magiques (enchantés) résistent automatiquement, le sort se dissipant sans effet, les points de rêve étant néanmoins dépensés","cible":"Un gourdin, morceau de bois, branche ou autre, de la taille et du diamètre approximatifs d’une épée dragonne","difficulte":"-7","portée":"","caseTMR":"foret","caseTMRspeciale":"","ptreve":"7","xp":0,"isrituel":false,"portee":"","bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/competence_narcos.svg","effects":[]} +{"_id":"4ShhmXKmsIbwoZcG","name":"Maîtrise","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Ce rituel établit le lien qui unira l'objet à son utilisateur, permettant à ce dernier d'en établir la maîtrise. Antinomique du rituel d'Autonomie, réservé à de très spécifiques Grandes Écailles de Narcos, le rituel de Maîtrise est obligatoire pour toutes les écailles courantes : efficacité, activité, protection.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-7","portée":"","caseTMR":"fleuve","caseTMRspeciale":"","ptreve":"7","portee":"","isrituel":true,"xp":0,"bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"5NZnTt0mvfPorSHG","name":"Écailles de Protection contre le venin *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection confère un bons de +1 au jet de CONSTITUTION contre toutes les sortes de venin et de poison, augmentant ainsi les chances de leur résister.

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"foret","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"74XSU8DqNBXGFn3R","name":"Dragonne Lame","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Même principe que la@Item[r9onPANmiK5E5Jnw]{Flèche de Feu} et la @Item[8BJ9kn3AWLFDwvez]{Dague de Force}, y compris la détérioration automatique de 1 point de résistance. Une épée dragonne ainsi modi$ée a un +dom de +6.

    ","draconic":"narcos","duree":"HN","JR":"Il n’y a aucun JR pour les objets ordinaires. Les objets magiques (enchantés) résistent automatiquement, le sort se dissipant sans effet, les points de rêve étant néanmoins dépensés","cible":"Une épée Dragonne (exclusivement)","difficulte":"6","portée":"","caseTMR":"desolation","caseTMRspeciale":"","ptreve":"4","xp":0,"isrituel":false,"portee":"","bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/competence_narcos.svg","effects":[]} +{"_id":"AIBLH8EduhfUQscn","name":"Écaille d'Efficacité *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Les écailles d'efficacité servent à rendre un objet plus efficace, mais uniquement dans sa fonction normale. Une arme magiquement efficace permettra de toucher plus facilement un adversaire ; un bouclier de mieux parer ; un instrument de musique de jouer mieux à moindre effort ; mais un balai magique permettre de mieux balayer et non de voler. Les écailles d'efficacité n'ont de pertinence que sur les objets pouvant être utilisés activement, armes, instruments, outils. Les objets passifs, meubles, contenants, vêtements, armures, ne peuvent pas être rendus plus efficaces.

    \n

    En terme de jeu, chaque écaille d'efficacité possédée par l'objet confère un bonus de +1 sur la table de Résolution lors de son utilisation. S'il s'agit d'une arme, chaque écaille d'efficacité augmente également de 1 le facteur d'initiative, ainsi que le +dom de l'arme, mais jusqu'au maximum du double normal de ce dernier. Soit une épée dragonne (+dom +3) possédant 5 écailles d'efficacité. Son utilisateur bénéficie d'un bonus de +5 à l'initiative, de +5 à l'attaque et à la parade, mais d'un +dom de +6 seulement (le double du +dom normal) et non pas de +8. Ne pas oublier néanmoins de rajouter le +dom personnel dû à la taille et à la force. Cette règle s'applique également aux armes de jet (dague, javelot, fouet). En ce qui concerne les armes de tir (arbalète, arc et fronde), l'efficacité ne s'applique qu'aux dommages  (toujours pour un maximum du double du +dom normal) et non au toucher. Pour qu'un archer bénéficie d'un bonus d'efficacité au toucher et aux dommages, il doit avoir à la fois un arc magique et une flèche magique.

    \n

    Le nombre maximum d'écailles d'efficacité pouvant être posées sur un objet est égal à l'enchantabilité de sa gemme, mais avec un maximum de 7 quelle que soit cette dernière. Pour obtenir des armes magiques d'un bonus supérieur à +7, il faut avoir recours à une éventuelle Grande Écaille de Narcos spécifique.

    \n

    La pose de chaque écaille d'efficacité coûte un point de seuil. Mais il n'y a aucune limite de temps entre la pose de chacune, l'objet pouvant être utilisé dans l'intervalle. Par exemple, on peut se contenter provisoirement d'une épée +1 (une écaille), s'en servir plusieurs fois en combat, et plus tard, rajouter une se conde écaille pour obtenir une épée +2. Toutefois, si entretemps l'objet a été maîtrisé par quelqu'un d'autre, il faut effectuer une Lecture d'Aura complète avant de pouvoir reposer une écaille. Si cette précaution est négligée, on aboutit à un cas de magie impossible. L'utilisation d'un objet magiquement efficace coûte un point de rêve par heure quel que soit le nombre d'écailles.

    \n

    Si plusieurs gemmes sont alliées à un même objet grâce à Individualité et reçoivent toutes des écailles d'efficacité, leurs bonus ne s'ajoutent pas, on ne considère que le meilleur. Des gemmes différentes sont faites pour des pouvoirs entièrement différents.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"monts","caseTMRspeciale":"","ptreve":"7","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"BibuJdKmaQJm3kFw","name":"Annulation de magie","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Ce rituel permet d’annuler un effet magique, que celui-ci ait été accompli par soi-même ou par un autre haut-rêvant. On peut annuler l’effet d’un sort, de zone ou individuel, d’un rituel d’enchantement, d’une invocation, etc.

    \n

    Le haut-rêvant doit se trouver dans la case spécifique des TMR d’où la magie a été accomplie. Le jet de RÊVE qu’il doit réussir a alors la même difficulté que celui ayant permis la magie, avec une dépense de points de rêve pareillement identique.

    \n

    Pour annuler une invocation, le rituel d’Annulation doit être ciblé sur la créature invoquée. Quand la magie est le résultat conjoint de plusieurs rituels, ce qui est notamment le cas des objets magiques, chacun doit être annulé tour à tour, en commençant toujours par le dernier à avoir été accompli chronologiquement. D’une manière générale, ce sont les mêmes opérations qui doivent être répétées à l’envers. Quand un rituel coûte des points de seuil, son annulation en coûte également (le même nombre). Annulation de Magie sert également à exorciser les entités de cauchemar non incarnées. La difficulté d’un exorcisme est toujours R-7, et le coût en points de rêve égal au RÊVE de l’entité. Le ciblage doit être fait sur la créature possédée.

    \n

    Avant d’accomplir une Annulation de Magie, les paramètres de la magie à annuler (case des TMR, R-, r) peuvent être découverts au moyen du rituel Lecture d’Aura.

    \n

    Pour la synthèse d’Annulation de Magie, considérer que ce rituel est de difficulté R-7. Il peut être utilisé indifféremment par Oniros, Hypnos ou Narcos (mais jamais Thanatos), quelle que soit la voie ayant servi à accomplir la magie à annuler.

    ","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"Effet magique","difficulte":"variable","portée":"","caseTMR":"special","caseTMRspeciale":"variable","ptreve":"variable","xp":0,"isrituel":true,"bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]} +{"_id":"FpwaK1qJxKGs9HgS","name":"Permanence *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    C'est par ce rituel que le haut-rêvant stabilise les points de rêve d'une potion ou d'un objet, afin d'en prévenir l'évaporation quotidienne. Facultatif pour les potions, le rituel de Permanence est obligatoire pour tous les autres objets magiques.  Son accomplissement diminue de 1 point le seuil de rêve du haut-rêvant.

    ","draconic":"narcos","duree":"Instantanée","JR":"","cible":"","difficulte":"-5","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"5","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"KW2VZhuEGJGglGcW","name":"Restauration *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Restauration est un rituel secondaire nullement obligatoire. Son seul usage est de redonner des points de rêve actifs à une amulette de protection. Il est en effet impossible d'utiliser le simple Enchantement une fois le rituel de Permanence accompli. Restauration fonctionne de façon semblable à un Enchantement, sauf que son accomplissement coûte chaque fois un point de seuil. On peut  restaurer les points de rêve d'une amulette en plusieurs fois en intercalant un rituel de Purifcation entre chaque rituel de Restauration (qui coûte chaque fois un point de seuil). Il est possible de redonner plus de points de rêve actifs à l'objet qu'il n'en avait au départ, jusqu'à concurrence du maximum possible. Le nombre maximum de points de rêve actifs qu'un objet puisse posséder est égal à 7 fois l'enchantabilité de sa gemme.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"1+","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"P9jMT8pl4pgKEoEW","name":"Écailles de Protection contre le feu *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection diminue de 1 point le jet d'encaissement de tout dommage dû au feu, jouant le rôle d'une \"armure ignifugée\". Soit un personnage possédant une telle amulette dotée de 5 écailles, et se retrouvant dans une zone d'Air en Feu. Au lieu de jouer un jet d'encaissement à +10, il ne la joue qu'à +5. La protection de l'amulette est en plus de la protection physique qu'il peut avoir, laquelle ne peut être - rappelons-le - que d'un maximum de 2 points.

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"desert","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"SUrdOuvvelLtiZMy","name":"Écailles de Protection contre les projectiles *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection diminue de 1 point le jet d'encaissement de tout dommage dû à un projectile, flèche, carreau, pierre de fronde, dague, javelot, fouet. La protection de l'amulette est en plus de l'armure véritable du personnage. Soit un personnage vêtu de cuir épais (prot. 3), possédant une amulette de 3 écailles, et recevant une flèche (+dom +2). Face à une flèche, le cuir épais ne vaut plus que 1, mais on y rajoute les 3 écailles de l'amulette, pour un jet d'encaissement final de -2 au lieu de +1.

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"gouffre","caseTMRspeciale":"","ptreve":"6","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"TSDY6o00ri2ktlVM","name":"Puits de rêve *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Le Puits de rêve permet de stocker des points de rêve et de les y puiser à volonté, c'est en quelque sorte une tirelire de points de rêve. Le Puits de rêve peut avoir la forme de n'importe quel objet et même se contenter d'être une gemme seule. Pour y stocker des points de rêve, l'utilisateur doit le tenir dans sa main nue et se concentrer pendant un round. Il perd autant de points de rêve que souhaité, points qui sont instantanément transvasés dans le Puits de rêve. Aucune montée en TMR ni jets de dés ne sont nécessaires. Pareillement, pour puiser des points de rêve dans le Puits, il suffit de le tenir dans sa main nue au moment de lancer un sort. Au lieu de dépenser ses propres points, l'utilisateur les puise dans le Puits de rêve. Les points puisés ne peuvent avoir qu'un seul usage : alimenter un sort, lancé naturellement ou via une écaille d'activité, ou alimenter un rituel. Rien d'autre. Il ne peuvent pas servir à payer un coût de maîtrise ni un coût d'objet efficace, ni un coût d'amulette de protection. La dépense de points de rêve doit provenir intégralement de l'une ou l'autre source, utilisateur ou Puits de rêve, on ne peut pas partager. On ne peut pas non plus les récupérer pour les \"remettre dans sa tête\".

    \n

    La gemme destinée à recevoir un Puits de rêve n'a pas besoin de points actifs ; si elle en a lors de l'accomplissement de Permanence, ils sont purement et simplement ignorés (annulés). La gemme peut recevoir autant de Grandes Écailles de Puits de rêve que son enchantibilité jusqu'à un maximum de 7. Chaque Grande Écaille permet de stocker jusqu'à 7 points de rêve. Soit une gemme d'enchantabilité 6 possédant 6 Grandes Écailles de Puits de rêve, on peut y stocker jusqu'à 42 points de rêve. Un Puits de rêve n'a jamais besoin d'être entièrement plein et peut pareillement rester vide sans en souffrir. Face à une grosse dépense, on peut le vider entièrement d'un seul coup.

    \n

    Un Puits de rêve peut être posé (avec Individualité) sur une seconde gemme d'un objet possédant une écaille d'activité. Lors de l'utilisation de l'objet, les points de rêve de coût de sort pourront être dépensés par le Puits de rêve ou par l'utilisateur au choix de ce dernier. Un Puits de rêve changeant de main doit être maîtrisé selon la règle normale. La maîtrise a lieu soit au moment où l'on stocke, soit où l'on puise, le premier des deux, et coûte 1 point de rêve par Grande Écaille. Note  : les points dépensés pour la maîtrise ne vont pas dans le Puis de rêve, sils ont perdus.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"8","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"TjhnUMh6UL04k0k8","name":"Purification","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Purification est un rituel secondaire, mais néanmoins obligatoire. A moins de disposer d'une énorme quantité de points de rêve, il est vain d'espérer enchanter l'objet en une seule fois. Purifcation doit toujours s'intercaler entre deux rituels identiques : entre deux Enchantements, mais également entre deux écailles, d'activité ou de protection. Sauter cette étape aboutit à un cas de magie impossible.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"necropole","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"xp":0,"bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"WUYaL4yvr0wFRLjk","name":"Enchantement","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    C'est le rituel de base de tout enchantement, c'est par lui que le haut-rêvant confère des points de rêve à la gemme ou à la potion. Le nombre de points conférés, paramétré au lancer du sort, est à son entière discrétion. Entre deux Enchantements de la même potion ou de la même gemme doit être accompli un rituel de Purificiation.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"1+","portee":"","isrituel":true,"xp":0,"bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"X8yMNrnbFIwTB6oL","name":"Écailles de Protection contre griffes et crocs *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection diminue de 1 point le jet d'encaissement de tout dommage dû aux armes naturelles des animaux, griffes, crocs, mais également piétinement, cornes, tentacules, etc. Elle protège également des dommages au corps à corps de pugilat, coups de poing, coups de pied, mais ne s'applique pas à l'empoignade. La protection est en plus de l'armure véritable du personnage. 

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-10","portée":"","caseTMR":"marais","caseTMRspeciale":"","ptreve":"8","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"Y4r9kTN2brWC2N0n","name":"Lecture d'aura","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Les rituels de Lecture d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.

    \n

    Ce rituel permet d’approfondir les informations fournies par Détection d’Aura. Pratiquer Lecture d’Aura quand il n’y a pas d’aura revient à demander une magie impossible et crée immédiatement une déchirure du rêve.

    \n

    Lecture d’Aura est effectuée en plusieurs étapes, toutes étant de difficulté R-3 et coûtant 3 points de rêve. La première a toujours lieu dans un sanctuaire et ne fait que révéler dans quel(s) autre(s) genre(s) de case(s) le haut-rêvant doit se rendre pour continuer sa lecture. Là, il apprend quel genre de magie a été produit ou à quel type de rêve il a a!aire, de même que les cases spécifiques concernées. Enfin dans les cases spécifiques, le haut-rêvant peut apprendre la force du rêve ou de la magie en cours, c’est-à-dire pratiquement la difficulté et le nombre de points de rêve impliqués, information indispensable dans l’optique d’une annulation de magie.

    \n

    Lecture d’Aura révèle également la couleur de l’aura (fixe ou pulsative) comme Détection d’Aura. Pour les créatures vivantes, on peut donc sauter l’étape de Détection d’Aura et commencer directement par la lecture, puisqu’on est sûr de trouver une aura. Dans les autres cas, il est plus prudent de commencer par la détection si, en l’absence finale d’une aura, on ne veut pas créer de magie impossible. Effectuée sur une créature non soumise à un effet magique ni sous l’emprise d’une entité, Lecture d’Aura indique toujours le Fleuve. Là, dans n’importe quelle case du Fleuve, le haut-rêvant se contente d’apprendre qu’il a a!aire à une créature vivante et douée de rêve.

    ","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"special","caseTMRspeciale":"Sanctuaire / variable","ptreve":"3","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]} +{"_id":"asVUMvyZ0OocReY6","name":"Individualité","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Rituel secondaire, Individualité est néanmoins obligatoire pour les objets possédant plusieurs pouvoirs distincts. Il doit être accompli sur toute nouvelle gemme, enchantée d’au moins un point de rêve actif, avant le rituel d’Alliance. Lors, c’est uniquement à cette nouvelle gemme que s’adresseront les points de rêve et les écailles. Vis à vis d’une nouvelle gemme, le matériau re-possède toute son inertie et doit à nouveau être saturé. Quand un objet a plusieurs gemmes, toutes ont dû recevoir Individualité sauf la première. Les pouvoirs d’un objet doivent être élaborés l’un après l’autre. Dès que l’on a commencé une nouvelle gemme, on ne peut plus revenir sur les précédentes.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"desert","caseTMRspeciale":"","ptreve":"4","xp":0,"isrituel":true,"portee":"","bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/competence_narcos.svg","effects":[]} +{"_id":"ckH9xONcfsffpRVr","name":"Écailles de Protection contre la magie *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection rajoute un +1 à tous les jets de résistance contre les sorts d'illusion-suggestion d'Hypnos ainsi que les rituels de Possession et les sorts et griffes de Thanatos. L'amulette n'est pas spécifique à un sort, elle protège de tous. Soit un personnage possédant une amulette de 4 écailles et devant jouer une JR r-8, il ne joue en réalité qu'un JR r-4, augmentant considérablement ses chances de résister à la magie. La protection ne s'applique qu'à la magie autorisant un JR.

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-8","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"6","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"hWAoVheMfyLIMKZy","name":"Alliance","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"sort","data":{"description":"

    Ce rituel unit magiquement la gemme, seul véritable réceptacle du rêve,au reste de l’objet, en sorte que son pouvoir puisse s’étendre à lui. Ce qui s’applique à la gemme s’applique désormais à l’objet, et inversement. La forme de l’objet participe maintenant à la magie. C’est pourquoi il doit être utilisé comme l’exige sa fonction normale (bague au doigt, etc.) et pourquoi sa forme doit être en analogie avec le ciblage. Pratiquement, une gemme seule ne peut être utilisée que pour une écaille d’activité lançant un sort sur l’utilisateur lui-même (la gemme ne lui permettant pas d’autre ciblage). Une gemme seule pourrait être une amulette de protection, mais il faudrait la tenir sans cesse dans le creux de la main (seule façon d’utiliser une gemme seule). En revanche, on peut s’en contenter pour la Grande Écaille de Narcos Puits de rêve.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-4","portée":"","caseTMR":"pont","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"xp":0,"bonuscase":"","coutseuil":0},"flags":{"core":{"sourceId":"Item.5UQMurs8lNa8eBr0"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"hunCnz9KW1gc5ab7","name":"Autonomie **","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Le rituel d'Autonomie doit obligatoirement être utilisé à la place du rituel de Maîtrise pour les objets autonomes, c'est-à-dire fonctionnant uniquement à partir d'une certaine programmation, sans l'intervention d'un utilisateur. Chaque cas d'objet autonome correspond à une Grande Écaille de Narcos spécifique. Il s'agit  usuellement de dispositifs se mettant automatiquement à fonctionner en présence d'un signal prévu dans leur programmation : piège magique qui se déclenche au moindre bruit, statue qui répète un message quand on passe devant elle, feu ou torche qui s'allume dès qu'on frappe dans ses mains, etc. Les objets autonomes étaient la grande passion des hauts-rêvants du Second Âge, qui les agençaient souvent en de grandioses mises en scène. Pratiquement, un objet autonome dépense ses points de rêve actifs pour obtenir son effet, tout comme un haut-rêvant dépense les siens. Autonomie permet de les récupérer tout seul, à raison de 3 points par heure complète de non-utilisation, sans pouvoir dépasser le nombre de points actifs initial. L'accomplissement du rituel d'Autonomie coûte 2 points de seuil.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-10","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"10","portee":"","isrituel":true,"coutseuil":2,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"lq3jQDJsAflJ2PEy","name":"Flèche de Feu","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    L’intitulé de ce sort n’est que métaphorique. Le sort ne rend pas la flèche ignée, mais augmente son tranchant et son pouvoir de pénétration. Un projectile ainsi modifié (quelle que soit l’arme, flèche ou carreau) a un +dom de +5 et annule 5 points d’armure au lieu de 2 (armure véritable et non pas protection naturelle).

    \n

    Si le projectile n’est pas utilisé, il est retrouvé intact à expiration du sort. Inversement, qu’il ait atteint ou non une cible, sa pointe devient inutilisable, le métal ayant fondu et coulé comme sous l’effet d’une intense chaleur.

    ","draconic":"narcos","duree":"HN","JR":"Il n’y a aucun JR pour les objets ordinaires. Les objets magiques (enchantés) résistent automatiquement, le sort se dissipant sans effet, les points de rêve étant néanmoins dépensés","cible":"Une flèche d'arc ou un carreau d'arbalète","difficulte":"-4","portée":"","caseTMR":"foret","caseTMRspeciale":"","ptreve":"2","xp":0,"isrituel":false,"portee":"","bonuscase":"","coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/templates/competence_narcos.svg","effects":[]} +{"_id":"mh9JjaKckzz1eAoe","name":"Écailles de Protection contre la maladie* ","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection confère un bons de +1 au jet de CONSTITUTION contre toutes les maladies, augmentant ainsi les chances de leur résister.

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-6","portée":"","caseTMR":"cite","caseTMRspeciale":"","ptreve":"4","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"mzAV6EdQlGkVkWEN","name":"Écailles de Protection contre les lames *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Chaque écaille de protection diminue de 1 point le jet d'encaissement de tout dommage dû à une arme de mêlée (dague, épée, hache, lance, masse, fléeau, arme d'hast), mais ni les projectiles ni les dommages au corps à corps. La protection est en plus de l'armure véritable du personnage. 

    \n

    Une amulette peut avoir n'importe quelle forme, mais ne fonctionne que si elle est en contact avec la peau nue de son possesseur. Si c'est le cas, elle fonctionne spontanément en face du danger pour lequel elle est conçue, même si le possesseur n'a aucune idée de son pouvoir. Pour fonctionner, l'amulette a besoin de points de rêve actifs. Ces points doivent être des points de rêve conférés par le rituel d'Enchantement en plus des points inertes. Autrement dit, voulant fabriquer une amulette, le haut-rêvant ne s'arrête pas d'enchanter quand il atteint un nombre de points de rêve égal à l'inertie totale de l'objet, mais continue à en rajouter. Le nombre maximum de points actifs qu'une amulette puisse posséder est égal à 7 fois l'enchantabilité de sa gemme ; et, comme pour les écailles d'efficacité, le nombre d'écailles de protection qu'elle puisse posséder est égal à l'enchantabilité de celle-ci avec un maximum de 7. Des amulettes plus puissantes ne pourraient être obtenues que par de spécifiques Grandes Écailles de Narcos.

    \n

    Soit une gemme de taille 6 et de pureté 5, ayant donc une inertie de 2 et une enchantabilité de 4. Elle peut posséder jusqu'à 4 écailles de protection (=enchantabilité) et un maximum de 28 points de rêve actifs (7   x 4 = 28).

    \n

    Chaque fois qu'une amulette de protection fonctionne, elle dépense un de ses points de rêve actifs quel que soit le nombre d'écailles. Le possesseur, lui, n'en dépense qu'un par heure, quel que soit le nombre de fonctionnements de l'amulette au cours de cette heure. Quand une amulette n'a plus de points actifs, elle cesse de fonctionner. On ne peut lui en redonner que par le rituel de Restauration. Les écailles de protection peuvent être posées progressivement, comme celles d'efficacité, même si l'amulette fonctionne entre temps. Mêmes règles d'application. Une gemme donnée ne peut recevoir que des écailles de protection d'un même type, mais grâce à Individualité, plusieurs gemmes d'une même amulette peuvent offrir des protections différentes. La pose de chaque écaille de protection coûte un point de seuil.

    \n

     

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-10","portée":"","caseTMR":"lac","caseTMRspeciale":"","ptreve":"8","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"sEBhR48HagKNbkob","name":"Écaille d'activité *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    Le rituel d'Écaille d'Activité confère à l'objet magique le pouvoir de lancer un sort. Ce peut être un sort de zone d'Oniros, un sort d'illusion-suggestion ou d'illusion sensorielle d'Hypnos, ou un sort de Thanatos, mais ne peut en aucun cas être un rituel d'aucune des quatre voies. Ayant posé l'écaille d'activité sur l'objet (\"poser\" est le terme consacré à l'accomplissement des rituels d'Écaille), le Haut-Rêvant y lance le sort de son choix et l'objet devient capable de le lancer à son tour. Pratiquement, le haut-rêvant effectue toutes les opérations nécessaires au lancer d'un sort, y compris son paramétrage précis, puis le lance normalement en dépensant les points de rêve du coût. Toutefois, au lieu de cibler comme l'exige le ciblage normal du sort, il touche l'objet possédant l'écaille d'activité. En résultat, aucun effet ne se produit, mais le sort est maintenant enregistré dans la \"mémoire\" de la gemme. Il suffit ensuite à l'utilisateur de se concentrer mentalement sur l'effet voulu (dont il doit avoir une idée) pour que l'objet lance le sort. Il pourra le lancer indéfiniment.

    \n

    A la fin du round de concentration, l'utilisateur doit être capable de dépenser les points de rêve exigés par le coût du sort tel qu'il est paramétéré. S'il n'en a pas assez, il ne dépense rien, mais l'objet ne fonctionne pas. Puis cela étant fait, le sort opère au tout début du round suivant, selon le ciblage voulu par l'utilisateur, fonction de la forme de l'objet et de la façon dont il est utilisé. Pour que le sort puisse être ciblé ailleurs que sur l'utilisateur lui-même, l'objet doit avoir une forme oblongue, analogue au doigt pointé d'un haut-rêvant. Le sort enregistré dans la gemme est paramétré une fois pour toutes. Un objet lançant un sort de Sommeil de 5 rounds lancera toujours un sort de Sommeil de 5 rounds, ni plus ni moins. Un objet lançant une illusion visuelle ne lancera toujours que la même illusion au moindre détail près. La portée est celle de l'EMPATHIE du 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.

    \n

    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 soi-même, mais évite la montée en TMR, les rencontres, et confère la certitude que le sort partira à coup sûr. L'effet d'un sort lancé par un objet peut être annulé par Annulatrion de Magie, mais pas par Annulation de ses Propres Zones ni Annulation de ses Propres Illusions.

    \n

    Chaque gemme d'un objet ne peut recevoir qu'une seule écaille d'activité, et la pose de cette dernière coûte un point de seuil. Une écaille d'activité ne peut enregistrer et lancer q'un seul sort. Mais un même objet peut avoir plusieurs gemmes, grâce à Individualité, chacune possédant une écaille d'activité pour lancer un sort différent.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-9","portée":"","caseTMR":"desolation","caseTMRspeciale":"","ptreve":"7","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} +{"_id":"xOicgRMCUxJNmVzF","name":"Détection d'aura","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"sort","data":{"description":"

    Les rituels de Détection d’Aura peuvent indifféremment être accomplis par n’importe laquelle des quatre voies.

    \n

    Toutes les créatures vivantes animées (humains, humanoïdes, animaux) ont une caractéristique RÊVE. Les objets enchantés possèdent des points de rêve, de même que les produits de magie naturelle, comme certaines pierres de chance. Les entités de cauchemar, incarnées ou non, en ont également. Quelle qu’elle soit, la présence de rêve émet une aura, laquelle est détectable par Détection d’Aura. Parallèlement, toute cible d’un sort ou d’un rituel, émet une aura propre, quand bien même ladite cible ne possède pas de points de rêve (centre de zone, objet ou plante soumis à une illusion d’Hypnos). Cette aura est également détectable par Détection d’Aura.

    \n

    L’aura de présence de rêve se traduit par un halo bleuté constant ; l’aura résultant d’un effet magique par un halo parcouru de pulsations. Quand les deux auras sont présentes conjointement, le halo est pulsatif et d’un bleu plus foncé. On peut toujours effectuer Détection d’Aura sans aucun risque, il y a toujours une réponse. Soit une aura est perçue, constante ou pulsative, et l’on peut tenter une Lecture d’Aura pour en savoir plus ; soit aucune aura n’est perçue et il s’agit de matière inerte, sans rêve, non soumise à un sort.

    ","draconic":"oniros","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-3","portée":"","caseTMR":"sanctuaire","caseTMRspeciale":"","ptreve":"1","xp":0,"bonuscase":"","isrituel":false,"coutseuil":0},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.png","effects":[]} +{"_id":"zT72qy3Xb8ye9YKb","name":"Bouilloire de Mélimnod *","permission":{"default":0,"6ibmdmaeRSMTjU4c":3},"type":"sort","data":{"description":"

    La Grande Écaille Bouilloire de Mélimnod, du nom d'un célèbre haut-rêvant du Second Âge, est un exemple abordable d'objet autonome. Elle doit être posée sur une bouilloire ou un petit chaudron intégralement fait d'argent, de cuivre ou d'étain, à l'exclusion de tout autre métal, d'une capacité de 2 mesures (40 centilitres). La gemme peut être incrustée dans le fond du récipient ou participer à son alliage. A la fin de l'enchantement, avant l'accomplissement de Permanence, elle doit posséder au minimum 1 point de rêve actif. (Le maximum étant comme toujours 7 fois son enchantabilité.) Puis, à la place de Maîtrise, il est obligatoire d'accomplir le rituel d'Autonomie (qui coûte 2 points de seuil). La Grande Écaille peut alors être posée. Il n'en est besoin que d'une seule.

    \n

    Dès que la bouilloire se retrouve pleine d'eau (2 mesures), ou d'un liquide appartenant à l'élément Eau, elle se met à chauffer spontanément et porte le liquide à ébullition ern l'espace d'un seul round. Au bout d'un second round, le liquide est réduit de moitié (une mesure). Puis la bouilloire le fait refroidir, et il se retrouve tout juste tiède au bout d'un troisième round. Il peut alors demeurer indéfiniment dans la bouilloire ou être transvasé, mais dès que la bouilloire se retrouve intégralement pleine, le processus recommence. Chaque chauffe lui coûte un de ses points de rêve actifs. Le rituel d'Autonomie les lui fait récupérer à raison de 3 par heure de complète non-utilisation.

    \n

    Il est bien entendu possible de mettre des herbes de soin dans la bouilloire avant d'y verser l'eau, de façon à obtenir une décoction en un temps record. Etant autonome, la Bouilloire de Mélimnod n'a pas être maîtrisée. La pose de la Grande Écaille coûte 1 point de seuil.

    ","draconic":"narcos","duree":"Instantanée","JR":"Aucun","cible":"","difficulte":"-9","portée":"","caseTMR":"special","caseTMRspeciale":"Monts Brûlants E5","ptreve":"9","portee":"","isrituel":true,"coutseuil":1,"xp":0,"bonuscase":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.png","effects":[]} diff --git a/packs/tetes-de-dragon-pour-haut-revants.db b/packs/tetes-de-dragon-pour-haut-revants.db index 314ab02a..aeaa1281 100644 --- a/packs/tetes-de-dragon-pour-haut-revants.db +++ b/packs/tetes-de-dragon-pour-haut-revants.db @@ -1,10 +1,11 @@ -{"_id":"5JccZSafqCXYqrwU","name":"Connaissance du fleuve","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Cette tête permet de téléporter instantanément son demi-rêve de n’importe quelle case de fleuve à n’importe quelle autre. Il s’agit du fleuve seul, à l’exclusion des cases de lac et marais. La téléportation remplace le mouvement normal et coûte donc un point de fatigue. Comme après un mouvement normal, une rencontre doit être tirée dans la case de fleuve d’arrivée, puis cette dernière doit être maîtrisée selon la règle usuelle. Noter enfin que la téléportation n’est possible que si le demi-rêve est libre de son mouvement, c’est-à-dire s’il n’est sous l’emprise ni d’un Reflet, ni d’un Tourbillon. Unique.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"} -{"_id":"BT18LAdIqEgSG2Hh","name":"Réserve en sécurité","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Un haut-rêvant possédant cette tête peut pénétrer sur une case où il a un sort en réserve sans forcément le déclencher s’il ne le souhaite pas. Même chose si un Tourbillon l’abandonne sur une case de réserve. Déclencher un sort en réserve devient un acte volontaire. Même chose pour un échec total en réserve. Cette tête s’applique à toutes les cases. Unique.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"} -{"_id":"SFxPAvWpEGYHI8mO","name":"Connaissance intuitive d'un nouveau sort","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Le haut-rêvant bénéficiaire de cette tête se retrouve en possession d’un nouveau sort ou rituel, déterminé par un procédé aléatoire quelconque.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"} -{"_id":"VWOXA0q6GB7o8oxz","name":"Don de double-rêve","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Lors de la récupération des points de rêve, permet de jeter 1ddr toutes les demi-heures draconiques au lieu de toutes les heures. Unique.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"} -{"_id":"YDo0a0ApM8iW9g82","name":"Terre d'attache","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Par cette tête, le haut-rêvant peut désigner une case des TMR de son choix à l’exception d’une case humide. Ensuite, à n’importe quel round de son périple en TMR, il peut s’y téléporter directement quel que soit le nombre de cases qui l’en sépare. Cette téléportation instantanée remplace son mouvement normal et coûte donc un point de fatigue. De même, tout comme après un mouvement normal, 1d7 de rencontre doit être tiré dès l’arrivée dans la terre d’attache. Enfin, le haut-rêvant ne peut s’y téléporter que s’il est libre de son mouvement, c’est-à-dire s’il n’est sous l’emprise ni d’un Reflet d’ancien rêve, ni d’un Tourbillon. Cumulable : on peut avoir plusieurs terres d’attache.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"} -{"_id":"ZVh8PLlAzAJulr37","name":"Don de déplacement accéléré","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Permet à tout moment l’option du déplacement accéléré dans les TMR sans avoir à dépenser un point de rêve supplémentaire. Unique.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"} -{"_id":"Zlt01O2sFrVR9pus","name":"Augmentation du seuil de rêve","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Permet d’augmenter le seuil de rêve de 2 points. Cumulable jusqu’à un maximum du double de la caractéristique Rêve.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"} -{"_id":"ZuTV36GyOhFgTlE7","name":"Présents de cités","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Par cette tête, chaque cité offre automatiquement soit une Fleur des rêves, soit un Passeur, soit un Messager, dès qu’elle est visitée par le demi-rêve du haut-rêvant. Il n’y a pas de d7 à tirer, le haut-rêvant choisit librement ce qu’il 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 qu’elle a offert son présent, la cité redevient normale en ce qui concerne le tirage des rencontres; il n’y a qu’un 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, la tête ne peut être ré-obtenue.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"} -{"_id":"a3Y5W0AX5EKxZRSL","name":"Quête des eaux","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Sous l’influence de cette tête, le haut-rêvant est invité à se rendre dans un lac ou dans un marais de son choix. Dès que cette case, lac ou marais, a été maîtrisée selon les règles usuelles, la victoire devient définitive, et la case n’aura plus jamais besoin d’être maîtrisée. Une fois le lac ou le marais choisi, le haut-rêvant ne peut en changer, mais a droit à un nombre illimité d’essais pour le maîtriser. Cumulable : on peut maîtriser définitivement plusieurs lacs ou marais.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"} -{"_id":"bFdU6ddgj4BAlJZX","name":"Réserve extensible","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Une (seule) case spécifique librement choisie par le haut-rêvant à l’exception d’une case de fleuve, n’est plus dorénavant limitée à un seul sort en réserve. Le haut-rêvant peut y en stocker autant qu’il le désire (dans les limites du nombre permis par ses niveaux). En conséquence, tant que ce maximum n’est pas atteint, le demi-rêve peut entrer dans la case concernée sans déclencher les sorts qui s’y trouvent. Le haut-rêvant peut se contenter d’y passer, ou rajouter un sort aux précédents. Dès que le maximum permis est atteint, le fait de passer par la case déclenche automatiquement l’un des sorts (au choix). Les sorts peuvent être déclenchés l’un après l’autre (rappelons que déclencher un sort fait obligatoirement redescendre le demi-rêve), ou déclenchés ensemble (tout ou partie d’entre eux) à la condition expresse qu’ils aient la même cible (même créature, objet, ou centre de zone). Cumulable : on peut avoir plusieurs cases de réserve extensible.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp"} +{"_id":"5JccZSafqCXYqrwU","name":"Connaissance du fleuve","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Cette tête permet de téléporter instantanément son demi-rêve de n’importe quelle case de fleuve à n’importe quelle autre. Il s’agit du fleuve seul, à l’exclusion des cases de lac et marais. La téléportation remplace le mouvement normal et coûte donc un point de fatigue. Comme après un mouvement normal, une rencontre doit être tirée dans la case de fleuve d’arrivée, puis cette dernière doit être maîtrisée selon la règle usuelle. Noter enfin que la téléportation n’est possible que si le demi-rêve est libre de son mouvement, c’est-à-dire s’il n’est sous l’emprise ni d’un Reflet, ni d’un Tourbillon. Unique.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","effects":[]} +{"_id":"BT18LAdIqEgSG2Hh","name":"Réserve en sécurité","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Un haut-rêvant possédant cette tête peut pénétrer sur une case où il a un sort en réserve sans forcément le déclencher s’il ne le souhaite pas. Même chose si un Tourbillon l’abandonne sur une case de réserve. Déclencher un sort en réserve devient un acte volontaire. Même chose pour un échec total en réserve. Cette tête s’applique à toutes les cases. Unique.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","effects":[]} +{"name":"Présent des cités","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"tete","data":{"description":"

    Par cette tête, chaque cité offre automatiquement soit une Fleur des rêves, soit un Passeur, soit un Messager, dès qu’elle est visitée par le demi-rêve du haut-rêvant. Il n’y a pas de d7 à tirer, le haut-rêvant choisit librement ce qu’il 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 qu’elle a offert son présent, la cité redevient normale en ce qui concerne le tirage des rencontres; il n’y a qu’un 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, la tête ne peut être ré-obtenue.

    "},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","effects":[],"_id":"E4a4O1IdrgbNGpVy"} +{"_id":"SFxPAvWpEGYHI8mO","name":"Connaissance intuitive d'un nouveau sort","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Le haut-rêvant bénéficiaire de cette tête se retrouve en possession d’un nouveau sort ou rituel, déterminé par un procédé aléatoire quelconque.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","effects":[]} +{"_id":"VWOXA0q6GB7o8oxz","name":"Don de double-rêve","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Lors de la récupération des points de rêve, permet de jeter 1ddr toutes les demi-heures draconiques au lieu de toutes les heures. Unique.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","effects":[]} +{"_id":"YDo0a0ApM8iW9g82","name":"Terre d'attache","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Par cette tête, le haut-rêvant peut désigner une case des TMR de son choix à l’exception d’une case humide. Ensuite, à n’importe quel round de son périple en TMR, il peut s’y téléporter directement quel que soit le nombre de cases qui l’en sépare. Cette téléportation instantanée remplace son mouvement normal et coûte donc un point de fatigue. De même, tout comme après un mouvement normal, 1d7 de rencontre doit être tiré dès l’arrivée dans la terre d’attache. Enfin, le haut-rêvant ne peut s’y téléporter que s’il est libre de son mouvement, c’est-à-dire s’il n’est sous l’emprise ni d’un Reflet d’ancien rêve, ni d’un Tourbillon. Cumulable : on peut avoir plusieurs terres d’attache.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","effects":[]} +{"_id":"ZVh8PLlAzAJulr37","name":"Don de déplacement accéléré","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Permet à tout moment l’option du déplacement accéléré dans les TMR sans avoir à dépenser un point de rêve supplémentaire. Unique.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","effects":[]} +{"_id":"Zlt01O2sFrVR9pus","name":"Augmentation du seuil de rêve","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Permet d’augmenter le seuil de rêve de 2 points. Cumulable jusqu’à un maximum du double de la caractéristique Rêve.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","effects":[]} +{"_id":"ZuTV36GyOhFgTlE7","name":"Présents de cités","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Par cette tête, chaque cité offre automatiquement soit une Fleur des rêves, soit un Passeur, soit un Messager, dès qu’elle est visitée par le demi-rêve du haut-rêvant. Il n’y a pas de d7 à tirer, le haut-rêvant choisit librement ce qu’il 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 qu’elle a offert son présent, la cité redevient normale en ce qui concerne le tirage des rencontres; il n’y a qu’un 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, la tête ne peut être ré-obtenue.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","effects":[]} +{"_id":"a3Y5W0AX5EKxZRSL","name":"Quête des eaux","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Sous l’influence de cette tête, le haut-rêvant est invité à se rendre dans un lac ou dans un marais de son choix. Dès que cette case, lac ou marais, a été maîtrisée selon les règles usuelles, la victoire devient définitive, et la case n’aura plus jamais besoin d’être maîtrisée. Une fois le lac ou le marais choisi, le haut-rêvant ne peut en changer, mais a droit à un nombre illimité d’essais pour le maîtriser. Cumulable : on peut maîtriser définitivement plusieurs lacs ou marais.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","effects":[]} +{"_id":"bFdU6ddgj4BAlJZX","name":"Réserve extensible","permission":{"default":0,"jOzRscDxoXZWpGS6":3},"type":"tete","data":{"description":"

    Une (seule) case spécifique librement choisie par le haut-rêvant à l’exception d’une case de fleuve, n’est plus dorénavant limitée à un seul sort en réserve. Le haut-rêvant peut y en stocker autant qu’il le désire (dans les limites du nombre permis par ses niveaux). En conséquence, tant que ce maximum n’est pas atteint, le demi-rêve peut entrer dans la case concernée sans déclencher les sorts qui s’y trouvent. Le haut-rêvant peut se contenter d’y passer, ou rajouter un sort aux précédents. Dès que le maximum permis est atteint, le fait de passer par la case déclenche automatiquement l’un des sorts (au choix). Les sorts peuvent être déclenchés l’un après l’autre (rappelons que déclencher un sort fait obligatoirement redescendre le demi-rêve), ou déclenchés ensemble (tout ou partie d’entre eux) à la condition expresse qu’ils aient la même cible (même créature, objet, ou centre de zone). Cumulable : on peut avoir plusieurs cases de réserve extensible.

    ","refoulement":null},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp","effects":[]} diff --git a/styles/simple.css b/styles/simple.css index 94ebf9e2..9e33cca0 100644 --- a/styles/simple.css +++ b/styles/simple.css @@ -675,6 +675,7 @@ ul, li { .subacteur-label, .chant-label, .musique-label, +.oeuvre-label, .chant-label, .danse-label, .recette-label, diff --git a/system.json b/system.json index 51b740bd..e1b9dfe4 100644 --- a/system.json +++ b/system.json @@ -2,11 +2,11 @@ "name": "foundryvtt-reve-de-dragon", "title": "Rêve de Dragon", "description": "Rêve de Dragon RPG for FoundryVTT", - "version": "1.3.15", + "version": "1.3.20", "manifestPlusVersion": "1.0.0", "minimumCoreVersion": "0.7.5", "compatibleCoreVersion": "0.7.9", - "templateVersion": 90, + "templateVersion": 93, "author": "LeRatierBretonnien", "authors": [ { diff --git a/template.json b/template.json index 79ce365f..17852e84 100644 --- a/template.json +++ b/template.json @@ -261,7 +261,7 @@ "dexterite": { "type": "number", "value": 10, - "label": "Dexterité", + "label": "Dextérité", "xp": 0, "derivee": false }, @@ -435,7 +435,8 @@ "reve": { "max": 0, "value": 10, - "label": "Points de Rêve actuels" + "label": "Points de Rêve actuels", + "thanatosused": false }, "seuil": { "max": 0, @@ -467,7 +468,7 @@ }, "ombres": { "list": [] - } + } }, "compteurs": { "sust": { @@ -563,7 +564,7 @@ "Item": { "types": ["objet", "arme", "armure", "conteneur", "competence", "sort", "herbe", "ingredient", "livre", "potion", "munition", "rencontresTMR", "queue", "ombre", "souffle", "tete", "competencecreature", "tarot", "monnaie", "nombreastral", "tache", "meditation", "casetmr", "recettealchimique", - "musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison" ], + "musique", "chant", "danse", "jeu", "recettecuisine", "maladie", "poison", "oeuvre" ], "objet": { "description": "", "quantite": 1, @@ -775,6 +776,7 @@ }, "musique": { "niveau": "", + "reference": "", "description": "" }, "danse": { @@ -782,16 +784,19 @@ "agilite": false, "apparence": false, "niveau": "", + "reference": "", "description": "" }, "chant": { "niveau": "", + "reference": "", "description": "" }, "jeu": { "type": "", "base": "", "caraccomp": "", + "reference": "", "description": "" }, "recettecuisine": { @@ -799,6 +804,15 @@ "ingredients": "", "duree": "", "sust": 0, + "exotisme": 0, + "reference": "", + "description": "" + }, + "oeuvre": { + "default_carac": "", + "competence": "", + "niveau": 0, + "reference": "", "description": "" }, "maladie": { @@ -815,7 +829,6 @@ "dommages":"", "description": "" } - } } diff --git a/templates/actor-sheet.html b/templates/actor-sheet.html index 2e8873d4..2ae3963d 100644 --- a/templates/actor-sheet.html +++ b/templates/actor-sheet.html @@ -128,7 +128,7 @@

+ {{!-- Liste de blessures --}}

Blessures:

@@ -650,32 +651,42 @@ {{!-- Connaissances Tab --}}
-

Chants :

+

Oeuvres diverses :

-

Danses :

- -

Musiques :

- -

Recettes de Cuisine :

-

Recettes Alchimiques

    {{#each data.recettesAlchimiques as |recette id|}} @@ -825,6 +825,20 @@ {{/each}}
+
+
+

Rencontres présentes:

+ +
{{!-- Queues, Souffles, Tetes, Ombre --}}
diff --git a/templates/casetmr-specific-list.html b/templates/casetmr-specific-list.html index 64a4e6d2..d69feec5 100644 --- a/templates/casetmr-specific-list.html +++ b/templates/casetmr-specific-list.html @@ -3,3 +3,9 @@ + + + + + + diff --git a/templates/chat-demande-defense.html b/templates/chat-demande-defense.html index 8b9b1ade..c9d2fe76 100644 --- a/templates/chat-demande-defense.html +++ b/templates/chat-demande-defense.html @@ -37,19 +37,19 @@ {{else}} {{#each armes as |arme key|}} - Parer avec {{arme.name}} à {{../diffLibre }} + Parer avec {{arme.name}} à {{../diffLibre }} (Utilisation : {{arme.data.nbUsage}})
{{/each}} {{#if mainsNues}} - Parer à mains nues à {{diffLibre}} + Parer à mains nues à {{diffLibre}} (Utilisation : {{arme.data.nbUsage}})
{{/if}} {{#if (ne attaqueCategorie 'tir')}} - Esquiver à {{diffLibre}} + Esquiver à {{diffLibre}} (Utilisation : {{esquiveUsage}})
{{/if}} diff --git a/templates/chat-resultat-chant.html b/templates/chat-resultat-chant.html index 13491202..4143eb70 100644 --- a/templates/chat-resultat-chant.html +++ b/templates/chat-resultat-chant.html @@ -1,4 +1,4 @@ -chant +{{oeuvre.data.competence}}

{{alias}} tente de chanter la chanson : {{oeuvre.name}} (niveau {{oeuvre.data.niveau}})

@@ -11,3 +11,18 @@ {{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}. {{/if}}
+{{#if oeuvre.data.description}} +
+ + {{{oeuvre.data.description}}} + {{#if oeuvre.data.reference}} +

{{oeuvre.data.reference}}

+ {{/if}} +
+{{else if oeuvre.data.reference}} +
+ +

{{oeuvre.data.reference}}

+
+{{/if}} + diff --git a/templates/chat-resultat-cuisine.html b/templates/chat-resultat-cuisine.html deleted file mode 100644 index 9a184f50..00000000 --- a/templates/chat-resultat-cuisine.html +++ /dev/null @@ -1,13 +0,0 @@ -cuisine -

- {{alias}} tente de cuisiner la recette : {{oeuvre.name}} (niveau {{oeuvre.data.niveau}}) -

-{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}} -
-
- {{#if rolled.isSuccess}} - {{alias}} réussit sa recette, avec un plat de {{qualiteFinale}} pour {{oeuvre.data.sust}} Points de Sustentation. - {{else}} - {{alias}} fait un pière cuisinier(e), et obtient une qualité de {{qualiteFinale}}. Selon la décision du MJ, le plat peut fournir {{oeuvre.data.sust}} Points de Sustentation - {{/if}} -
diff --git a/templates/chat-resultat-danse.html b/templates/chat-resultat-danse.html index 21d03a95..abe93ba7 100644 --- a/templates/chat-resultat-danse.html +++ b/templates/chat-resultat-danse.html @@ -1,4 +1,4 @@ -danse +{{oeuvre.data.competence}}

{{alias}} tente de danser : {{oeuvre.name}} (niveau {{oeuvre.data.niveau}})

@@ -11,3 +11,18 @@ {{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}. {{/if}}
+{{#if oeuvre.data.description}} +
+ + {{{oeuvre.data.description}}} + {{#if oeuvre.data.reference}} +

{{oeuvre.data.reference}}

+ {{/if}} +
+{{else if oeuvre.data.reference}} +
+ +

{{oeuvre.data.reference}}

+
+{{/if}} + diff --git a/templates/chat-resultat-jeu.html b/templates/chat-resultat-jeu.html index d1af862c..c8e1736c 100644 --- a/templates/chat-resultat-jeu.html +++ b/templates/chat-resultat-jeu.html @@ -1,4 +1,4 @@ -jeu +{{oeuvre.data.competence}}

{{alias}} joue à : {{oeuvre.name}}

@@ -11,3 +11,18 @@ {{alias}} a perdu ... {{/if}} +{{#if oeuvre.data.description}} +
+ + {{{oeuvre.data.description}}} + {{#if oeuvre.data.reference}} +

{{oeuvre.data.reference}}

+ {{/if}} +
+{{else if oeuvre.data.reference}} +
+ +

{{oeuvre.data.reference}}

+
+{{/if}} + diff --git a/templates/chat-resultat-maitrise-tmr.html b/templates/chat-resultat-maitrise-tmr.html new file mode 100644 index 00000000..e5f4fa6f --- /dev/null +++ b/templates/chat-resultat-maitrise-tmr.html @@ -0,0 +1,30 @@ +{{competence.name}} +

+ {{alias}} tente de {{maitrise.verbe}} {{le tmr.genre}} {{tmr.label}} ({{tmr.coord}}) +

+{{#if previous}} + {{#with previous}} + {{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}} +
Double résistance du fleuve!
+ {{/with}} +{{/if}} +{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}} +
+ +{{#if rolled.isSuccess}} + Vous parvenez à {{maitrise.verbe}} {{le tmr.genre}} {{tmr.label}} ! + {{else}} + Vous ne parvenez pas à {{maitrise.verbe}} {{le tmr.genre}} {{tmr.label}}. + Vous quittez les Terres Médianes ! + {{#if souffle}} +
De plus, votre échec total vous fait subir un Souffle de Dragon : {{souffle.name}} + {{/if}} +{{/if}} +
+{{#if poesie}} +
+ + {{{poesie.extrait}}} +

{{poesie.reference}}

+
+{{/if}} diff --git a/templates/chat-resultat-musique.html b/templates/chat-resultat-musique.html index f39253e0..ffea62b6 100644 --- a/templates/chat-resultat-musique.html +++ b/templates/chat-resultat-musique.html @@ -1,4 +1,4 @@ -musique +{{oeuvre.data.competence}}

{{alias}} tente de jouer le morceau : {{oeuvre.name}} (niveau {{oeuvre.data.niveau}})

@@ -11,3 +11,18 @@ {{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}. {{/if}} +{{#if oeuvre.data.description}} +
+ + {{{oeuvre.data.description}}} + {{#if oeuvre.data.reference}} +

{{oeuvre.data.reference}}

+ {{/if}} +
+{{else if oeuvre.data.reference}} +
+ +

{{oeuvre.data.reference}}

+
+{{/if}} + diff --git a/templates/chat-resultat-oeuvre.html b/templates/chat-resultat-oeuvre.html new file mode 100644 index 00000000..84141952 --- /dev/null +++ b/templates/chat-resultat-oeuvre.html @@ -0,0 +1,29 @@ +

{{oeuvre.data.competence}} + + {{alias}} tente d'interpréter {{oeuvre.name}} (niveau {{oeuvre.data.niveau}}) +

+
{{upperFirst oeuvre.data.default_carac}} / {{oeuvre.data.competence}} +{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}} +
+
+ {{#if rolled.isSuccess}} + {{alias}} réussi son interprétation avec une qualité de {{qualiteFinale}} . + {{else}} + {{alias}} est peu inspiré(e) et son interprétation a une qualité de {{qualiteFinale}}. + {{/if}} +
+{{#if oeuvre.data.description}} +
+ + {{{oeuvre.data.description}}} + {{#if oeuvre.data.reference}} +

{{oeuvre.data.reference}}

+ {{/if}} +
+{{else if oeuvre.data.reference}} +
+ +

{{oeuvre.data.reference}}

+
+{{/if}} + diff --git a/templates/chat-resultat-recettecuisine.html b/templates/chat-resultat-recettecuisine.html new file mode 100644 index 00000000..fa75d72d --- /dev/null +++ b/templates/chat-resultat-recettecuisine.html @@ -0,0 +1,34 @@ +{{oeuvre.data.competence}} +

+ {{alias}} tente de cuisiner la recette : {{oeuvre.name}} (niveau {{oeuvre.data.niveau}}) +

+{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}} +
+ +{{#if rolled.isSuccess}} + {{alias}} réussit sa recette, avec un plat de {{qualiteFinale}} pour {{oeuvre.data.sust}} Points de Sustentation. +{{else}} + {{alias}} fait un pière cuisinier(e), et obtient {{#if (lt qualiteFinale 0)}}un plat à l'exotisme certain{{else}}un plat de qualité {{qualiteFinale}}{{/if}}. + Selon la décision du MJ, le plat peut fournir {{oeuvre.data.sust}} Points de Sustentation +{{/if}} + +{{#if (lt exotismeFinal 0)}} +
Au vu de l'exotisme du plat, les convives devront réussir un jet de Volonté / Cuisine à {{exotismeFinal}}. +En cas d'échec, ils peuvent se forcer pour faire plaisir au Maître Queux, mais devront faire un jet de moral Malheureux. +{{/if}} + +{{#if oeuvre.data.description}} +
+ + {{{oeuvre.data.description}}} + {{#if oeuvre.data.reference}} +

{{oeuvre.data.reference}}

+ {{/if}} +
+{{else if oeuvre.data.reference}} +
+ +

{{oeuvre.data.reference}}

+
+{{/if}} + diff --git a/templates/chat-resultat-reve-de-dragon.html b/templates/chat-resultat-reve-de-dragon.html new file mode 100644 index 00000000..f1aa7992 --- /dev/null +++ b/templates/chat-resultat-reve-de-dragon.html @@ -0,0 +1,28 @@ +Rêve de Dragon +

+ {{alias}} tente de maîtriser un Rêve de Dragon! +

+{{> "systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html"}} +
+ +{{#if rolled.isSuccess}} + Vous maîtrisez le Rêve de Dragon! Vous gagnez ses {{rencontre.force}} points de Rêve. + {{#if tete}} +
Vous devez demander au Gardien des Rêves de faire un tirage sur une des + tables des têtes de dragon (Haut-rêvant ou Tous personnages). + {{/if}} +{{else}} + Vous ne parvenez pas à vaincre le Rêve de Dragon, et prennez un violent coup de queue. + Vous subissez {{#if rolled.isETotal}}deux queues{{else}}une queue{{/if}} de dragon! + {{#each queues as | queue key|}} +
{{queue.name}}: {{{queue.data.data.description}}} + {{/each}} +{{/if}} +
+{{#if poesie}} +
+ + {{{poesie.extrait}}} +

{{poesie.reference}}

+
+{{/if}} diff --git a/templates/chat-resultat-sort.html b/templates/chat-resultat-sort.html index c9ed4073..b17920a9 100644 --- a/templates/chat-resultat-sort.html +++ b/templates/chat-resultat-sort.html @@ -4,7 +4,7 @@ le {{#if selectedSort.data.isrituel}}rituel{{else}}sort{{/if}} {{selectedSort.name}} -
Pour {{selectedSort.data.ptreve_reel}} point{{~#if (gt selectedSort.data.ptreve_reel 1)}}s{{/if}} de rêve en {{coordLabel}} ({{coord}}). +
Pour {{selectedSort.data.ptreve_reel}} point{{~#if (gt selectedSort.data.ptreve_reel 1)}}s{{/if}} de rêve en {{tmr.label}} ({{tmr.coord}}). {{#if show.reveInsuffisant}} Pas assez de rêve! {{/if}} @@ -22,4 +22,8 @@ {{else}}{{depenseReve}} points de rêve ont été dépensés {{~/if}}. -
\ No newline at end of file +
+
+ + {{{selectedSort.data.description}}} + diff --git a/templates/dialog-competence.html b/templates/dialog-competence.html index 4b0ab6e7..b7a32544 100644 --- a/templates/dialog-competence.html +++ b/templates/dialog-competence.html @@ -44,12 +44,20 @@ {{else}} + - + +
+
+ Charge : Les longueurs d'armes n'interviennent pas dans la charge, il faut gérer une initiative aléatoire dans ce cas. +
Feinte : Vous devez avoir l'initative sur votre adversaire et y renoncer. +
+
+
diff --git a/templates/dialog-roll-jeu.html b/templates/dialog-roll-jeu.html index 0d062344..0ccf3b77 100644 --- a/templates/dialog-roll-jeu.html +++ b/templates/dialog-roll-jeu.html @@ -1,23 +1,21 @@
    -
  • -
  • -
  • -
  • +
  • +
  • +
  • +
- - - {{#select carac}} {{#each carac as |caracitem key|}} {{/each}} {{/select}} - - -
+ + {{#select diffConditions}} + {{#each ajustementsConditions as |key|}} + + {{/each}} + {{/select}} + + +
+ {{>"systems/foundryvtt-reve-de-dragon/templates/dialog-roll-surenc.html"}} +
+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/templates/dialog-roll-oeuvre.html b/templates/dialog-roll-oeuvre.html new file mode 100644 index 00000000..f6dc0d41 --- /dev/null +++ b/templates/dialog-roll-oeuvre.html @@ -0,0 +1,37 @@ +
+
+
    +
  • +
  • +
+
+ +
+ + + + +
+ +
+
+
+
+
+
+
+ + diff --git a/templates/dialog-roll-cuisine.html b/templates/dialog-roll-recettecuisine.html similarity index 86% rename from templates/dialog-roll-cuisine.html rename to templates/dialog-roll-recettecuisine.html index d6bdcb32..ef52543e 100644 --- a/templates/dialog-roll-cuisine.html +++ b/templates/dialog-roll-recettecuisine.html @@ -1,8 +1,10 @@
+
    -
  • +
  • +
diff --git a/templates/dialog-roll-reve-de-dragon.html b/templates/dialog-roll-reve-de-dragon.html new file mode 100644 index 00000000..6b584c51 --- /dev/null +++ b/templates/dialog-roll-reve-de-dragon.html @@ -0,0 +1,12 @@ + +

Rêve de Dragon de force {{rencontre.force}}!

+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/templates/dialog-roll-sort.html b/templates/dialog-roll-sort.html index 3879df15..c32366ef 100644 --- a/templates/dialog-roll-sort.html +++ b/templates/dialog-roll-sort.html @@ -1,7 +1,7 @@
- +
diff --git a/templates/enum-initpremierround.html b/templates/enum-initpremierround.html index 6408d711..a2a5f9a9 100644 --- a/templates/enum-initpremierround.html +++ b/templates/enum-initpremierround.html @@ -1,4 +1,4 @@ - + diff --git a/templates/item-chant-sheet.html b/templates/item-chant-sheet.html index a198761b..1d9af9ff 100644 --- a/templates/item-chant-sheet.html +++ b/templates/item-chant-sheet.html @@ -12,6 +12,10 @@
+
+ + +
diff --git a/templates/item-competence-sheet.html b/templates/item-competence-sheet.html index 7d297780..17fefbb0 100644 --- a/templates/item-competence-sheet.html +++ b/templates/item-competence-sheet.html @@ -28,7 +28,7 @@
- +
diff --git a/templates/item-danse-sheet.html b/templates/item-danse-sheet.html index 450de001..ea410cf4 100644 --- a/templates/item-danse-sheet.html +++ b/templates/item-danse-sheet.html @@ -29,6 +29,10 @@
+
+ + +
diff --git a/templates/item-jeu-sheet.html b/templates/item-jeu-sheet.html index 56ad2d67..11649435 100644 --- a/templates/item-jeu-sheet.html +++ b/templates/item-jeu-sheet.html @@ -27,6 +27,10 @@
+
+ + +
diff --git a/templates/item-meditation-sheet.html b/templates/item-meditation-sheet.html index 1893346e..0b484acb 100644 --- a/templates/item-meditation-sheet.html +++ b/templates/item-meditation-sheet.html @@ -50,20 +50,7 @@
diff --git a/templates/item-musique-sheet.html b/templates/item-musique-sheet.html index a198761b..1d9af9ff 100644 --- a/templates/item-musique-sheet.html +++ b/templates/item-musique-sheet.html @@ -12,6 +12,10 @@
+
+ + +
diff --git a/templates/item-oeuvre-sheet.html b/templates/item-oeuvre-sheet.html new file mode 100644 index 00000000..82f2c2b0 --- /dev/null +++ b/templates/item-oeuvre-sheet.html @@ -0,0 +1,45 @@ + +
+ +
+

+
+
+ + {{!-- Sheet Body --}} +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ {{editor content=data.description target="data.description" button=true owner=owner editable=editable}} +
+
+
+ + diff --git a/templates/item-recettecuisine-sheet.html b/templates/item-recettecuisine-sheet.html index b82e08d1..2d64730c 100644 --- a/templates/item-recettecuisine-sheet.html +++ b/templates/item-recettecuisine-sheet.html @@ -9,25 +9,33 @@ {{!-- Sheet Body --}}
- +
- +
- +
+
+ + +
- +
{{editor content=data.ingredients target="data.ingredients" button=true owner=owner editable=editable}}
+
+ + +
- +
{{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
diff --git a/templates/item-sort-sheet.html b/templates/item-sort-sheet.html index 728b0d73..a77801a0 100644 --- a/templates/item-sort-sheet.html +++ b/templates/item-sort-sheet.html @@ -21,6 +21,7 @@
diff --git a/templates/sort-tmr.html b/templates/sort-tmr.html index c716adbc..0231eb92 100644 --- a/templates/sort-tmr.html +++ b/templates/sort-tmr.html @@ -2,7 +2,7 @@ - + @@ -12,4 +12,4 @@ - +