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/module/actor-sheet.js b/module/actor-sheet.js index 6c7314f0..ef20bd34 100644 --- a/module/actor-sheet.js +++ b/module/actor-sheet.js @@ -9,6 +9,7 @@ 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 +39,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 => { diff --git a/module/actor-vehicule-sheet.js b/module/actor-vehicule-sheet.js index b9136a2b..0a2c90d7 100644 --- a/module/actor-vehicule-sheet.js +++ b/module/actor-vehicule-sheet.js @@ -6,6 +6,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 +37,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 a22e56bf..fadb6bbb 100644 --- a/module/actor.js +++ b/module/actor.js @@ -1,5 +1,5 @@ import { RdDUtility } from "./rdd-utility.js"; -import { TMRUtility } from "./tmr-utility.js"; +import { TMRType, TMRUtility } from "./tmr-utility.js"; import { RdDRollDialogEthylisme } from "./rdd-roll-ethylisme.js"; import { RdDRoll } from "./rdd-roll.js"; import { RdDTMRDialog } from "./rdd-tmr-dialog.js"; @@ -21,6 +21,7 @@ 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 { RdDItem } from "./item.js"; /* -------------------------------------------- */ @@ -1837,22 +1838,25 @@ export class RdDActor extends Actor { } /* -------------------------------------------- */ - checkIsAdditionnalHumide(cellDescr, coordTMR) { - let pontHumide = this.data.items.find(item => item.type == 'souffle' && item.name.toLowerCase().includes(' des ponts')); - if (pontHumide && cellDescr.type == 'pont') { + isCaseHumideAdditionelle(tmr) { + if (tmr.type == 'pont' && this.data.items.find(it => RdDItem.isSoufflePontImpraticable(it))) { ChatMessage.create({ - content: "Vous êtes sous le coup d'une Impraticabilité des Ponts : ils doivent être maîtrisés comme des cases humides.", + 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; } // 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; + let isTmrInondee = this.data.items.filter(it => RdDItem.isCaseTMR(it)) + .filter(it => it.data.coord == tmr.coord) + .find(it => RdDItem.isCaseInnondee(it)); + if (isTmrInondee) { + 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; } @@ -2398,14 +2402,14 @@ 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) { + checkMonteeLaborieuse() { // Return +1 par queue/ombre/souffle Montée Laborieuse présente + let countMonteLaborieuse = this.data.items.filter(item => (item.type == 'queue' || item.type == 'ombre' || item.type == 'souffle') && item.name.toLowerCase().includes('montée laborieuse')).length; + if (countMonteLaborieuse) { 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 ${countMonteLaborieuse} Point de Rêve de plus.`, whisper: ChatMessage.getWhisperRecipients(game.user.name) }); - return 1; + return countMonteLaborieuse; } return 0; } @@ -2414,7 +2418,7 @@ export class RdDActor extends Actor { refreshTMRView( tmrData ) { console.log("REFRESH !!!!"); if ( this.currentTMR ) { - this.currentTMR.forceDemiRevePositionView(tmrData.tmrPos); + this.currentTMR.forceDemiRevePositionView(); } } 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.js b/module/item.js index 46ad7721..988d3ecf 100644 --- a/module/item.js +++ b/module/item.js @@ -1,28 +1,18 @@ +import { Misc } from "./misc.js"; /* -------------------------------------------- */ export class RdDItem { - /* -------------------------------------------- */ - static buildItemsClassification(items) { - return RdDItem.classify(items, it => it.type) + static isSoufflePontImpraticable(item) { + return item.type == 'souffle' && item.name.toLowerCase().includes(' des ponts'); } - static classify(items, classifier = it => it.type, transform = it => it) { - let itemsBy = {}; - RdDItem.classifyInto(itemsBy, items, classifier, transform); - return itemsBy; + static isCaseInnondee(item) { + return RdDItem.isCaseTMR(item) && item.data.specific == 'debordement'; } - 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)); - } - } + static isCaseTMR(item) { + return item.type == 'casetmr'; + } } \ 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/rdd-commands.js b/module/rdd-commands.js index d148eca9..f58eaec9 100644 --- a/module/rdd-commands.js +++ b/module/rdd-commands.js @@ -1,6 +1,5 @@ /* -------------------------------------------- */ -import { ChatUtility } from "./chat-utility.js"; import { DeDraconique } from "./de-draconique.js"; import { RdDItemCompetence } from "./item-competence.js"; import { Misc } from "./misc.js"; @@ -10,7 +9,7 @@ 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)?/; @@ -28,15 +27,17 @@ export class RdDCommands { 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: ["/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 +56,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 +185,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 +232,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(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-rolltables.js b/module/rdd-rolltables.js index 8d7ba802..c0152062 100644 --- a/module/rdd-rolltables.js +++ b/module/rdd-rolltables.js @@ -35,12 +35,12 @@ export class RdDRollTables { } /* -------------------------------------------- */ - static async getSouffle(toChat = true) { + static async getSouffle(toChat = false) { return await RdDRollTables.drawItemFromRollTable("Souffles de Dragon", toChat); } /* -------------------------------------------- */ - static async getQueue(toChat = true) { + 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); @@ -52,17 +52,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..9745a5f6 100644 --- a/module/rdd-tmr-dialog.js +++ b/module/rdd-tmr-dialog.js @@ -200,7 +200,6 @@ export class RdDTMRDialog extends Dialog { this.actor.deleteTMRRencontreAtPosition(); this.updatePreviousRencontres(); - let rencontreData = { actor: this.actor, alias: this.actor.name, @@ -248,20 +247,22 @@ export class RdDTMRDialog extends Dialog { rencontreData.nbRounds++; this.nbFatigue += 1; 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,38 +276,38 @@ 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); } } /* -------------------------------------------- */ - async _jetDeRencontre(coordTMR, cellDescr) { + async _jetDeRencontre(tmr) { if (TMRUtility.isForceRencontre()) { - return await TMRUtility.rencontreTMRRoll(coordTMR, cellDescr); + return await TMRUtility.rencontreTMRRoll(tmr.coord, tmr); } - let rencontre = this.rencontresExistantes.find(prev => prev.coord == coordTMR); + 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); + return await TMRUtility.rencontreTMRRoll(tmr.coord, tmr, isMauvaise); } - this._tellToUser(myRoll.total + ": Pas de rencontre en " + cellDescr.label + " (" + coordTMR + ")"); + this._tellToUser(myRoll.total + ": Pas de rencontre en " + tmr.label + " (" + tmr.coord + ")"); } /* -------------------------------------------- */ @@ -330,13 +331,13 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async manageCaseSpeciale(cellDescr, coordTMR) { + async manageCaseSpeciale(tmr) { for (let caseTMR of this.casesSpeciales) { - if (caseTMR.data.coord == coordTMR) { // Match ! + if (caseTMR.data.coord == tmr.coord) { // Match ! if (caseTMR.data.specific == 'trounoir') { let newTMR = TMRUtility.getTMRAleatoire(); let tmrPos = duplicate(this.actor.data.data.reve.tmrpos); - tmrPos.coord = newTMR; + 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.", @@ -349,12 +350,7 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ isCaseMaitrisee(coordTMR) { - for (let caseTMR of this.casesSpeciales) { - if (caseTMR.data.coord == coordTMR && caseTMR.data.specific == 'maitrisee') { - return true; - } - } - return false; + return this.casesSpeciales.find(it => it.data.coord = coordTMR && it.data.specific == 'maitrisee'); } /* -------------------------------------------- */ @@ -364,19 +360,11 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - 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)) { // TODO: permettre de choisir la voie de draconic? let draconic = this.actor.getBestDraconic(); @@ -404,7 +392,7 @@ export class RdDTMRDialog extends Dialog { 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 + "" + explication += "
Test : Rêve actuel / " + draconic.name + " / " + tmr.type + "" + RdDResolutionTable.explain(rolled); if (rolled.isETotal) { @@ -414,7 +402,7 @@ export class RdDTMRDialog extends Dialog { } if (rolled.isPart) { explication += "
Vous avez fait une Réussite Particulière"; - this.actor._appliquerAjoutExperience({ rolled: rolled, seletedCarac: { label: 'reve' }, competence: draconic.name }) + this.actor._appliquerAjoutExperience({ rolled: rolled, selectedCarac: { label: 'reve' }, competence: draconic.name }) msg2MJ += "
Et a fait une réussite particulière"; } @@ -432,6 +420,21 @@ export class RdDTMRDialog extends Dialog { humideDiag.render(true); } } + + isCaseHumide(tmr) { + 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 false; + } + if (this.actor.isCaseHumideAdditionelle(tmr)) { + return true; + } + return tmr.type == "lac" || tmr.type == "fleuve" || tmr.type == "marais"; + } + /* -------------------------------------------- */ isReserveExtensible(coordTMR) { for (let caseTMR of this.casesSpeciales) { @@ -537,60 +540,38 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - async deplacerDemiReve(event) { + async onClickTMR(event) { if (this.viewOnly) { return; } let origEvent = event.data.originalEvent; - let myself = event.target.tmrObject; + let tmrObject = event.target.tmrObject; - 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 (!RdDTMRDialog._horsDePortee(currentPos, eventPos) || this.isTerreAttache(targetCoordTMR) || this.checkConnaissanceFleuve(currentCoordTMR, targetCoordTMR)) { 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,29 +579,71 @@ 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.nbFatigue += 1; + 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.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); + this.manageCaseHumide(tmr); + await this.declencheSortEnReserve(tmr.coord); } /* -------------------------------------------- */ @@ -661,7 +684,7 @@ export class RdDTMRDialog extends Dialog { mytmr.buttonMode = true; mytmr.tmrObject = this; if (!this.viewOnly) { - mytmr.on('pointerdown', this.deplacerDemiReve); + mytmr.on('pointerdown', this.onClickTMR); } this.pixiApp.stage.addChild(mytmr); @@ -676,42 +699,36 @@ export class RdDTMRDialog extends Dialog { } // 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; - } + let reveCout = (this.tmrdata.isRapide && !this.actor.checkTeteDeplacementAccelere()) ? -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(); + let tmr = TMRUtility.getTMR(this.actor.data.data.reve.tmrpos.coord); + await this.manageRencontre(tmr, () => { + this.postRencontre(tmr); + 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); } /* -------------------------------------------- */ @@ -811,14 +828,14 @@ export class RdDTMRDialog extends Dialog { } /* -------------------------------------------- */ - _updateDemiReve(myself) { - myself._setTokenPosition(myself.demiReve); + _updateDemiReve() { + this._setTokenPosition(this.demiReve); } /* -------------------------------------------- */ /** Retourne les coordonnées x, h, w, h du rectangle d'une case donnée */ _getCaseRectangleCoord(coord) { - let coordXY = TMRUtility.convertToCellCoord(coord); + let coordXY = TMRUtility.convertToCellPos(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; @@ -827,7 +844,7 @@ export class RdDTMRDialog extends Dialog { /* -------------------------------------------- */ _setTokenPosition(token) { - let coordXY = TMRUtility.convertToCellCoord(token.coordTMR()); + let coordXY = TMRUtility.convertToCellPos(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; diff --git a/module/rdd-tmr-rencontre-dialog.js b/module/rdd-tmr-rencontre-dialog.js index 5b432fda..dfa9ffb3 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.maitriser()) } }, 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(); + } + onButtonFuir(action) { + this.toClose = true; + await action(); + } + /* -------------------------------------------- */ close() { - if ( this.toClose ) { + if (this.toClose) { this.tmrApp.maximize(); return super.close(); } diff --git a/module/tmr-rencontres.js b/module/tmr-rencontres.js index da24a414..cab3a844 100644 --- a/module/tmr-rencontres.js +++ b/module/tmr-rencontres.js @@ -84,7 +84,7 @@ 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); return `Le ${data.rencontre.name} vous embobine avec des promesses, et vous transporte en ${data.newTMR.label} sans attendre votre avis.`; diff --git a/module/tmr-utility.js b/module/tmr-utility.js index b423edc8..4cedfaa7 100644 --- a/module/tmr-utility.js +++ b/module/tmr-utility.js @@ -1,6 +1,7 @@ import { DeDraconique } from "./de-draconique.js"; import { TMRRencontres } from "./tmr-rencontres.js"; import { Grammar } from "./grammar.js"; +import { Misc } from "./misc.js"; /* -------------------------------------------- */ const TMRMapping = { @@ -210,20 +211,20 @@ const TMRMapping = { } 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" + cite: {name:"cité"}, + sanctuaire: {name:"sanctuaire"}, + plaines: {name:"plaines"}, + pont: {name:"pont"}, + collines: {name:"collines"}, + foret: {name:"forêt"}, + monts: {name:"monts"}, + desert: {name:"désert"}, + fleuve: {name:"fleuve"}, + lac: {name:"lac"}, + marais: {name:"marais"}, + gouffre: {name:"gouffre"}, + necropole: {name:"nécropole"}, + desolation: {name:"désolation"} } /* -------------------------------------------- */ @@ -257,14 +258,17 @@ export class TMRUtility { 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 ) + static convertToTMRCoord( pos ) { - y = y + 1 - let letterX = String.fromCharCode(65+x); - return letterX+y + let letterX = String.fromCharCode(65+ (pos.x)); + return letterX + (pos.y +1) } /* -------------------------------------------- */ @@ -280,7 +284,7 @@ export class TMRUtility { } /* -------------------------------------------- */ - static convertToCellCoord( coordTMR ) + static convertToCellPos( coordTMR ) { let x = coordTMR.charCodeAt(0) - 65; let y = coordTMR.substr(1) - 1; @@ -328,13 +332,13 @@ export class TMRUtility { /* -------------------------------------------- */ static deplaceTMRSelonPattern( coord, direction, nTime ) { for (let i=0; i it.coord); } - /* -------------------------------------------- */ - 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 getTMRAleatoire(terrain = undefined) { + let list = terrain ? TMRUtility.getListTMR(terrain) : Object.values(TMRMapping); + let index = new Roll("1d" + list.length).evaluate().total - 1; + return list[index]; } /* -------------------------------------------- */ @@ -432,22 +413,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 ); + 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(x, y) ); // Inside the area + caseList.push( this.convertToTMRCoord(currentPos) ); // Inside the area } } } 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":[]}