Compare commits

..

149 Commits

Author SHA1 Message Date
4f80c719c2 Fix services/boutique 2022-12-23 14:26:23 +01:00
7d8b5c9549 Merge pull request '10.4.0: Pour Noël, je voudrais plein de cadeaux' (#598) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #598
2022-12-23 09:50:26 +01:00
Vincent Vandemeulebrouck
ec58317b35 Version 10.4.0 2022-12-23 02:18:43 +01:00
Vincent Vandemeulebrouck
7c70e944b1 Ajout des "boutiques"
Une boutique est un Item service permettant de définir l'inventaire
en vente, et de le vendre facilement.

Les boutiques peuvent être accédées par les joueurs (avec le lien)
pour y faire leurs courses.
2022-12-23 02:17:37 +01:00
Vincent Vandemeulebrouck
f397c82c6d Prepare sous-classes Item 2022-12-23 00:35:44 +01:00
Vincent Vandemeulebrouck
81e3ceb4dc Lien vers Items monde/compendium 2022-12-23 00:35:44 +01:00
Vincent Vandemeulebrouck
7bec249e8d Cleanup init & start
- classe SystemReveDeDragon pour l'init/start
- déplacement de la migration 1.5.34 dans les migrations
2022-12-23 00:25:11 +01:00
Vincent Vandemeulebrouck
70b30b545b Affichage consistant prix unitaire/total 2022-12-22 00:04:49 +01:00
Vincent Vandemeulebrouck
ed2eebf99d Renommage confirmation 2022-12-21 00:49:36 +01:00
Vincent Vandemeulebrouck
4ba2c384d7 Alignement de prix/quantité/enc
- alignement à droite
- affichage des prix avec 2 décimales
2022-12-21 00:48:32 +01:00
Vincent Vandemeulebrouck
7f27399f3c comptage de monde en async
Au cas où on n'a pas de connection internet (merci la coupure Orange)
2022-12-21 00:48:32 +01:00
Vincent Vandemeulebrouck
61389e117b Séparation inventaire/monnaie 2022-12-20 01:13:51 +01:00
Vincent Vandemeulebrouck
46cc245abf Fix edition minutes du calendrier 2022-12-20 01:13:51 +01:00
Vincent Vandemeulebrouck
a372531849 Cleanup: html TMR multiligne 2022-12-20 01:12:52 +01:00
Vincent Vandemeulebrouck
8a8323ac8d Cleanup: Suppression log 2022-12-20 01:12:52 +01:00
Vincent Vandemeulebrouck
8e6d4fbb89 Fix: la valeur de l'inventaire hors fortune
La valeur de l'inventaire ne tient plus compte de la fortune
2022-12-20 01:12:51 +01:00
Vincent Vandemeulebrouck
886307f24c Fix: affichage de la fortune avec arrondis
Affichage en sols + deniers
2022-12-20 01:12:51 +01:00
f40dbd5d7b Merge pull request '10.3.17 - petits fixes' (#597) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #597
2022-12-18 17:08:21 +01:00
Vincent Vandemeulebrouck
66da7d5eb4 Version 10.3.17 2022-12-17 20:08:11 +01:00
Vincent Vandemeulebrouck
b2d8c2439a Fix: affichage des descriptions
Pour les feuilles dérivées de RdDItemSheet, il faut appeler
super.getData() pour préparer les données à afficher dans le formulaire.
2022-12-17 20:08:11 +01:00
Vincent Vandemeulebrouck
ceb4095c31 Fix: escaping dans les messages de rencontres 2022-12-17 20:08:11 +01:00
Vincent Vandemeulebrouck
2af37cf98f Fix: l'ajout de queues fonctionne de nouveau 2022-12-17 20:08:11 +01:00
Vincent Vandemeulebrouck
fd156960a7 Fix: les rencontres persistantes disparaissent
Après un échec, il était impossible de se débarasser d'une rencontre
persistante. Maintenant, les rencontres persistantes vaincues sont
bien supprimées.
2022-12-17 20:08:03 +01:00
Vincent Vandemeulebrouck
80a904e533 Fix: Surencombrement toujours calculé
Sur de vieux personnages, le sur-encombrement stocké pouvait
être affiché (et incorrect).
2022-12-17 17:49:11 +01:00
Vincent Vandemeulebrouck
c9dc847440 Migration des monnaies par nom
Vu que dans les migrations précédentes, le "cout" avait une valeur
(pas undefined), les migrations ont échoué
2022-12-17 17:26:39 +01:00
4e382d405e Merge pull request 'Ils sont bons mes Maquereaux, elles sont bien mes macros' (#596) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #596
2022-12-17 11:33:44 +01:00
Vincent Vandemeulebrouck
6a12dc97f6 Version 10.3.16 2022-12-17 01:39:22 +01:00
Vincent Vandemeulebrouck
e0b6957bc6 Ajout de macros RdD 2022-12-17 01:37:54 +01:00
Vincent Vandemeulebrouck
944120b524 Fix commande /rdd sans compétence
On peut maintenant faire /rdd Vue -2
2022-12-17 00:55:13 +01:00
Vincent Vandemeulebrouck
bb6bf3387e Malus fatigue indiqué sur la fatigue 2022-12-17 00:55:13 +01:00
Vincent Vandemeulebrouck
467a4d53a4 Séparation des boutons Haut-rêve 2022-12-17 00:55:13 +01:00
Vincent Vandemeulebrouck
d5635b27fe Suppression du test 2022-12-15 22:40:23 +01:00
3a33f7c4fc Fix actor sheet 2022-12-15 10:41:19 +01:00
d2e77dc61c Merge pull request 'Version 10.3.14' (#595) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #595
2022-12-15 07:36:04 +01:00
Vincent Vandemeulebrouck
320bc471e3 Version 10.3.14
- Améliorations cosmétiques
- Affichage de la fortune
- Fix dissolution
- Fix des monnaies dans les compendiums
- Nettoyage des compendiums
2022-12-15 01:03:57 +01:00
Vincent Vandemeulebrouck
090241f0f5 Alignement des champs d'environement 2022-12-15 01:00:28 +01:00
Vincent Vandemeulebrouck
ddc37c6969 Ajustement champs description 2022-12-15 00:56:23 +01:00
Vincent Vandemeulebrouck
6af6e41bc9 Reprise des attributs secondaires 2022-12-15 00:56:23 +01:00
Vincent Vandemeulebrouck
0f7f609a2a Fix dissolution
La dissolution n'est que de 1 point
2022-12-15 00:56:23 +01:00
Vincent Vandemeulebrouck
a58f701ca6 Centrage seuil de rêve 2022-12-15 00:56:23 +01:00
Vincent Vandemeulebrouck
757b46080a Suppression compendiums inutilisés 2022-12-15 00:56:23 +01:00
Vincent Vandemeulebrouck
df44cd66c7 Nettoyage compendiums
- correction des monnaies des acteurs par défaut
- re-export pour garder les données systeme
- suppression des champs "competencecreature[0]" incorrects
- suppression de champs data non utilisés
2022-12-15 00:56:23 +01:00
Vincent Vandemeulebrouck
1040ec1be2 Auto reformat 2022-12-15 00:56:23 +01:00
Vincent Vandemeulebrouck
92643d1c46 Autocomplete Main directrice
Permet de choisir rapidement dans les valeurs proposées
2022-12-15 00:56:22 +01:00
Vincent Vandemeulebrouck
31c4aa32d9 Affichage de la fortune 2022-12-14 19:58:52 +01:00
f5431b58fb Merge pull request 'Non à la dévaluation' (#594) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #594
2022-12-13 22:28:42 +01:00
Vincent Vandemeulebrouck
bd32e1039a Mettre en valeur l'argent sans valeur 2022-12-13 22:27:36 +01:00
Vincent Vandemeulebrouck
6b8f0ed51e Version 10.3.13 2022-12-12 23:33:53 +01:00
Vincent Vandemeulebrouck
10681b3f61 DialogItemSplit height fit-content 2022-12-12 23:32:35 +01:00
Vincent Vandemeulebrouck
bbde3b73fe Gestion des monnaies de valeur 0
Ajout d'un message d'erreur quand on met la valeur d'une monnaie à 0.
Ajout d'une notification quand on détecte des monnaies de valeur 0

Pour les pièces en bois, les créer comme objets, si on ne veut pas de
messages d'avertissement.
2022-12-12 23:32:35 +01:00
57d52c1966 Inc release 2022-12-11 10:35:51 +01:00
e3a29cdab5 Merge pull request 'Fix taille du texte des boutons' (#593) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #593
2022-12-11 10:34:36 +01:00
Vincent Vandemeulebrouck
10e4f14eb2 Fix taille du texte des boutons 2022-12-11 02:10:39 +01:00
04273dfcf1 Inc release 2022-12-10 18:14:52 +01:00
8c5c01114e Merge pull request 'Corrections esthétiques' (#592) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #592
2022-12-10 18:13:44 +01:00
Vincent Vandemeulebrouck
19e6124330 Suppression scripts vides 2022-12-10 16:38:18 +01:00
Vincent Vandemeulebrouck
1c908b50cb Dialog repos 2022-12-10 16:38:18 +01:00
Vincent Vandemeulebrouck
969cedfc3d Fix espace avant boutons 2022-12-10 16:28:08 +01:00
Vincent Vandemeulebrouck
830e66749d Lien des label vers les champs 2022-12-10 16:09:55 +01:00
Vincent Vandemeulebrouck
df26e654ae Fix des tailles de polices 2022-12-10 16:09:35 +01:00
Vincent Vandemeulebrouck
153bfe2e75 Simplification hbs pour la vue détaillée 2022-12-10 16:07:33 +01:00
Vincent Vandemeulebrouck
f6d42875ae Stress et archétype
Déplacement du stress et de l'archétype avant les compétences

Les lignes d'archétypes totalement réparties disparaissent
2022-12-10 15:49:09 +01:00
Vincent Vandemeulebrouck
450cb8e899 Largeur des compétences
Ajustement de la largeur des colonnes de compétenes en vue
simplifiée

Déplacement de l'en-tête dans la première ligne de la liste (avec les
boutons en vue détaillée)
2022-12-10 15:44:08 +01:00
0202938910 Ajout faune 2022-12-09 22:50:23 +01:00
512a056e59 Merge pull request 'Poissons, coquillages, crustacés' (#591) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #591
2022-12-09 22:49:29 +01:00
Vincent Vandemeulebrouck
214377c66d Poissons, coquillages, crustacés
Ils sont frais, mes poissons!
2022-12-09 22:36:17 +01:00
752e534350 Ajout faune 2022-12-09 21:50:12 +01:00
c85a544cc9 Ajout faune + fix sur suppression milieux 2022-12-09 12:01:44 +01:00
3a90c693d9 Release 2022-12-09 10:39:21 +01:00
c04b179176 Merge pull request 'Permettre d'avoir plusieurs fenêtres' (#590) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #590
2022-12-09 10:36:48 +01:00
Vincent Vandemeulebrouck
63770790b9 Fix multi-dialogs
Arrêter d'utiliser le jQuery $(selector) qui cause des effets de bord si
plusieurs élements de la page (ie: foundry) correspondent
au selector.

Stocker le html dans les Sheet/Dialogs lors de l'appel
activateListeners  afin de pouvoir s'y référer ensuite.

Utiliser this.html.find pour chercher dans le html de la fenêtre
courante.

Eliminer les référence par id html car l'id est unique (donc ne marche
pas en multi-fenêtres)
2022-12-09 02:07:59 +01:00
Vincent Vandemeulebrouck
aefc7a434b Fix: lien vers rencontre du compendium 2022-12-09 02:07:59 +01:00
Vincent Vandemeulebrouck
f02959adee Cleanup
Construction du message de jet de constitution par template hbs
2022-12-09 02:07:59 +01:00
Vincent Vandemeulebrouck
e652027b02 Cleanup accorder entité
Méthode pour accorder une entité en double (dont une version sans xp,
et message mal formaté)
2022-12-09 02:07:45 +01:00
Vincent Vandemeulebrouck
2122a54db7 Cleanup roll windows
- permettre plusieurs fenêtres de jets en même temps en éliminant les
  id dans le html et les jquery sur id pour éviter les interactions
- génération de la table par handlebars
2022-12-06 01:30:31 +01:00
f027e3318b Merge pull request 'Ragoût de Klampin' (#588) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #588
2022-12-05 16:50:33 +01:00
Vincent Vandemeulebrouck
31b4d1cfcc Version 10.3.6 2022-12-05 16:39:24 +01:00
Vincent Vandemeulebrouck
5056c35038 Faune et flore comestibles
- permettre de cuisiner les ingrédients (faune & flore)
- permettre de manger des ingrédients "crus"
2022-12-05 16:38:26 +01:00
Vincent Vandemeulebrouck
7b58407634 Cleanup 2022-12-05 16:36:27 +01:00
Vincent Vandemeulebrouck
7efa7be1c0 L'art ne s'encombre de rien
Ne pas appliquer le surencombrement (ou l'encombrement) aux oeuvres
d'art: on considère que pour faire de l'art, on pose son sac.
2022-12-05 16:36:27 +01:00
Vincent Vandemeulebrouck
717bb6fc6e Fix ouverture conteneur 2022-12-05 16:36:27 +01:00
51273bcc3e Merge pull request 'Gestion de la Faune' (#587) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #587
2022-12-03 23:16:36 +01:00
Vincent Vandemeulebrouck
b8f3a9af27 Version 10.3.5 2022-12-03 22:31:56 +01:00
Vincent Vandemeulebrouck
ab704c46d2 Ajout de l'Item "faune" pour tables environnement 2022-12-03 22:31:42 +01:00
Vincent Vandemeulebrouck
db8fd6dbf8 Meilleur post to tchat 2022-12-03 22:27:21 +01:00
Vincent Vandemeulebrouck
d998a4cb08 Amélioration Classes ItemSheet séparées
Meilleur support des feuilles ItemSheet séparés
Séparation de la feuille Conteneurs

Mise en commun de la logique drag&drop
2022-12-03 22:27:20 +01:00
Vincent Vandemeulebrouck
b1e27a9597 On ne peut pas tout donner
Limitation des types d'objets pouvant être donnés à différents acteurs
2022-12-03 18:31:14 +01:00
eaac9564b4 Merge pull request 'La recherche par milieu fonctionnelle' (#586) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #586
2022-12-03 10:05:49 +01:00
Vincent Vandemeulebrouck
0826c7e9e3 Version 10.3.4 2022-12-03 01:26:39 +01:00
Vincent Vandemeulebrouck
bdd3802e72 Amélioration de la recherche dans un milieu
- gestion correcte de la case
- recherche insensitive
- correction de la liste des milieux à ajouter dans la feuille
- si aucun milieu ne correspond à la recherche, affiche la
  liste des milieux disponibles
2022-12-03 01:25:24 +01:00
Vincent Vandemeulebrouck
b07cea40e2 Fallback sur compendium system
quand le compendium configuré n'existe plus, fallback sur le
compendium du système
2022-12-03 01:25:23 +01:00
Vincent Vandemeulebrouck
bb7f4c42ad Feuilles Ingrédient&Herbe extends RdDItemSheet
Pour bénéficier de certains comportements (description...)
2022-12-03 01:25:23 +01:00
Vincent Vandemeulebrouck
ac15a022df Fréquences dans les milieux standard
Saisie dans le compendiums de fréquences pour la liste de milieux
par défaut
2022-12-03 01:25:23 +01:00
a43c725b06 Merge pull request '10.3.3' (#585) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #585
2022-12-02 23:51:15 +01:00
Vincent Vandemeulebrouck
1276c64835 Version 10.3.3 2022-12-02 21:22:43 +01:00
Vincent Vandemeulebrouck
4b4d778d9c Entrée ajoute le milieu aux fréquences 2022-12-02 21:22:11 +01:00
Vincent Vandemeulebrouck
86f9c37b30 Liste des milieux par défaut 2022-12-02 21:22:11 +01:00
Vincent Vandemeulebrouck
ac77c6da9e Fix calcul valeur équipement 2022-12-02 21:22:11 +01:00
344540ea8e Merge pull request 'Fix initiative' (#584) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #584
2022-12-01 08:05:14 +01:00
Vincent Vandemeulebrouck
8a5cf3cb09 Version 10.3.2 2022-12-01 01:25:06 +01:00
Vincent Vandemeulebrouck
3a29570bae Fix message d'expérience invisibles
Les messages d'expérience sur mêlée/tir/lancer (à répartir)
n'étaient plus visibles
2022-12-01 01:22:25 +01:00
Vincent Vandemeulebrouck
02c48f4796 Fix initiative 2022-12-01 00:28:23 +01:00
ee01878fae Fixes suite à dernières modifs 2022-11-30 16:41:39 +01:00
2e1005e909 Merge pull request 'Fixes mineurs' (#583) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #583
2022-11-30 16:40:35 +01:00
Vincent Vandemeulebrouck
98c016696d Correction de l'ajout de milieux parfois KO
Pas sûr du pourquoi, il semble qu'il y a un souci jQuery
(avec deux fenêtres?)
2022-11-30 16:03:56 +01:00
Vincent Vandemeulebrouck
e67ac96e93 Fix: /roll
Regression sur /roll causée par méthode async:
return Promise(false)=>true au lieu de false...
2022-11-30 14:28:11 +01:00
Vincent Vandemeulebrouck
979a48e4d9 Amélioration recherche dans un milieu
Si la recherche est sur un milieu exact, seul ce millieu est considéré.
ie: chercher en "Forêts" ne cherchera pas en "Forêts humides".

Le recherche en "for" cherchera dans tous les milieux contenant "for".
Un message d'avertissement est affiché, et la description de la table
contient la liste des milieux correspondants.

Si plusieurs milieux cherchés ont une fréquence pour une ressource,
la fréquence la plus élevée est utilisée.
2022-11-30 14:24:09 +01:00
Vincent Vandemeulebrouck
faff6e54ef Fix arborescence de conteneur 2022-11-30 14:24:08 +01:00
d493e99bcb Merge pull request 'Tables de compendiums et feuilles de personnages' (#582) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #582
2022-11-30 09:37:49 +01:00
Vincent Vandemeulebrouck
92ae0b7431 Correction aide /tirer milieu 2022-11-30 02:35:12 +01:00
Vincent Vandemeulebrouck
13135ff2ca Version 10.3.0 2022-11-30 02:16:59 +01:00
Vincent Vandemeulebrouck
453e7da848 Création du compendium Faune, Flore, Minéraux
- les tables d'environnement se basent sur ce seul compendium
- les tables de compendiums peuvent chercher plusieurs types d'items
- déplacement de la botanique
- déplacement des sels alchimiques depuis l'équipement
- modification de l'équipement de départ
- modification des acteurs (lien vers compendium de l'item source)
2022-11-30 02:12:31 +01:00
Vincent Vandemeulebrouck
b7a0e5d034 Fréquences par milieu pour l'environnement
Les herbes et les ingrédients peuvent être cherchées/tirées
2022-11-30 02:06:46 +01:00
Vincent Vandemeulebrouck
b7a8b0c08d Standardisation inventaire et prix
Les objets d'inventaire ont maintenant tous:
coût, encombrement, qualité, quantité

Le coût est toujours exprimé en sols, y compris pour les monnaies.
Les paiements et achat-ventes sont fait en sols.
2022-11-29 11:37:49 +01:00
Vincent Vandemeulebrouck
7557d33c73 Feuille de véhicule avec compteurs 2022-11-29 11:37:49 +01:00
Vincent Vandemeulebrouck
e35f77b5a8 Cleanup
- Partage méthode pour label des types
- Methode joining pour concaténation
- suppression template obsolete
- Déplacement de singleton rencontre dans game.system.rdd
- init des commandes lazy
2022-11-29 11:37:11 +01:00
Vincent Vandemeulebrouck
dd4484c17b En-tête de feuille de personnage
Affichage des portraits plus grands
Les boutons sont sur la ligne du nom du personnage
Les états sont affichés sur une colonne
2022-11-29 00:04:50 +01:00
Vincent Vandemeulebrouck
4bd2c1c2b4 Notion d'équipement/inventaire 2022-11-29 00:04:38 +01:00
Vincent Vandemeulebrouck
42c4fe0b29 Standardisation des descriptions
Utilisation des templates sur les items pour la description
2022-11-28 21:02:32 +01:00
Vincent Vandemeulebrouck
39c6478422 Affichage des images de tarot 2022-11-28 21:02:32 +01:00
Vincent Vandemeulebrouck
c06491eb2f Ne pas tronquer les images
Corrections des tailles d'images pour éviter de tronquer
2022-11-28 21:02:32 +01:00
Vincent Vandemeulebrouck
e869d15b24 Correction mise à jour état général 2022-11-28 21:02:32 +01:00
Vincent Vandemeulebrouck
7045b6d8e1 Amélioration du message de confirmation 2022-11-28 21:02:32 +01:00
431d3199db Merge pull request 'v10.2.10: Gestion des tables depuis les compendiums' (#581) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #581
2022-11-26 18:42:10 +01:00
Vincent Vandemeulebrouck
5555705912 10.2.10 2022-11-26 18:12:44 +01:00
Vincent Vandemeulebrouck
4a51f698ab Fix regressions liste dans conteneurs
Les lignes étaient affichées de manière étrange et peu lisible
2022-11-26 18:12:31 +01:00
Vincent Vandemeulebrouck
029bece877 Gestion des désir lancinant/idée fixe
Ajout d'un flag pour les identifier.
2022-11-26 16:58:53 +01:00
Vincent Vandemeulebrouck
31eabbce23 Fix fréquence Mauvais reflet d'ancien rêve 2022-11-26 16:58:53 +01:00
Vincent Vandemeulebrouck
7200ff529f Cleanup 2022-11-26 16:58:53 +01:00
Vincent Vandemeulebrouck
0dacbefd6b Tirer dans les compendiums selon les fréquences 2022-11-26 16:58:53 +01:00
970be67537 Increase release, VincentVK fixes 2022-11-25 07:35:19 +01:00
53aa9cd643 Merge pull request 'Corrections des jets de dés' (#580) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #580
2022-11-25 07:33:53 +01:00
Vincent Vandemeulebrouck
c435bfa343 Chronologie et année
Fix jour dans chronologie
Permettre de saisir l'année
2022-11-25 03:17:27 +01:00
Vincent Vandemeulebrouck
8667d77169 Ajout de champs pour les tables-compendium
Le champ "frequence" sert à rêgler le nombre d'occurences d'une entrée
du compendium. Le total des fréquences donnera le dé à lancer pour
tirer dans la table. Il servira pour réguler l'apparition des
queues/souffles/... d'un compendium sans avoir besoin de déclarer une
RollTable.

Le champ "hautrevant" permet d'indiquer les queues/souffles/...
réservés aux haut-rêvants.
2022-11-25 03:17:27 +01:00
Vincent Vandemeulebrouck
5e7fcf3c9b fit-content pour toutes les fenêtres roll
C'est le comportement par défaut, donc enlever les surcharges
Corrections pour les fenêtres de combat
2022-11-25 03:17:27 +01:00
Vincent Vandemeulebrouck
e78ae3b292 Chargement depuis les compendium sélectionnés
Fix, les compendiums systèmes n'étaient pas utilisés pour les herbes
et les compétences
2022-11-25 03:17:27 +01:00
Vincent Vandemeulebrouck
97ee5bc331 Amélioration possession
- Créer la possession lors de la première attaque
- Le personnage ciblé par la possession est affiché
2022-11-25 03:17:27 +01:00
Vincent Vandemeulebrouck
c3c0bbc922 Fix jets de caracs dérivées
Appel à la chance, jets de rêve actuel: pas de liste de compétences
2022-11-25 03:17:26 +01:00
Vincent Vandemeulebrouck
9992b64cae Corrections sur les ajustements
- le malus de sur-encombrement est correctement calculé (dans la
  zone d'état)
- par défaut, le sur-encombrement est appliqué
- le sur-encombrement est affiché sur les actions physiques
- l'encombrement s'applique à agilité/dérobée, avec natation/acrobatie
  (par défaut)
- le moral est géré dans le noeud 'use' du rollData
- le moral est associé aux actions physiques
2022-11-25 03:17:26 +01:00
Vincent Vandemeulebrouck
7698147e97 Affichage de la cible dans la fenêtre d'attaque 2022-11-23 22:42:18 +01:00
81aaf9e8d7 Merge pull request 'Choisir parmi plusieurs cibles' (#579) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #579
2022-11-23 08:24:17 +01:00
Vincent Vandemeulebrouck
8e1b33d964 Version 10.2.8 2022-11-23 00:14:55 +01:00
Vincent Vandemeulebrouck
eca61fff57 Fix: hauteur des onglets Foundry
Le texte des onglets de configuration Foundry (vision des tokens,
lumières par exemple) sont sur plusieurs lignes.

La réduction de la hauteur des lignes éviter que le titre de l'onglet
soit par dessus le contenu.

Fixe aussi l'onglêt "haut-rêve" si la fenêtre d'acteur est de largeur
réduite.
2022-11-23 00:13:33 +01:00
Vincent Vandemeulebrouck
acc5ddac08 Simplifier la sélection
Lorsque plusieurs tokens sont ciblés, laisser le joueur choisir parmi
ceux-là
2022-11-23 00:13:33 +01:00
06024a0007 Merg/Increase release 2022-11-22 07:39:31 +01:00
da9158e718 Merge pull request 'Autoriser le combat sans cible' (#578) from VincentVk/foundryvtt-reve-de-dragon:v10 into v10
Reviewed-on: #578
2022-11-22 07:38:11 +01:00
Vincent Vandemeulebrouck
f57f03547a Autoriser le combat sans cible 2022-11-22 02:15:51 +01:00
Vincent Vandemeulebrouck
5424763ad6 Cleanup 2022-11-22 02:15:51 +01:00
3543ce60cb Fix armes naturelles/corps à corps 2022-11-20 16:08:48 +01:00
245 changed files with 6556 additions and 4988 deletions

BIN
icons/faune/Escargot.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

BIN
icons/faune/andurak.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
icons/faune/barbon.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
icons/faune/brocart.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
icons/faune/cancre.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.6 KiB

BIN
icons/faune/cancrelas.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

BIN
icons/faune/cerf.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.0 KiB

BIN
icons/faune/chamois.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
icons/faune/chevre.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

BIN
icons/faune/colimace.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
icons/faune/coquille.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

BIN
icons/faune/crabe.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

BIN
icons/faune/fretin.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
icons/faune/lapin.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
icons/faune/oie.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

BIN
icons/faune/oiseau.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
icons/faune/ours.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
icons/faune/padongre.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

BIN
icons/faune/poisson.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

BIN
icons/faune/rongeur.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.8 KiB

BIN
icons/faune/sanglier.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
icons/faune/saumon.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 KiB

BIN
icons/faune/singe-vert.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
icons/faune/soldieze.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

BIN
icons/faune/ver.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
icons/faune/wolf-head.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
icons/items/services.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@@ -20,12 +20,14 @@
"TypeMonnaie": "Monnaie", "TypeMonnaie": "Monnaie",
"TypeHerbe": "Herbe ou plante", "TypeHerbe": "Herbe ou plante",
"TypeIngredient": "Ingrédient", "TypeIngredient": "Ingrédient",
"TypeFaune": "Faune",
"TypeLivre": "Livre", "TypeLivre": "Livre",
"TypePotion": "Potion", "TypePotion": "Potion",
"TypeArme": "Arme", "TypeArme": "Arme",
"TypeArmure": "Armure", "TypeArmure": "Armure",
"TypeConteneur": "Conteneur", "TypeConteneur": "Conteneur",
"TypeNourritureboisson": "Nourriture & boisson", "TypeNourritureboisson": "Nourriture & boisson",
"TypeService": "Services/Boutique",
"TypeChant": "Chant", "TypeChant": "Chant",
"TypeDanse": "Danse", "TypeDanse": "Danse",
"TypeMusique": "Musique", "TypeMusique": "Musique",

View File

@@ -27,15 +27,15 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
if (!this.options.editable) return; if (!this.options.editable) return;
// On competence change // On competence change
html.find('.creature-carac').change(async event => { this.html.find('.creature-carac').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCreatureCompetence(compName, "carac_value", parseInt(event.target.value)); this.actor.updateCreatureCompetence(compName, "carac_value", parseInt(event.target.value));
}); });
html.find('.creature-niveau').change(async event => { this.html.find('.creature-niveau').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCreatureCompetence(compName, "niveau", parseInt(event.target.value)); this.actor.updateCreatureCompetence(compName, "niveau", parseInt(event.target.value));
}); });
html.find('.creature-dommages').change(async event => { this.html.find('.creature-dommages').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value)); this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value));
}); });

View File

@@ -23,15 +23,15 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
if (!this.options.editable) return; if (!this.options.editable) return;
// On competence change // On competence change
html.find('.creature-carac').change(async event => { this.html.find('.creature-carac').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCreatureCompetence( compName, "carac_value", parseInt(event.target.value) ); this.actor.updateCreatureCompetence( compName, "carac_value", parseInt(event.target.value) );
} ); } );
html.find('.creature-niveau').change(async event => { this.html.find('.creature-niveau').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCreatureCompetence( compName, "niveau", parseInt(event.target.value) ); this.actor.updateCreatureCompetence( compName, "niveau", parseInt(event.target.value) );
} ); } );
html.find('.creature-dommages').change(async event => { this.html.find('.creature-dommages').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCreatureCompetence( compName, "dommages", parseInt(event.target.value) ); this.actor.updateCreatureCompetence( compName, "dommages", parseInt(event.target.value) );
} ); } );

View File

@@ -8,9 +8,10 @@ import { RdDCombatManager } from "./rdd-combat.js";
import { RdDCarac } from "./rdd-carac.js"; import { RdDCarac } from "./rdd-carac.js";
import { DialogSplitItem } from "./dialog-split-item.js"; import { DialogSplitItem } from "./dialog-split-item.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js"; import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { DialogRepos } from "./dialog-repos.js";
import { RdDSheetUtility } from "./rdd-sheet-utility.js"; import { RdDSheetUtility } from "./rdd-sheet-utility.js";
import { STATUSES } from "./settings/status-effects.js"; import { STATUSES } from "./settings/status-effects.js";
import { Monnaie } from "./item-monnaie.js";
import { MAINS_DIRECTRICES } from "./actor.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
/** /**
@@ -25,7 +26,7 @@ export class RdDActorSheet extends ActorSheet {
return mergeObject(super.defaultOptions, { return mergeObject(super.defaultOptions, {
classes: ["rdd", "sheet", "actor"], classes: ["rdd", "sheet", "actor"],
template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html",
width: 640, width: 550,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }], tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }], dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
showCompNiveauBase: false, showCompNiveauBase: false,
@@ -36,6 +37,7 @@ export class RdDActorSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
this.timerRecherche = undefined; this.timerRecherche = undefined;
this.actor.computeEtatGeneral();
let formData = { let formData = {
title: this.title, title: this.title,
@@ -55,7 +57,9 @@ export class RdDActorSheet extends ActorSheet {
notes: await TextEditor.enrichHTML(this.object.system.notes, { async: true }), notes: await TextEditor.enrichHTML(this.object.system.notes, { async: true }),
notesmj: await TextEditor.enrichHTML(this.object.system.notesmj, { async: true }), notesmj: await TextEditor.enrichHTML(this.object.system.notesmj, { async: true }),
calc: { calc: {
fortune: Monnaie.getFortuneSolsDeniers(this.actor),
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(), encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
surenc: this.actor.computeMalusSurEncombrement(),
prixTotalEquipement: this.actor.computePrixTotalEquipement(), prixTotalEquipement: this.actor.computePrixTotalEquipement(),
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr, surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures), resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
@@ -70,6 +74,7 @@ export class RdDActorSheet extends ActorSheet {
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs); formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
if (formData.type == 'personnage') { if (formData.type == 'personnage') {
formData.options.mainsDirectrices = MAINS_DIRECTRICES;
formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie) formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie)
formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences); formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences);
formData.calc.competenceXPTotal = RdDItemCompetence.computeTotalXP(formData.competences); formData.calc.competenceXPTotal = RdDItemCompetence.computeTotalXP(formData.competences);
@@ -117,76 +122,26 @@ export class RdDActorSheet extends ActorSheet {
return formData; return formData;
} }
isCompetenceAffichable(competence) {
return !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(competence);
}
/* -------------------------------------------- */
async _onDropActor(event, dragData) {
const dropActor = fromUuidSync(dragData.uuid);
this.actor.addSubActeur(dropActor);
super._onDropActor(event, dragData);
}
/* -------------------------------------------- */
async _onDropItem(event, dragData) {
const destItemId = $(event.target)?.closest('.item').attr('data-item-id')
const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor.id, dragData, this.objetVersConteneur)
const callSuper = await this.actor.processDropItem(dropParams)
if (callSuper) {
await super._onDropItem(event, dragData)
}
}
/* -------------------------------------------- */
async createItem(name, type) {
await this.actor.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
}
/* -------------------------------------------- */
async createEmptyTache() {
await this.createItem('Nouvelle tache', 'tache');
}
/* -------------------------------------------- */ /** @override */ /* -------------------------------------------- */ /** @override */
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = html;
HtmlUtility._showControlWhen($(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue")); HtmlUtility._showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
// Everything below here is only needed if the sheet is editable // Everything below here is only needed if the sheet is editable
if (!this.options.editable) return; if (!this.options.editable) return;
html.find('.item-split').click(async event => { this.html.find('.item-split').click(async event => {
const item = RdDSheetUtility.getItem(event, this.actor); const item = RdDSheetUtility.getItem(event, this.actor);
RdDSheetUtility.splitItem(item, this.actor); RdDSheetUtility.splitItem(item, this.actor);
}); });
html.find('.item-edit').click(async event => { this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true))
const item = RdDSheetUtility.getItem(event, this.actor) this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, RdDSheetUtility.getItem(event, this.actor)));
item.sheet.render(true) this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente());
}) this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItem());
html.find('.display-label a').click(async event => { this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor));
const item = RdDSheetUtility.getItem(event, this.actor); this.html.find('.subacteur-delete').click(async event => {
item.sheet.render(true);
});
html.find('.item-delete').click(async event => {
const li = RdDSheetUtility.getEventElement(event);
const item = this.actor.getObjet(li.data("item-id"));
RdDUtility.confirmerSuppressionItem(this, item, li);
});
html.find('.item-vendre').click(async event => {
const item = RdDSheetUtility.getItem(event, this.actor);
item?.proposerVente();
});
html.find('.item-montrer').click(async event => {
const item = RdDSheetUtility.getItem(event, this.actor);
item?.postItem();
});
html.find('.item-action').click(async event => {
const item = RdDSheetUtility.getItem(event, this.actor)
this.actor.actionItem(item);
});
html.find('.subacteur-delete').click(async event => {
const li = RdDSheetUtility.getEventElement(event); const li = RdDSheetUtility.getEventElement(event);
const actorId = li.data("actor-id"); const actorId = li.data("actor-id");
if (actorId) { if (actorId) {
@@ -194,54 +149,54 @@ export class RdDActorSheet extends ActorSheet {
RdDUtility.confirmerSuppressionSubacteur(this, subActor, li); RdDUtility.confirmerSuppressionSubacteur(this, subActor, li);
} }
}); });
html.find('.experiencelog-delete').click(async event => { this.html.find('.experiencelog-delete').click(async event => {
const li = $(event.currentTarget)?.parents(".experiencelog"); const li = this.html.find(event.currentTarget)?.parents(".experiencelog");
const key = Number(li.data("key") ?? -1); const key = Number(li.data("key") ?? -1);
await this.actor.deleteExperienceLog(key, 1); await this.actor.deleteExperienceLog(key, 1);
}); });
html.find('.experiencelog-delete-previous').click(async event => { this.html.find('.experiencelog-delete-previous').click(async event => {
const li = $(event.currentTarget)?.parents(".experiencelog"); const li = this.html.find(event.currentTarget)?.parents(".experiencelog");
const key = Number(li.data("key") ?? -1); const key = Number(li.data("key") ?? -1);
await this.actor.deleteExperienceLog(0, key + 1); await this.actor.deleteExperienceLog(0, key + 1);
}); });
html.find('.encaisser-direct').click(async event => { this.html.find('.encaisser-direct').click(async event => {
this.actor.encaisser(); this.actor.encaisser();
}) })
html.find('.sheet-possession-attack').click(async event => { this.html.find('.sheet-possession-attack').click(async event => {
const poss = RdDSheetUtility.getItem(event, this.actor) const poss = RdDSheetUtility.getItem(event, this.actor)
this.actor.conjurerPossession(poss) this.actor.conjurerPossession(poss)
}) })
html.find('.remise-a-neuf').click(async event => { this.html.find('.remise-a-neuf').click(async event => {
if (game.user.isGM) { if (game.user.isGM) {
this.actor.remiseANeuf(); this.actor.remiseANeuf();
} }
}); });
html.find('.creer-tache').click(async event => { this.html.find('.creer-tache').click(async event => {
this.createEmptyTache(); this.createEmptyTache();
}); });
html.find('.creer-un-objet').click(async event => { this.html.find('.creer-un-objet').click(async event => {
RdDUtility.selectObjetType(this); RdDUtility.selectObjetType(this);
}); });
html.find('.creer-une-oeuvre').click(async event => { this.html.find('.creer-une-oeuvre').click(async event => {
RdDUtility.selectTypeOeuvre(this); RdDUtility.selectTypeOeuvre(this);
}); });
html.find('.nettoyer-conteneurs').click(async event => { this.html.find('.nettoyer-conteneurs').click(async event => {
this.actor.nettoyerConteneurs(); this.actor.nettoyerConteneurs();
}); });
// Blessure control // Blessure control
html.find('.blessure-control').click(async event => { this.html.find('.blessure-control').click(async event => {
const tr = $(event.currentTarget).parents(".item"); const tr = this.html.find(event.currentTarget).parents(".item");
let btype = tr.data("blessure-type"); let btype = tr.data("blessure-type");
let index = tr.data('blessure-index'); let index = tr.data('blessure-index');
let active = $(event.currentTarget).data('blessure-active'); let active = this.html.find(event.currentTarget).data('blessure-active');
//console.log(btype, index, active); //console.log(btype, index, active);
await this.actor.manageBlessureFromSheet(btype, index, active); await this.actor.manageBlessureFromSheet(btype, index, active);
}); });
// Blessure data // Blessure data
html.find('.blessure-soins').change(async event => { this.html.find('.blessure-soins').change(async event => {
const tr = $(event.currentTarget).parents(".item"); const tr = this.html.find(event.currentTarget).parents(".item");
let btype = tr.data('blessure-type'); let btype = tr.data('blessure-type');
let index = tr.data('blessure-index'); let index = tr.data('blessure-index');
let psoins = tr.find('.blessure-premiers_soins').val(); let psoins = tr.find('.blessure-premiers_soins').val();
@@ -255,57 +210,57 @@ export class RdDActorSheet extends ActorSheet {
}); });
// Equip Inventory Item // Equip Inventory Item
html.find('.item-equip').click(async event => { this.html.find('.item-equip').click(async event => {
this.actor.equiperObjet(RdDSheetUtility.getItemId(event)); this.actor.equiperObjet(RdDSheetUtility.getItemId(event));
}); });
// Roll Carac // Roll Carac
html.find('.carac-label a').click(async event => { this.html.find('.carac-label a').click(async event => {
let caracName = event.currentTarget.attributes.name.value; let caracName = event.currentTarget.attributes.name.value;
this.actor.rollCarac(caracName.toLowerCase()); this.actor.rollCarac(caracName.toLowerCase());
}); });
html.find('.chance-actuelle').click(async event => { this.html.find('.chance-actuelle').click(async event => {
this.actor.rollCarac('chance-actuelle'); this.actor.rollCarac('chance-actuelle');
}); });
html.find('.chance-appel').click(async event => { this.html.find('.chance-appel').click(async event => {
this.actor.rollAppelChance(); this.actor.rollAppelChance();
}); });
html.find('#jet-astrologie').click(async event => { this.html.find('[name="jet-astrologie"]').click(async event => {
this.actor.astrologieNombresAstraux(); this.actor.astrologieNombresAstraux();
}); });
// Roll Skill // Roll Skill
html.find('a.competence-label').click(async event => { this.html.find('a.competence-label').click(async event => {
this.actor.rollCompetence(RdDSheetUtility.getItemId(event)); this.actor.rollCompetence(RdDSheetUtility.getItemId(event));
}); });
html.find('.tache-label a').click(async event => { this.html.find('.tache-label a').click(async event => {
this.actor.rollTache(RdDSheetUtility.getItemId(event)); this.actor.rollTache(RdDSheetUtility.getItemId(event));
}); });
html.find('.meditation-label a').click(async event => { this.html.find('.meditation-label a').click(async event => {
this.actor.rollMeditation(RdDSheetUtility.getItemId(event)); this.actor.rollMeditation(RdDSheetUtility.getItemId(event));
}); });
html.find('.chant-label a').click(async event => { this.html.find('.chant-label a').click(async event => {
this.actor.rollChant(RdDSheetUtility.getItemId(event)); this.actor.rollChant(RdDSheetUtility.getItemId(event));
}); });
html.find('.danse-label a').click(async event => { this.html.find('.danse-label a').click(async event => {
this.actor.rollDanse(RdDSheetUtility.getItemId(event)); this.actor.rollDanse(RdDSheetUtility.getItemId(event));
}); });
html.find('.musique-label a').click(async event => { this.html.find('.musique-label a').click(async event => {
this.actor.rollMusique(RdDSheetUtility.getItemId(event)); this.actor.rollMusique(RdDSheetUtility.getItemId(event));
}); });
html.find('.oeuvre-label a').click(async event => { this.html.find('.oeuvre-label a').click(async event => {
this.actor.rollOeuvre(RdDSheetUtility.getItemId(event)); this.actor.rollOeuvre(RdDSheetUtility.getItemId(event));
}); });
html.find('.jeu-label a').click(async event => { this.html.find('.jeu-label a').click(async event => {
this.actor.rollJeu(RdDSheetUtility.getItemId(event)); this.actor.rollJeu(RdDSheetUtility.getItemId(event));
}); });
html.find('.recettecuisine-label a').click(async event => { this.html.find('.recettecuisine-label a').click(async event => {
this.actor.rollRecetteCuisine(RdDSheetUtility.getItemId(event)); this.actor.rollRecetteCuisine(RdDSheetUtility.getItemId(event));
}); });
html.find('.subacteur-label a').click(async event => { this.html.find('.subacteur-label a').click(async event => {
let actorId = RdDSheetUtility.getEventItemData(event, 'actor-id'); let actorId = RdDSheetUtility.getEventItemData(event, 'actor-id');
let actor = game.actors.get(actorId); let actor = game.actors.get(actorId);
if (actor) { if (actor) {
@@ -314,25 +269,25 @@ export class RdDActorSheet extends ActorSheet {
}); });
// Boutons spéciaux MJs // Boutons spéciaux MJs
html.find('.forcer-tmr-aleatoire').click(async event => { this.html.find('.forcer-tmr-aleatoire').click(async event => {
this.actor.reinsertionAleatoire("Action MJ"); this.actor.reinsertionAleatoire("Action MJ");
}); });
html.find('.afficher-tmr').click(async event => { this.html.find('.afficher-tmr').click(async event => {
this.actor.changeTMRVisible(); this.actor.changeTMRVisible();
}); });
// Points de reve actuel // Points de reve actuel
html.find('.ptreve-actuel a').click(async event => { this.html.find('.ptreve-actuel a').click(async event => {
this.actor.rollCarac('reve-actuel'); this.actor.rollCarac('reve-actuel');
}); });
// Roll Weapon1 // Roll Weapon1
html.find('.arme-label a').click(async event => { this.html.find('.arme-label a').click(async event => {
let arme = this._getEventArmeCombat(event); let arme = this._getEventArmeCombat(event);
this.actor.rollArme(duplicate(arme)); this.actor.rollArme(duplicate(arme));
}); });
// Initiative pour l'arme // Initiative pour l'arme
html.find('.arme-initiative a').click(async event => { this.html.find('.arme-initiative a').click(async event => {
let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id); let combatant = game.combat.combatants.find(c => c.actor.id == this.actor.id);
if (combatant) { if (combatant) {
let action = this._getEventArmeCombat(event); let action = this._getEventArmeCombat(event);
@@ -342,88 +297,88 @@ export class RdDActorSheet extends ActorSheet {
} }
}); });
// Display TMR, visualisation // Display TMR, visualisation
html.find('.visu-tmr').click(async event => { this.html.find('.visu-tmr').click(async event => {
this.actor.displayTMR("visu"); this.actor.displayTMR("visu");
}); });
// Display TMR, normal // Display TMR, normal
html.find('.monte-tmr').click(async event => { this.html.find('.monte-tmr').click(async event => {
this.actor.displayTMR("normal"); this.actor.displayTMR("normal");
}); });
// Display TMR, fast // Display TMR, fast
html.find('.monte-tmr-rapide').click(async event => { this.html.find('.monte-tmr-rapide').click(async event => {
this.actor.displayTMR("rapide"); this.actor.displayTMR("rapide");
}); });
html.find('.repos').click(async event => { this.html.find('.repos').click(async event => {
await DialogRepos.create(this.actor); await this.actor.repos();
}); });
html.find('.delete-active-effect').click(async event => { this.html.find('.delete-active-effect').click(async event => {
if (game.user.isGM) { if (game.user.isGM) {
let effect = $(event.currentTarget).parents(".active-effect").data('effect'); let effect = this.html.find(event.currentTarget).parents(".active-effect").data('effect');
this.actor.removeEffect(effect); this.actor.removeEffect(effect);
} }
}); });
html.find('.enlever-tous-effets').click(async event => { this.html.find('.enlever-tous-effets').click(async event => {
if (game.user.isGM) { if (game.user.isGM) {
await this.actor.removeEffects(); await this.actor.removeEffects();
} }
}); });
html.find('.conteneur-name a').click(async event => { this.html.find('.conteneur-name a').click(async event => {
RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event)); RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event));
this.render(true); this.render(true);
}); });
html.find('.carac-xp-augmenter').click(async event => { this.html.find('.carac-xp-augmenter').click(async event => {
let caracName = event.currentTarget.name.replace("augmenter.", ""); let caracName = event.currentTarget.name.replace("augmenter.", "");
this.actor.updateCaracXPAuto(caracName); this.actor.updateCaracXPAuto(caracName);
}); });
html.find('.competence-xp-augmenter').click(async event => { this.html.find('.competence-xp-augmenter').click(async event => {
this.actor.updateCompetenceXPAuto(RdDSheetUtility.getItemId(event)); this.actor.updateCompetenceXPAuto(RdDSheetUtility.getItemId(event));
}); });
html.find('.competence-stress-augmenter').click(async event => { this.html.find('.competence-stress-augmenter').click(async event => {
this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event)); this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event));
}); });
if (this.options.vueDetaillee) { if (this.options.vueDetaillee) {
// On carac change // On carac change
html.find('.carac-value').change(async event => { this.html.find('.carac-value').change(async event => {
let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", ""); let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", "");
this.actor.updateCarac(caracName, parseInt(event.target.value)); this.actor.updateCarac(caracName, parseInt(event.target.value));
}); });
html.find('input.carac-xp').change(async event => { this.html.find('input.carac-xp').change(async event => {
let caracName = event.currentTarget.name.replace(".xp", "").replace("system.carac.", ""); let caracName = event.currentTarget.name.replace(".xp", "").replace("system.carac.", "");
this.actor.updateCaracXP(caracName, parseInt(event.target.value)); this.actor.updateCaracXP(caracName, parseInt(event.target.value));
}); });
// On competence change // On competence change
html.find('.competence-value').change(async event => { this.html.find('.competence-value').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
//console.log("Competence changed :", compName); //console.log("Competence changed :", compName);
this.actor.updateCompetence(compName, parseInt(event.target.value)); this.actor.updateCompetence(compName, parseInt(event.target.value));
}); });
// On competence xp change // On competence xp change
html.find('input.competence-xp').change(async event => { this.html.find('input.competence-xp').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCompetenceXP(compName, parseInt(event.target.value)); this.actor.updateCompetenceXP(compName, parseInt(event.target.value));
}); });
// On competence xp change // On competence xp change
html.find('input.competence-xp-sort').change(async event => { this.html.find('input.competence-xp-sort').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value)); this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value));
}); });
// On competence archetype change // On competence archetype change
html.find('.competence-archetype').change(async event => { this.html.find('.competence-archetype').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCompetenceArchetype(compName, parseInt(event.target.value)); this.actor.updateCompetenceArchetype(compName, parseInt(event.target.value));
}); });
} }
html.find('.show-hide-competences').click(async event => { this.html.find('.show-hide-competences').click(async event => {
this.options.showCompNiveauBase = !this.options.showCompNiveauBase; this.options.showCompNiveauBase = !this.options.showCompNiveauBase;
this.render(true); this.render(true);
}); });
html.find('.recherche') this.html.find('.recherche')
.each((index, field) => { .each((index, field) => {
if (this.options.recherche) { if (this.options.recherche) {
field.focus(); field.focus();
@@ -446,92 +401,125 @@ export class RdDActorSheet extends ActorSheet {
.change(async event => .change(async event =>
this.options.recherche = this._optionRecherche(event.currentTarget) this.options.recherche = this._optionRecherche(event.currentTarget)
); );
html.find('.vue-detaillee').click(async event => { this.html.find('.vue-detaillee').click(async event => {
this.options.vueDetaillee = !this.options.vueDetaillee; this.options.vueDetaillee = !this.options.vueDetaillee;
this.render(true); this.render(true);
}); });
// On pts de reve change // On pts de reve change
html.find('.pointsreve-value').change(async event => { this.html.find('.pointsreve-value').change(async event => {
let reveValue = event.currentTarget.value; let reveValue = event.currentTarget.value;
this.actor.update({ "system.reve.reve.value": reveValue }); this.actor.update({ "system.reve.reve.value": reveValue });
}); });
// On seuil de reve change // On seuil de reve change
html.find('.seuil-reve-value').change(async event => { this.html.find('.seuil-reve-value').change(async event => {
console.log("seuil-reve-value", event.currentTarget) console.log("seuil-reve-value", event.currentTarget)
this.actor.setPointsDeSeuil(event.currentTarget.value); this.actor.setPointsDeSeuil(event.currentTarget.value);
}); });
html.find('#attribut-protection-edit').change(async event => { this.html.find('#attribut-protection-edit').change(async event => {
this.actor.updateAttributeValue(event.currentTarget.attributes.name.value, parseInt(event.target.value)); this.actor.updateAttributeValue(event.currentTarget.attributes.name.value, parseInt(event.target.value));
}); });
// On stress change // On stress change
html.find('.compteur-edit').change(async event => { this.html.find('.compteur-edit').change(async event => {
let fieldName = event.currentTarget.attributes.name.value; let fieldName = event.currentTarget.attributes.name.value;
this.actor.updateCompteurValue(fieldName, parseInt(event.target.value)); this.actor.updateCompteurValue(fieldName, parseInt(event.target.value));
}); });
html.find('#ethylisme').change(async event => { this.html.find('#ethylisme').change(async event => {
this.actor.setEthylisme(parseInt(event.target.value)); this.actor.setEthylisme(parseInt(event.target.value));
}); });
html.find('.stress-test').click(async event => { this.html.find('.stress-test').click(async event => {
this.actor.transformerStress(); this.actor.transformerStress();
}); });
html.find('.moral-malheureux').click(async event => { this.html.find('.moral-malheureux').click(async event => {
this.actor.jetDeMoral('malheureuse'); this.actor.jetDeMoral('malheureuse');
}); });
html.find('.moral-neutre').click(async event => { this.html.find('.moral-neutre').click(async event => {
this.actor.jetDeMoral('neutre'); this.actor.jetDeMoral('neutre');
}); });
html.find('.moral-heureux').click(async event => { this.html.find('.moral-heureux').click(async event => {
this.actor.jetDeMoral('heureuse'); this.actor.jetDeMoral('heureuse');
}); });
html.find('.ethylisme-test').click(async event => { this.html.find('.ethylisme-test').click(async event => {
this.actor.jetEthylisme(); this.actor.jetEthylisme();
}); });
html.find('.jet-vie').click(async event => { this.html.find('.jet-vie').click(async event => {
this.actor.jetVie(); this.actor.jetVie();
}); });
html.find('.jet-endurance').click(async event => { this.html.find('.jet-endurance').click(async event => {
this.actor.jetEndurance(); this.actor.jetEndurance();
}); });
html.find('.monnaie-plus').click(async event => { this.html.find('.monnaie-plus').click(async event => {
this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), 1); this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), 1);
}); });
html.find('.monnaie-moins').click(async event => { this.html.find('.monnaie-moins').click(async event => {
this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), -1); this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), -1);
}); });
html.find('.vie-plus').click(async event => { this.html.find('.vie-plus').click(async event => {
this.actor.santeIncDec("vie", 1); this.actor.santeIncDec("vie", 1);
}); });
html.find('.vie-moins').click(async event => { this.html.find('.vie-moins').click(async event => {
this.actor.santeIncDec("vie", -1); this.actor.santeIncDec("vie", -1);
}); });
html.find('.endurance-plus').click(async event => { this.html.find('.endurance-plus').click(async event => {
this.actor.santeIncDec("endurance", 1); this.actor.santeIncDec("endurance", 1);
}); });
html.find('.endurance-moins').click(async event => { this.html.find('.endurance-moins').click(async event => {
this.actor.santeIncDec("endurance", -1); this.actor.santeIncDec("endurance", -1);
}); });
html.find('.ptreve-actuel-plus').click(async event => { this.html.find('.ptreve-actuel-plus').click(async event => {
this.actor.reveActuelIncDec(1); this.actor.reveActuelIncDec(1);
}); });
html.find('.ptreve-actuel-moins').click(async event => { this.html.find('.ptreve-actuel-moins').click(async event => {
this.actor.reveActuelIncDec(-1); this.actor.reveActuelIncDec(-1);
}); });
html.find('.fatigue-plus').click(async event => { this.html.find('.fatigue-plus').click(async event => {
this.actor.santeIncDec("fatigue", 1); this.actor.santeIncDec("fatigue", 1);
}); });
html.find('.fatigue-moins').click(async event => { this.html.find('.fatigue-moins').click(async event => {
this.actor.santeIncDec("fatigue", -1); this.actor.santeIncDec("fatigue", -1);
}); });
} }
isCompetenceAffichable(competence) {
return !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(competence);
}
/* -------------------------------------------- */
async _onDropActor(event, dragData) {
const dropActor = fromUuidSync(dragData.uuid);
this.actor.addSubActeur(dropActor);
super._onDropActor(event, dragData);
}
/* -------------------------------------------- */
async _onDropItem(event, dragData) {
const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id')
const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor, dragData, this.objetVersConteneur)
if (dropParams) {
const callSuper = await this.actor.processDropItem(dropParams)
if (callSuper) {
await super._onDropItem(event, dragData)
}
}
}
/* -------------------------------------------- */
async createItem(name, type) {
await this.actor.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
}
/* -------------------------------------------- */
async createEmptyTache() {
await this.createItem('Nouvelle tache', 'tache');
}
_optionRecherche(target) { _optionRecherche(target) {
if (!target.value?.length) { if (!target.value?.length) {
return undefined; return undefined;
@@ -544,7 +532,7 @@ export class RdDActorSheet extends ActorSheet {
} }
_getEventArmeCombat(event) { _getEventArmeCombat(event) {
const li = $(event.currentTarget)?.parents(".item"); const li = this.html.find(event.currentTarget)?.parents(".item");
let armeName = li.data("arme-name"); let armeName = li.data("arme-name");
let compName = li.data('competence-name'); let compName = li.data('competence-name');
const arme = this.armesList.find(a => a.name == armeName && a.system.competence == compName); const arme = this.armesList.find(a => a.name == armeName && a.system.competence == compName);

View File

@@ -18,5 +18,22 @@ export class RdDActorVehiculeSheet extends RdDActorSheet {
}); });
} }
activateListeners(html) {
super.activateListeners(html);
if (!this.options.editable) return;
this.html.find('.resistance-moins').click(async event => {
this.actor.vehicleIncDec("resistance", -1);
});
this.html.find('.resistance-plus').click(async event => {
this.actor.vehicleIncDec("resistance", 1);
});
this.html.find('.structure-moins').click(async event => {
this.actor.vehicleIncDec("structure", -1);
});
this.html.find('.structure-plus').click(async event => {
this.actor.vehicleIncDec("structure", 1);
});
}
} }

File diff suppressed because it is too large Load Diff

View File

@@ -16,13 +16,15 @@ export class DialogChronologie extends Dialog {
}); });
} }
static async create() { static async create() {
const dateRdD = game.system.rdd.calendrier.getCalendrier();
const dialogData = { const dialogData = {
auteur: game.user.name, auteur: game.user.name,
isGM: game.user.isGM, isGM: game.user.isGM,
information: "", information: "",
journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID), journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID),
journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)), journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)),
dateRdD: game.system.rdd.calendrier.getCalendrier(), dateRdD: dateRdD,
jourRdD: dateRdD.jour +1,
heureRdD: game.system.rdd.calendrier.getCurrentHeure(), heureRdD: game.system.rdd.calendrier.getCurrentHeure(),
dateReel: DialogChronologie.getCurrentDateTime() dateReel: DialogChronologie.getCurrentDateTime()
}; };
@@ -60,6 +62,7 @@ export class DialogChronologie extends Dialog {
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = html;
} }
async ajouter() { async ajouter() {
@@ -72,11 +75,11 @@ export class DialogChronologie extends Dialog {
} }
async forceValidation() { async forceValidation() {
await $("form.rdddialogchrono :input").change(); await this.html.find("form.rdddialogchrono :input").change();
} }
findJournal() { findJournal() {
const journalId = $("form.rdddialogchrono :input[name='journalId']").val(); const journalId = this.html.find("form.rdddialogchrono :input[name='journalId']").val();
const journalEntry = game.journal.get(journalId); const journalEntry = game.journal.get(journalId);
return { journalId, journalEntry }; return { journalId, journalEntry };
} }
@@ -87,15 +90,15 @@ export class DialogChronologie extends Dialog {
extractJournalParameters() { extractJournalParameters() {
return { return {
auteur: $("form.rdddialogchrono :input[name='auteur']").val(), auteur: this.html.find("form.rdddialogchrono :input[name='auteur']").val(),
information: $("form.rdddialogchrono :input[name='information']").val(), information: this.html.find("form.rdddialogchrono :input[name='information']").val(),
dateRdD: { dateRdD: {
jour: $("form.rdddialogchrono :input[name='dateRdD.jour']").val(), jour: this.html.find("form.rdddialogchrono :input[name='jourRdD']").val(),
moisRdD: $("form.rdddialogchrono :input[name='dateRdD.moisRdD.key']").val(), moisRdD: this.html.find("form.rdddialogchrono :input[name='dateRdD.moisRdD.key']").val(),
annee: $("form.rdddialogchrono :input[name='dateRdD.annee']").val() annee: this.html.find("form.rdddialogchrono :input[name='dateRdD.annee']").val()
}, },
heureRdD: $("form.rdddialogchrono :input[name='heureRdD']").val(), heureRdD: this.html.find("form.rdddialogchrono :input[name='heureRdD']").val(),
dateReel: $("form.rdddialogchrono :input[name='dateReel']").val().replace('T', ' ') dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val().replace('T', ' ')
} }
} }

View File

@@ -37,8 +37,8 @@ export class DialogCreateSigneDraconique extends Dialog {
} }
async _onCreerSigneActeurs() { async _onCreerSigneActeurs() {
await $("[name='signe.system.ephemere']").change(); await this.html.find("[name='signe.system.ephemere']").change();
await $(".signe-xp-sort").change(); await this.html.find(".signe-xp-sort").change();
this.validerSigne(); this.validerSigne();
this.dialogData.actors.filter(it => it.selected) this.dialogData.actors.filter(it => it.selected)
.map(it => game.actors.get(it.id)) .map(it => game.actors.get(it.id))
@@ -57,19 +57,20 @@ export class DialogCreateSigneDraconique extends Dialog {
} }
validerSigne() { validerSigne() {
this.dialogData.signe.name = $("[name='signe.name']").val(); this.dialogData.signe.name = this.html.find("[name='signe.name']").val();
this.dialogData.signe.system.valeur.norm = $("[name='signe.system.valeur.norm']").val(); this.dialogData.signe.system.valeur.norm = this.html.find("[name='signe.system.valeur.norm']").val();
this.dialogData.signe.system.valeur.sign = $("[name='signe.system.valeur.sign']").val(); this.dialogData.signe.system.valeur.sign = this.html.find("[name='signe.system.valeur.sign']").val();
this.dialogData.signe.system.valeur.part = $("[name='signe.system.valeur.part']").val(); this.dialogData.signe.system.valeur.part = this.html.find("[name='signe.system.valeur.part']").val();
this.dialogData.signe.system.difficulte = $("[name='signe.system.difficulte']").val(); this.dialogData.signe.system.difficulte = this.html.find("[name='signe.system.difficulte']").val();
this.dialogData.signe.system.ephemere = $("[name='signe.system.ephemere']").prop("checked"); this.dialogData.signe.system.ephemere = this.html.find("[name='signe.system.ephemere']").prop("checked");
this.dialogData.signe.system.duree = $("[name='signe.system.duree']").val(); this.dialogData.signe.system.duree = this.html.find("[name='signe.system.duree']").val();
this.dialogData.signe.system.typesTMR = TMRUtility.buildListTypesTMRSelection(this.dialogData.tmrs); this.dialogData.signe.system.typesTMR = TMRUtility.buildListTypesTMRSelection(this.dialogData.tmrs);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = html;
this.setEphemere(this.dialogData.signe.system.ephemere); this.setEphemere(this.dialogData.signe.system.ephemere);
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire()); html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
html.find("[name='signe.system.ephemere']").change((event) => this.setEphemere(event.currentTarget.checked)); html.find("[name='signe.system.ephemere']").change((event) => this.setEphemere(event.currentTarget.checked));
@@ -81,27 +82,27 @@ export class DialogCreateSigneDraconique extends Dialog {
async setSigneAleatoire() { async setSigneAleatoire() {
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true}); const newSigne = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
$("[name='signe.name']").val(newSigne.name); this.html.find("[name='signe.name']").val(newSigne.name);
$("[name='signe.system.valeur.norm']").val(newSigne.system.valeur.norm); this.html.find("[name='signe.system.valeur.norm']").val(newSigne.system.valeur.norm);
$("[name='signe.system.valeur.sign']").val(newSigne.system.valeur.sign); this.html.find("[name='signe.system.valeur.sign']").val(newSigne.system.valeur.sign);
$("[name='signe.system.valeur.part']").val(newSigne.system.valeur.part); this.html.find("[name='signe.system.valeur.part']").val(newSigne.system.valeur.part);
$("[name='signe.system.difficulte']").val(newSigne.system.difficulte); this.html.find("[name='signe.system.difficulte']").val(newSigne.system.difficulte);
$("[name='signe.system.duree']").val(newSigne.system.duree); this.html.find("[name='signe.system.duree']").val(newSigne.system.duree);
$("[name='signe.system.ephemere']").prop("checked", newSigne.system.ephemere); this.html.find("[name='signe.system.ephemere']").prop("checked", newSigne.system.ephemere);
this.dialogData.tmrs = TMRUtility.buildSelectionTypesTMR(newSigne.system.typesTMR); this.dialogData.tmrs = TMRUtility.buildSelectionTypesTMR(newSigne.system.typesTMR);
this.dialogData.tmrs.forEach(t => { this.dialogData.tmrs.forEach(t => {
$(`[data-tmr-name='${t.name}']`).prop( "checked", t.selected); this.html.find(`[data-tmr-name='${t.name}']`).prop( "checked", t.selected);
}) })
this.setEphemere(newSigne.system.ephemere); this.setEphemere(newSigne.system.ephemere);
} }
async setEphemere(ephemere) { async setEphemere(ephemere) {
this.dialogData.signe.system.ephemere = ephemere; this.dialogData.signe.system.ephemere = ephemere;
HtmlUtility._showControlWhen($(".signe-system-duree"), ephemere); HtmlUtility._showControlWhen(this.html.find(".signe-system-duree"), ephemere);
} }
async onSelectActor(event) { async onSelectActor(event) {
const actorId = $(event.currentTarget)?.data("actor-id"); const actorId = this.html.find(event.currentTarget)?.data("actor-id");
const actor = this.dialogData.actors.find(it => it.id == actorId); const actor = this.dialogData.actors.find(it => it.id == actorId);
if (actor) { if (actor) {
actor.selected = event.currentTarget.checked; actor.selected = event.currentTarget.checked;
@@ -109,7 +110,7 @@ export class DialogCreateSigneDraconique extends Dialog {
} }
onSelectTmr(event) { onSelectTmr(event) {
const tmrName = $(event.currentTarget)?.data("tmr-name"); const tmrName = this.html.find(event.currentTarget)?.data("tmr-name");
const onTmr = this.tmrs.find(it => it.name == tmrName); const onTmr = this.tmrs.find(it => it.name == tmrName);
if (onTmr){ if (onTmr){
onTmr.selected = event.currentTarget.checked; onTmr.selected = event.currentTarget.checked;

View File

@@ -13,18 +13,12 @@ export class DialogFabriquerPotion extends Dialog {
} }
let potionData = DialogFabriquerPotion.prepareData(actor, item); let potionData = DialogFabriquerPotion.prepareData(actor, item);
let conf = { const html = await renderTemplate(dialogConfig.html, potionData);
title: `Fabriquer une potion de ${potionData.system.categorie}`,
content: await renderTemplate(dialogConfig.html, potionData),
default: potionData.buttonName,
};
let options = { classes: ["dialogfabriquerpotion"], width: 600, height: 160, 'z-index': 99999 }; let options = { classes: ["dialogfabriquerpotion"], width: 600, height: 160, 'z-index': 99999 };
mergeObject(options, dialogConfig.options ?? {}, { overwrite: true }) mergeObject(options, dialogConfig.options ?? {}, { overwrite: true })
const dialog = new DialogFabriquerPotion(actor, potionData, conf, options); new DialogFabriquerPotion(actor, potionData, html, options).render(true);
dialog.render(true);
return dialog;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -40,10 +34,15 @@ export class DialogFabriquerPotion extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
constructor(actor, potionData, conf, options) { constructor(actor, potionData, html, options) {
conf.buttons = { const conf = {
[potionData.buttonName]: { title: `Fabriquer une potion de ${potionData.system.categorie}`,
label: potionData.buttonName, callback: it => this.onFabriquer(it) content: html,
default: 'fabriquer',
buttons: {
'fabriquer': {
label: potionData.buttonName, callback: it => this.onFabriquer(html)
}
} }
}; };
@@ -53,6 +52,24 @@ export class DialogFabriquerPotion extends Dialog {
this.potionData = potionData; this.potionData = potionData;
} }
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
this.html = html;
this.html.find("[name='nbBrins']").change(event => {
this.potionData.nbBrins = Misc.toInt(event.currentTarget.value);
const brinsManquants = Math.max(0, DialogFabriquerPotion.nombreBrinsOptimal(this.potionData) - this.potionData.nbBrins);
this.potionData.herbebonus = Math.max(0, this.potionData.system.niveau - brinsManquants)
});
}
/* -------------------------------------------- */
async onFabriquer(html) {
await this.html.find("[name='nbBrins']").change();
this.actor.fabriquerPotion(this.potionData);
this.close();
}
static nombreBrinsMinimum(herbeData) { static nombreBrinsMinimum(herbeData) {
switch (herbeData.system.categorie ?? '') { switch (herbeData.system.categorie ?? '') {
case "Soin": return 1 + Math.max(0, 12 - 2 * herbeData.system.niveau); case "Soin": return 1 + Math.max(0, 12 - 2 * herbeData.system.niveau);
@@ -68,22 +85,4 @@ export class DialogFabriquerPotion extends Dialog {
} }
return 1; return 1;
} }
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
html.find("#nbBrins").change(event => {
this.potionData.nbBrins = Misc.toInt(event.currentTarget.value);
const brinsManquants = Math.max(0, DialogFabriquerPotion.nombreBrinsOptimal(this.potionData) - this.potionData.nbBrins);
this.potionData.herbebonus = Math.max(0, this.potionData.system.niveau - brinsManquants)
});
}
/* -------------------------------------------- */
async onFabriquer(it) {
await $("#nbBrins").change();
this.actor.fabriquerPotion(this.potionData);
this.close();
}
} }

View File

@@ -1,15 +1,13 @@
import { Monnaie } from "./item-monnaie.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
export class DialogItemAchat extends Dialog { export class DialogItemAchat extends Dialog {
static venteData(button) { static preparerAchat(chatButton) {
const vendeurId = button.attributes['data-vendeurId']?.value; const vendeurId = chatButton.attributes['data-vendeurId']?.value;
const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined; const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined;
const acheteur = RdDUtility.getSelectedActor(); const acheteur = RdDUtility.getSelectedActor();
const json = button.attributes['data-jsondata']?.value; const json = chatButton.attributes['data-jsondata']?.value;
if (!acheteur && !vendeur) { if (!acheteur && !vendeur) {
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement"); ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
return undefined; return undefined;
@@ -19,61 +17,82 @@ export class DialogItemAchat extends Dialog {
return undefined; return undefined;
} }
const prixLot = Monnaie.arrondiDeniers(button.attributes['data-prixLot']?.value ?? 0);
return { return {
item: json ? JSON.parse(json) : undefined, item: (json ? JSON.parse(json) : undefined),
actingUserId: game.user.id, vendeur,
vendeurId: vendeurId, acheteur,
vendeur: vendeur, nbLots: parseInt(chatButton.attributes['data-quantiteNbLots']?.value),
acheteur: acheteur, tailleLot: parseInt(chatButton.attributes['data-tailleLot']?.value ?? 1),
tailleLot: parseInt(button.attributes['data-tailleLot']?.value ?? 1), prixLot: Number(chatButton.attributes['data-prixLot']?.value ?? 0),
quantiteIllimite: button.attributes['data-quantiteIllimite']?.value == 'true', quantiteIllimite: chatButton.attributes['data-quantiteIllimite']?.value == 'true',
quantiteNbLots: parseInt(button.attributes['data-quantiteNbLots']?.value), chatMessageIdVente: RdDUtility.findChatMessageId(chatButton),
choix: {
nombreLots: 1,
seForcer: false,
supprimerSiZero: true
},
prixLot: prixLot,
prixTotal: prixLot,
isVente: prixLot > 0,
chatMessageIdVente: RdDUtility.findChatMessageId(button)
}; };
} }
static async onAcheter(venteData) {
static async onAcheter({ item, vendeur, acheteur, service, tailleLot, prixLot, nbLots, quantiteIllimite, chatMessageIdVente }) {
const venteData = {
item,
actingUserId: game.user.id,
vendeurId: vendeur?.id,
vendeur,
acheteur,
service,
tailleLot,
quantiteIllimite,
quantiteNbLots: nbLots,
choix: { seForcer: false, supprimerSiZero: true },
prixLot,
isVente: prixLot > 0,
isConsommable: item.type == 'nourritureboisson' && acheteur?.isPersonnage(),
chatMessageIdVente
};
DialogItemAchat.changeNombreLots(venteData, 1);
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData); const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
const dialog = new DialogItemAchat(html, venteData); new DialogItemAchat(html, venteData).render(true);
dialog.render(true); }
static changeNombreLots(venteData, nombreLots) {
venteData.choix.nombreLots = nombreLots;
venteData.prixTotal = (nombreLots * venteData.prixLot).toFixed(2);
if (venteData.isConsommable) {
const doses = nombreLots * venteData.tailleLot;
venteData.totalSust = Misc.keepDecimals(doses * (venteData.item.system.sust ?? 0), 2);
venteData.totalDesaltere = venteData.item.system.boisson
? Misc.keepDecimals(doses * (venteData.item.system.desaltere ?? 0), 2)
: 0;
}
} }
constructor(html, venteData) { constructor(html, venteData) {
const isConsommable = venteData.item.type == 'nourritureboisson' && venteData.acheteur?.isPersonnage();
let options = { classes: ["dialogachat"], width: 400, height: 'fit-content', 'z-index': 99999 }; let options = { classes: ["dialogachat"], width: 400, height: 'fit-content', 'z-index': 99999 };
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre"; const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
const buttons = {}; const buttons = {};
if (isConsommable) { if (venteData.isConsommable) {
buttons["consommer"] = { label: venteData.item.system.boisson ? "Boire" : "Manger", callback: it => this.onAchatConsommer() } buttons["consommer"] = { label: venteData.item.system.boisson ? "Boire" : "Manger", callback: it => this.onAchatConsommer() }
} }
buttons[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } }; buttons[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } };
buttons["decliner"] = { label: "Décliner", callback: it => { } }; buttons["decliner"] = { label: "Décliner", callback: it => { } };
const acheteur = venteData.acheteur?.name ?? 'Un acheteur';
const vendeur = (venteData.service ?? venteData.vendeur)?.name ?? 'Un vendeur';
let conf = { let conf = {
title: venteData.acheteur ? venteData.acheteur.name + " - " + actionAchat : actionAchat, title: `${acheteur} - ${actionAchat} à ${vendeur}`,
content: html, content: html,
default: actionAchat, default: actionAchat,
buttons: buttons buttons: buttons
}; };
super(conf, options); super(conf, options);
this.venteData = venteData; this.venteData = venteData;
} }
async onAchat() { async onAchat() {
await $(".nombreLots").change(); await this.html.find(".nombreLots").change();
(this.venteData.vendeur ?? this.venteData.acheteur).achatVente({ (this.venteData.vendeur ?? this.venteData.acheteur).achatVente({
userId: game.user.id, userId: game.user.id,
serviceId: this.venteData.service?.id,
vendeurId: this.venteData.vendeur?.id, vendeurId: this.venteData.vendeur?.id,
acheteurId: this.venteData.acheteur?.id, acheteurId: this.venteData.acheteur?.id,
prixTotal: this.venteData.prixTotal, prixTotal: this.venteData.prixTotal,
@@ -91,9 +110,9 @@ export class DialogItemAchat extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = html;
html.find(".nombreLots").change(event => this.setNombreLots(Number(event.currentTarget.value))); this.html.find(".nombreLots").change(event => this.setNombreLots(Number(event.currentTarget.value)));
html.find(".se-forcer").change(event => this.setSeForcer(event)); this.html.find(".se-forcer").change(event => this.setSeForcer(event));
} }
setSeForcer(event) { setSeForcer(event) {
@@ -101,13 +120,21 @@ export class DialogItemAchat extends Dialog {
} }
setNombreLots(nombreLots) { setNombreLots(nombreLots) {
if (nombreLots > this.venteData.quantiteNbLots) {
if (!this.venteData.quantiteIllimite) {
if (!this.venteData.quantiteIllimite && nombreLots > this.venteData.quantiteNbLots) {
ui.notifications.warn(`Seulement ${this.venteData.quantiteNbLots} lots disponibles, vous ne pouvez pas en prendre ${nombreLots}`) ui.notifications.warn(`Seulement ${this.venteData.quantiteNbLots} lots disponibles, vous ne pouvez pas en prendre ${nombreLots}`)
} }
this.venteData.choix.nombreLots = Math.min(nombreLots, this.venteData.quantiteNbLots); nombreLots = Math.min(nombreLots, this.venteData.quantiteNbLots);
this.venteData.prixTotal = (nombreLots * this.venteData.prixLot).toFixed(2);
$(".nombreLots").val(this.venteData.choix.nombreLots);
$(".prixTotal").text(this.venteData.prixTotal);
} }
DialogItemAchat.changeNombreLots(this.venteData, nombreLots);
this.html.find(".nombreLots").val(nombreLots);
this.html.find(".prixTotal").text(this.venteData.prixTotal);
this.html.find("span.total-sust").text(this.venteData.totalSust);
this.html.find("span.total-desaltere").text(this.venteData.totalDesaltere);
}
} }

View File

@@ -17,8 +17,9 @@ export class DialogConsommer extends Dialog {
buttons: { buttons: {
[consommerData.buttonName]: { [consommerData.buttonName]: {
label: consommerData.buttonName, callback: async it => { label: consommerData.buttonName, callback: async it => {
await this.onConsommer(it); await this.onConsommer();
await onActionItem();} await onActionItem();
}
} }
} }
}; };
@@ -30,17 +31,23 @@ export class DialogConsommer extends Dialog {
this.consommerData = consommerData; this.consommerData = consommerData;
} }
async onConsommer(event) { activateListeners(html) {
await $(".se-forcer").change(); super.activateListeners(html);
await $(".consommer-doses").change(); this.html = html;
this.html.find(".se-forcer").change(event => this.setSeForcer(event));
this.html.find(".consommer-doses").change(event => this.selectDoses(event));
}
async onConsommer() {
await this.html.find(".se-forcer").change();
await this.html.find(".consommer-doses").change();
await this.actor.consommer(this.item, this.consommerData.choix); await this.actor.consommer(this.item, this.consommerData.choix);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static prepareData(actor, item) { static prepareData(actor, item) {
item = duplicate(item);
let consommerData = { let consommerData = {
item: item, item: duplicate(item),
cuisine: actor.getCompetence('cuisine'), cuisine: actor.getCompetence('cuisine'),
choix: { choix: {
doses: 1, doses: 1,
@@ -48,33 +55,47 @@ export class DialogConsommer extends Dialog {
} }
} }
switch (item.type) { switch (item.type) {
case 'herbe': case 'faune':
consommerData.title = 'Manger une portion crue: ';
consommerData.buttonName = "Manger";
break;
case 'nourritureboisson': case 'nourritureboisson':
consommerData.title = item.system.boisson ? `${item.name}: boire une dose` : `${item.name}: manger une portion`; consommerData.title = item.system.boisson ? 'Boire une dose: ' : 'Manger une portion: ';
consommerData.buttonName = item.system.boisson ? "Boire" : "Manger"; consommerData.buttonName = item.system.boisson ? "Boire" : "Manger";
break; break;
case 'potion': case 'potion':
consommerData.title = `${item.name}: boire la potion`; consommerData.title = 'Boire la potion: ';
consommerData.buttonName = "Boire"; consommerData.buttonName = "Boire";
break; break;
} }
DialogConsommer.calculDoses(consommerData, consommerData.choix.doses) consommerData.title += item.name;
DialogConsommer.calculDoses(consommerData, item)
return consommerData; return consommerData;
} }
static calculDoses(consommer) { static calculDoses(consommer, item) {
const doses = consommer.choix.doses; const doses = consommer.choix.doses;
switch (item.type) {
case 'herbe': case 'faune':
consommer.totalSust = doses;
consommer.totalDesaltere = 0;
consommer.choix.sust = 1;
consommer.choix.quantite = 0;
consommer.choix.encombrement = Misc.keepDecimals(consommer.item.system.encombrement / item.system.sust, 2);
return;
case 'nourritureboisson':
consommer.choix.sust = consommer.item.system.sust;
consommer.choix.quantite = doses;
consommer.choix.encombrement = 0
consommer.totalSust = Misc.keepDecimals(doses * (consommer.item.system.sust ?? 0), 2); consommer.totalSust = Misc.keepDecimals(doses * (consommer.item.system.sust ?? 0), 2);
consommer.totalDesaltere = consommer.item.system.boisson consommer.totalDesaltere = consommer.item.system.boisson
? Misc.keepDecimals(doses * (consommer.item.system.desaltere ?? 0), 2) ? Misc.keepDecimals(doses * (consommer.item.system.desaltere ?? 0), 2)
: 0; : 0;
break;
case 'potion':
consommer.totalSust = 0
consommer.totalDesaltere = 0
} }
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
html.find(".se-forcer").change(event => this.setSeForcer(event));
html.find(".consommer-doses").change(event => this.selectDoses(event));
} }
@@ -84,8 +105,8 @@ export class DialogConsommer extends Dialog {
selectDoses(event) { selectDoses(event) {
this.consommerData.choix.doses = Number(event.currentTarget.value); this.consommerData.choix.doses = Number(event.currentTarget.value);
DialogConsommer.calculDoses(this.consommerData); DialogConsommer.calculDoses(this.consommerData, this.item);
$(".total-sust").text(this.consommerData.totalSust); this.html.find(".total-sust").text(this.consommerData.totalSust);
$(".total-desaltere").text(this.consommerData.totalDesaltere); this.html.find(".total-desaltere").text(this.consommerData.totalDesaltere);
} }
} }

View File

@@ -1,14 +1,16 @@
import { HtmlUtility } from "./html-utility.js"; import { HtmlUtility } from "./html-utility.js";
import { Misc } from "./misc.js";
export class DialogItemVente extends Dialog { export class DialogItemVente extends Dialog {
static async display(item, callback) { static async display({ item, callback, service = undefined, quantiteMax = undefined }) {
const quantite = item.isConteneur() ? 1 : item.system.quantite; const quantite = quantiteMax ?? item.getQuantite();
const isOwned = item.isOwned;
// const isOwned = item.isOwned || service?.actor;
const venteData = { const venteData = {
item: item, item: item,
alias: item.actor?.name ?? game.user.name, alias: item.actor?.name ?? service?.name ?? game.user.name,
vendeurId: item.actor?.id, serviceId: service?.id,
vendeurId: item.actor?.id ?? service?.actor?.id,
prixOrigine: item.system.cout, prixOrigine: item.system.cout,
prixUnitaire: item.system.cout, prixUnitaire: item.system.cout,
prixLot: item.system.cout, prixLot: item.system.cout,
@@ -16,8 +18,8 @@ export class DialogItemVente extends Dialog {
quantiteNbLots: quantite, quantiteNbLots: quantite,
quantiteMaxLots: quantite, quantiteMaxLots: quantite,
quantiteMax: quantite, quantiteMax: quantite,
quantiteIllimite: !item.isOwned, quantiteIllimite: service? service.system.illimite : !isOwned,
isOwned: item.isOwned, isOwned: isOwned,
}; };
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData); const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData);
return new DialogItemVente(venteData, html, callback).render(true); return new DialogItemVente(venteData, html, callback).render(true);
@@ -38,26 +40,26 @@ export class DialogItemVente extends Dialog {
this.venteData = venteData; this.venteData = venteData;
} }
activateListeners(html) {
super.activateListeners(html);
this.html = html;
HtmlUtility._showControlWhen(this.html.find(".quantiteNbLots"), !this.venteData.quantiteIllimite)
this.html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value)));
this.html.find(".quantiteNbLots").change(event => this.setNbLots(Number(event.currentTarget.value)));
this.html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked));
this.html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value)));
}
async onProposer(it) { async onProposer(it) {
await $(".tailleLot").change(); await this.html.find(".tailleLot").change();
await $(".quantiteNbLots").change(); await this.html.find(".quantiteNbLots").change();
await $(".quantiteIllimite").change(); await this.html.find(".quantiteIllimite").change();
await $(".prixLot").change(); await this.html.find(".prixLot").change();
this.callback(this.venteData); this.callback(this.venteData);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
HtmlUtility._showControlWhen($(".quantiteNbLots"), !this.venteData.quantiteIllimite)
html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value)));
html.find(".quantiteNbLots").change(event => this.setNbLots(Number(event.currentTarget.value)));
html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked));
html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value)));
}
setPrixLot(prixLot) { setPrixLot(prixLot) {
this.venteData.prixLot = prixLot; this.venteData.prixLot = prixLot;
} }
@@ -66,16 +68,14 @@ export class DialogItemVente extends Dialog {
// recalculer le prix du lot // recalculer le prix du lot
if (tailleLot != this.venteData.tailleLot) { if (tailleLot != this.venteData.tailleLot) {
this.venteData.prixLot = (tailleLot * this.venteData.prixOrigine).toFixed(2); this.venteData.prixLot = (tailleLot * this.venteData.prixOrigine).toFixed(2);
$(".prixLot").val(this.venteData.prixLot); this.html.find(".prixLot").val(this.venteData.prixLot);
} }
this.venteData.tailleLot = tailleLot; this.venteData.tailleLot = tailleLot;
if (this.venteData.isOwned) {
// recalculer le nombre de lots max // recalculer le nombre de lots max
this.venteData.quantiteMaxLots = Math.floor(this.venteData.quantiteMax / tailleLot); this.venteData.quantiteMaxLots = Math.floor(this.venteData.quantiteMax / tailleLot);
this.venteData.quantiteNbLots = Math.min(this.venteData.quantiteMaxLots, this.venteData.quantiteNbLots); this.venteData.quantiteNbLots = Math.min(this.venteData.quantiteMaxLots, this.venteData.quantiteNbLots);
$(".quantiteNbLots").val(this.venteData.quantiteNbLots); this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
$(".quantiteNbLots").attr("max", this.venteData.quantiteMaxLots) this.html.find(".quantiteNbLots").attr("max", this.venteData.quantiteMaxLots)
}
} }
setNbLots(nbLots) { setNbLots(nbLots) {
@@ -83,12 +83,12 @@ export class DialogItemVente extends Dialog {
nbLots = Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots)); nbLots = Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots));
} }
this.venteData.quantiteNbLots = nbLots; this.venteData.quantiteNbLots = nbLots;
$(".quantiteNbLots").val(this.venteData.quantiteNbLots); this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
} }
setQuantiteIllimite(checked) { setQuantiteIllimite(checked) {
this.venteData.quantiteIllimite = checked; this.venteData.quantiteIllimite = checked;
$(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles"); this.html.find(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles");
HtmlUtility._showControlWhen($(".quantiteNbLots"), !this.venteData.quantiteIllimite) HtmlUtility._showControlWhen(this.html.find(".quantiteNbLots"), !this.venteData.quantiteIllimite)
} }
} }

View File

@@ -1,4 +1,3 @@
import { Misc } from "./misc.js";
export class DialogRepos extends Dialog { export class DialogRepos extends Dialog {
@@ -9,7 +8,7 @@ export class DialogRepos extends Dialog {
} }
constructor(html, actor) { constructor(html, actor) {
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 500, height: 400, 'z-index': 99999 }; let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 400, height: 'fit-content', 'z-index': 99999 };
let conf = { let conf = {
title: "Se reposer", title: "Se reposer",
content: html, content: html,
@@ -21,13 +20,18 @@ export class DialogRepos extends Dialog {
super(conf, options); super(conf, options);
this.actor = actor; this.actor = actor;
} }
activateListeners(html) {
super.activateListeners(html);
this.html = html;
}
/* -------------------------------------------- */
async repos() { async repos() {
await $("[name='nb-heures']").change(); await this.html.find("[name='nb-heures']").change();
await $("[name='nb-jours']").change(); await this.html.find("[name='nb-jours']").change();
const selection = await $("[name='repos']:checked").val(); const selection = await this.html.find("[name='repos']:checked").val();
const nbHeures = Number.parseInt(await $("[name='nb-heures']").val()); const nbHeures = Number.parseInt(await this.html.find("[name='nb-heures']").val());
const nbJours = Number.parseInt(await $("[name='nb-jours']").val()); const nbJours = Number.parseInt(await this.html.find("[name='nb-jours']").val());
switch (selection) { switch (selection) {
case "sieste": { case "sieste": {
await this.actor.dormir(nbHeures); await this.actor.dormir(nbHeures);
@@ -49,8 +53,4 @@ export class DialogRepos extends Dialog {
} }
} }
} }
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
}
} }

View File

@@ -0,0 +1,37 @@
export class DialogSelectTarget extends Dialog {
constructor(html, onSelectTarget, targets) {
const options = {
classes: ["rdd-dialog-select-target"],
width: 'fit-content',
height: 'fit-content',
'max-height': 600,
'z-index': 99999
};
const conf = {
title: "Choisir une cible",
content: html,
buttons: {}
};
super(conf, options);
this.onSelectTarget = onSelectTarget;
this.targets = targets;
}
activateListeners(html) {
super.activateListeners(html);
this.html = html;
this.html.find("li.select-target").click((event) => {
this.targetSelected(this.html.find(event.currentTarget)?.data("token-id"));
});
}
targetSelected(tokenId) {
const target = this.targets.find(it => it.id == tokenId);
this.close();
if (target) {
this.onSelectTarget(target);
}
}
}

View File

@@ -12,21 +12,15 @@ export class DialogSplitItem extends Dialog {
} }
constructor(item, splitData, html, callback) { constructor(item, splitData, html, callback) {
let options = { classes: ["dialogsplit"], width: 300, height: 160, 'z-index': 99999 }; let options = { classes: ["dialogsplit"], width: 300, height: 'fit-content', 'z-index': 99999 };
let conf = { let conf = {
title: "Séparer en deux", title: "Séparer en deux",
content: html, content: html,
default: "separer", default: "separer",
buttons: { buttons: {
"separer": { "separer": { label: "Séparer", callback: it => this.onSplit() }
label: "Séparer", callback: it => {
this.onSplit();
}
}
} }
}; };
super(conf, options); super(conf, options);
this.callback = callback; this.callback = callback;
@@ -34,18 +28,18 @@ export class DialogSplitItem extends Dialog {
this.splitData = splitData; this.splitData = splitData;
} }
async onSplit(){
await $(".choix-quantite").change();
this.callback(this.item, this.splitData.choix.quantite);
}
/* -------------------------------------------- */
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = html;
html.find(".choix-quantite").change(event => { this.html.find(".choix-quantite").change(event => {
this.splitData.choix.quantite = Number(event.currentTarget.value); this.splitData.choix.quantite = Number(event.currentTarget.value);
}); });
} }
/* -------------------------------------------- */
async onSplit() {
await this.html.find(".choix-quantite").change();
this.callback(this.item, this.splitData.choix.quantite);
}
} }

View File

@@ -37,24 +37,24 @@ export class DialogStress extends Dialog {
this.dialogData = dialogData; this.dialogData = dialogData;
} }
activateListeners(html) {
super.activateListeners(html);
this.html = html;
this.html.find("input.select-actor").change((event) => this.onSelectActor(event));
}
async onStress() { async onStress() {
const motif = $("form.rdddialogstress input[name='motif']").val(); const motif = this.html.find("form.rdddialogstress input[name='motif']").val();
const stress = Number($("form.rdddialogstress input[name='stress']").val()); const stress = Number(this.html.find("form.rdddialogstress input[name='stress']").val());
const compteur = ($("form.rdddialogstress input[name='immediat']").prop("checked")) ? 'experience' : 'stress'; const compteur = (this.html.find("form.rdddialogstress input[name='immediat']").prop("checked")) ? 'experience' : 'stress';
this.dialogData.actors.filter(it => it.selected) this.dialogData.actors.filter(it => it.selected)
.map(it => game.actors.get(it.id)) .map(it => game.actors.get(it.id))
.forEach(actor => actor.distribuerStress(compteur, stress, motif)); .forEach(actor => actor.distribuerStress(compteur, stress, motif));
} }
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
html.find("input.select-actor").change((event) => this.onSelectActor(event));
}
async onSelectActor(event) { async onSelectActor(event) {
const actorId = $(event.currentTarget)?.data("actor-id"); const actorId = this.html.find(event.currentTarget)?.data("actor-id");
const actor = this.dialogData.actors.find(it => it.id == actorId); const actor = this.dialogData.actors.find(it => it.id == actorId);
if (actor) { if (actor) {
actor.selected = event.currentTarget.checked; actor.selected = event.currentTarget.checked;

View File

@@ -35,7 +35,7 @@ export class DialogValidationEncaissement extends Dialog {
} }
let dialogOptions = { let dialogOptions = {
classes: ["rdddialog"], classes: ["rdd-roll-dialog"],
width: 350, width: 350,
height: 290 height: 290
} }
@@ -55,11 +55,12 @@ export class DialogValidationEncaissement extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
html.find('input.encaissement-roll-result').keyup(async event => { this.html = html;
this.html.find('input.encaissement-roll-result').keyup(async event => {
this.forceDiceResult.total = event.currentTarget.value; this.forceDiceResult.total = event.currentTarget.value;
this.encaissement = await RdDUtility.jetEncaissement(this.rollData, this.armure, { showDice: HIDE_DICE, forceDiceResult: this.forceDiceResult}); this.encaissement = await RdDUtility.jetEncaissement(this.rollData, this.armure, { showDice: HIDE_DICE, forceDiceResult: this.forceDiceResult});
$('label.encaissement-total').text(this.encaissement.total); this.html.find('label.encaissement-total').text(this.encaissement.total);
$('label.encaissement-blessure').text(this.encaissement.blessures) this.html.find('label.encaissement-blessure').text(this.encaissement.blessures)
}); });
} }

223
module/environnement.js Normal file
View File

@@ -0,0 +1,223 @@
import { SYSTEM_RDD } from "./constants.js";
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { CompendiumTableHelpers, CompendiumTable } from "./settings/system-compendiums.js";
const RARETES = [
{ name: 'Commune', frequence: 54, min: 27, max: 108 },
{ name: 'Frequente', frequence: 18, min: 9, max: 36 },
{ name: 'Rare', frequence: 6, min: 3, max: 12 },
{ name: 'Rarissime', frequence: 2, min: 1, max: 4 }]
const DEFAULT_RARETE = 1;
const SETTINGS_LISTE_MILIEUX = "liste-milieux";
const MILIEUX = [
"Collines",
"Cours d'eau",
"Déserts",
"Forêts",
"Marais",
"Maritimes",
"Montagnes",
"Plaines",
"Sous-sols"
]
const ITEM_ENVIRONNEMENT_TYPES = [
'herbe', 'ingredient', 'faune'
]
export class Environnement {
static init() {
game.settings.register(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX, {
name: "Liste des milieux proposés",
hint: "Liste des milieux proposés pour la faune&flore, séparés par des virgules",
scope: "world",
config: true,
default: MILIEUX.reduce(Misc.joining(',')),
type: String
});
game.system.rdd.environnement = new Environnement();
}
constructor() {
this.table = new CompendiumTable('faune-flore-mineraux', 'Item', ITEM_ENVIRONNEMENT_TYPES)
}
static getRarete(name = undefined) {
return RARETES.find(it => it.name == name) ?? RARETES[DEFAULT_RARETE];
}
static getFrequenceRarete(rarete, field = undefined) {
const selected = this.getRarete(rarete);
return selected[field];
}
async milieux() {
return Object.values(await this.mapMilieux());
}
async mapMilieux() {
const compendiumItems = await this.getElements(it => 1, it => ITEM_ENVIRONNEMENT_TYPES.includes(it.type));
return Misc.indexLowercase(this.getMilieuxSettings().concat(Environnement.listMilieux(compendiumItems)));
}
static listMilieux(items) {
return Misc.concat(items.map(it => Environnement.$itemToMilieux(it).filter(m => m)));
}
async autresMilieux(item) {
const mapMilieux = await this.mapMilieux();
const milieuxExistants = Environnement.$itemToMilieux(item).map(it => Grammar.toLowerCaseNoAccent(it));
return Object.keys(mapMilieux)
.filter(it => !milieuxExistants.includes(it))
.map(it => mapMilieux[it]);
}
static $itemToMilieux(item) {
return item.system.environnement.map(env => env.milieu);
}
getMilieuxSettings() {
return game.settings.get(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX).split(',').map(it => it.trim()).filter(it => it != '');
}
async findEnvironnementsLike(search) {
const milieux = await this.mapMilieux();
const searchLower = Grammar.toLowerCaseNoAccent(search);
const keys = Object.keys(milieux).filter(it => it.includes(searchLower));
if (keys.length > 1) {
const milieuExact = milieux[searchLower];
if (milieuExact) {
return [milieuExact];
}
}
return keys.map(k => milieux[k]);
}
async searchToChatMessage(milieux, typeName) {
const table = await this.buildEnvironnementTable(milieux);
await CompendiumTableHelpers.tableToChatMessage(table, 'Item', ITEM_ENVIRONNEMENT_TYPES, typeName);
return true
}
async getRandom(milieux, typeName) {
const table = await this.buildEnvironnementTable(milieux);
return await CompendiumTableHelpers.getRandom(table, 'Item', ITEM_ENVIRONNEMENT_TYPES, undefined, typeName);
}
async buildEnvironnementTable(milieux) {
const filterMilieux = item => item.system?.environnement.filter(env => milieux.includes(env.milieu));
const itemRareteEnMilieu = item => {
const raretes = filterMilieux(item);
const frequenceMax = Math.max(raretes.map(env => env.frequence));
return raretes.find(env => env.frequence == frequenceMax);
}
const itemFrequenceEnMilieu = item => itemRareteEnMilieu(item)?.frequence ?? 0;
const isPresentEnMilieu = item => itemFrequenceEnMilieu(item) > 0;
return await this.table.buildTable(itemFrequenceEnMilieu, isPresentEnMilieu);
}
async getElements(itemFrequence, filter) {
return await this.table.getContent(itemFrequence, filter);
}
}
export class EnvironmentSheetHelper {
static defaultOptions(defaultOptions) {
return mergeObject(defaultOptions, {
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }]
});
}
static setPosition(sheet, superPosition) {
const position = superPosition;
const sheetHeader = sheet.element.find(".sheet-header");
const sheetBody = sheet.element.find(".sheet-body");
sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
return position;
}
/* -------------------------------------------- */
static async getData(sheet, formData) {
return mergeObject(formData, {
milieux: await game.system.rdd.environnement.autresMilieux(sheet.item)
});
}
static activateListeners(sheet) {
if (!sheet.options.editable) return;
sheet.html.find("input.input-selection-milieu").keypress(event => {
if (event.keyCode == '13') {
EnvironmentSheetHelper.onAddMilieu(sheet, event);
}
event.stopPropagation();
})
sheet.html.find("a.milieu-add").click(event => EnvironmentSheetHelper.onAddMilieu(sheet, event));
sheet.html.find("div.environnement-milieu a.milieu-delete").click(event => EnvironmentSheetHelper.onDeleteMilieu(sheet, event));
sheet.html.find("div.environnement-milieu select.environnement-rarete").change(event => EnvironmentSheetHelper.onChange(sheet, event,
updated => EnvironmentSheetHelper.$changeRarete(sheet, event, updated)));
sheet.html.find("div.environnement-milieu input[name='environnement-frequence']").change(event => EnvironmentSheetHelper.onChange(sheet, event,
updated => EnvironmentSheetHelper.$changeFrequence(sheet, event, updated)));
}
static $changeFrequence(sheet, event, updated) {
updated.frequence = Number(sheet.html.find(event.currentTarget).val());
}
static $changeRarete(sheet, event, updated) {
const name = sheet.html.find(event.currentTarget).val();
const rarete = Environnement.getRarete(name);
updated.rarete = rarete.name;
updated.frequence = rarete.frequence;
// updated.frequence = Math.min(
// Math.max(rarete.min, updated.frequence ?? rarete.frequence),
// rarete.max);
}
static async onAddMilieu(sheet, event) {
const milieu = sheet.html.find('input.input-selection-milieu').val();
if (!milieu) {
ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${sheet.item.name}`);
return
}
const list = sheet.item.system.environnement;
const exists = list.find(it => it.milieu == milieu);
if (exists) {
ui.notifications.warn(`${sheet.item.name} a déjà une rareté ${exists.rarete} en ${milieu} (fréquence: ${exists.frequence})`);
return
}
const rarete = Environnement.getRarete();
const newList = [...list, { milieu, rarete: rarete.name, frequence: rarete.frequence }].sort(Misc.ascending(it => it.milieu))
await sheet.item.update({ 'system.environnement': newList })
}
static async onDeleteMilieu(sheet, event) {
const milieu = EnvironmentSheetHelper.$getEventMilieu(sheet, event);
if (milieu != undefined) {
const newList = sheet.item.system.environnement.filter(it => it.milieu != milieu)
.sort(Misc.ascending(it => it.milieu));
await sheet.item.update({ 'system.environnement': newList });
}
}
static async onChange(sheet, event, doMutation) {
const list = sheet.item.system.environnement;
const milieu = EnvironmentSheetHelper.$getEventMilieu(sheet, event);
const updated = list.find(it => it.milieu == milieu);
if (updated) {
doMutation(updated);
const newList = [...list.filter(it => it.milieu != milieu), updated]
.sort(Misc.ascending(it => it.milieu));
await sheet.item.update({ 'system.environnement': newList });
}
}
static $getEventMilieu(sheet, event) {
return sheet.html.find(event.currentTarget)?.parents("div.environnement-milieu").data("milieu");
}
}

View File

@@ -1,10 +1,10 @@
export class HtmlUtility{ export class HtmlUtility{
static _showControlWhen(control, condition) { static _showControlWhen(jQuerySelector, condition) {
if (condition) { if (condition) {
control.show(); jQuerySelector.show();
} }
else { else {
control.hide(); jQuerySelector.hide();
} }
} }
} }

View File

@@ -28,7 +28,7 @@ export class RdDItemArme extends Item {
switch (arme ? arme.type : '') { switch (arme ? arme.type : '') {
case 'arme': return arme; case 'arme': return arme;
case 'competencecreature': case 'competencecreature':
return RdDItemCompetenceCreature.toActionArme(arme); return RdDItemCompetenceCreature.armeNaturelle(arme);
} }
return RdDItemArme.mainsNues(); return RdDItemArme.mainsNues();
} }

View File

@@ -8,18 +8,18 @@ const xp_par_niveau = [5, 5, 5, 10, 10, 10, 10, 15, 15, 15, 15, 20, 20, 20, 20,
const niveau_max = xp_par_niveau.length - 10; const niveau_max = xp_par_niveau.length - 10;
/* -------------------------------------------- */ /* -------------------------------------------- */
const limitesArchetypes = [ const limitesArchetypes = [
{ "niveau": 0, "nombreMax": 100, "nombre": 0 }, { "niveau": 0, "nombreMax": 100, "reste": 100 },
{ "niveau": 1, "nombreMax": 10, "nombre": 0 }, { "niveau": 1, "nombreMax": 10, "reste": 10 },
{ "niveau": 2, "nombreMax": 9, "nombre": 0 }, { "niveau": 2, "nombreMax": 9, "reste": 9 },
{ "niveau": 3, "nombreMax": 8, "nombre": 0 }, { "niveau": 3, "nombreMax": 8, "reste": 8 },
{ "niveau": 4, "nombreMax": 7, "nombre": 0 }, { "niveau": 4, "nombreMax": 7, "reste": 7 },
{ "niveau": 5, "nombreMax": 6, "nombre": 0 }, { "niveau": 5, "nombreMax": 6, "reste": 6 },
{ "niveau": 6, "nombreMax": 5, "nombre": 0 }, { "niveau": 6, "nombreMax": 5, "reste": 5 },
{ "niveau": 7, "nombreMax": 4, "nombre": 0 }, { "niveau": 7, "nombreMax": 4, "reste": 4 },
{ "niveau": 8, "nombreMax": 3, "nombre": 0 }, { "niveau": 8, "nombreMax": 3, "reste": 3 },
{ "niveau": 9, "nombreMax": 2, "nombre": 0 }, { "niveau": 9, "nombreMax": 2, "reste": 2 },
{ "niveau": 10, "nombreMax": 1, "nombre": 0 }, { "niveau": 10, "nombreMax": 1, "reste": 1 },
{ "niveau": 11, "nombreMax": 1, "nombre": 0 } { "niveau": 11, "nombreMax": 1, "reste": 1 }
]; ];
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -34,13 +34,6 @@ const categorieCompetences = {
"lancer": { base: -8, label: "Lancer" } "lancer": { base: -8, label: "Lancer" }
} }
const compendiumCompetences = {
"personnage": "foundryvtt-reve-de-dragon.competences",
"creature": "foundryvtt-reve-de-dragon.competences-creatures",
"entite": "foundryvtt-reve-de-dragon.competences-entites"
};
function _buildCumulXP() { function _buildCumulXP() {
let cumulXP = { "-11": 0 }; let cumulXP = { "-11": 0 };
let cumul = 0; let cumul = 0;
@@ -55,12 +48,6 @@ function _buildCumulXP() {
const competence_xp_cumul = _buildCumulXP(); const competence_xp_cumul = _buildCumulXP();
export class RdDItemCompetence extends Item { export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static actorCompendium(actorType = undefined) {
return compendiumCompetences[actorType ?? 'personnage'];
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static getCategorieCompetences() { static getCategorieCompetences() {
return categorieCompetences; return categorieCompetences;
@@ -280,18 +267,47 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeResumeArchetype(competences) { static computeResumeArchetype(competences) {
const archetype = RdDItemCompetence.getLimitesArchetypes(); const computed = duplicate(limitesArchetypes);
competences.map(it => Math.max(0, it.system.niveau_archetype)) competences.map(it => Math.max(0, it.system.niveau_archetype))
.forEach(niveau => { .filter(n => n > 0)
archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 }; .forEach(n => {
archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1; computed[n] = computed[n] ?? { niveau: n, nombreMax: 0, reste: 0 };
computed[n].reste = computed[n].reste - 1;
}); });
return archetype; return computed.filter(it => it.reste > 0 && it.niveau > 0);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getLimitesArchetypes() { static triVisible(competences) {
return duplicate(limitesArchetypes); return competences.filter(it => it.system.isVisible)
.sort((a, b) => RdDItemCompetence.compare(a, b))
}
static $positionTri(comp) {
if (comp.name.startsWith("Survie")) {
if (comp.name.includes("Cité")) return 0;
if (comp.name.includes("Extérieur")) return 1;
return 2;
}
if (comp.system.categorie.startsWith("melee")) {
if (comp.name.includes("Corps")) return 0;
if (comp.name.includes("Dague")) return 1;
if (comp.name.includes("Esquive")) return 2;
return 3;
}
if (comp.system.categorie.startsWith("draconic")) {
if (comp.name.includes("Oniros")) return 0;
if (comp.name.includes("Hypnos")) return 1;
if (comp.name.includes("Narcos")) return 2;
if (comp.name.includes("Thanatos")) return 3;
return 4;
}
return 0;
}
static compare(a, b) {
const diff = RdDItemCompetence.$positionTri(a) - RdDItemCompetence.$positionTri(b);
return diff ? diff : a.name.localeCompare(b.name);
} }
} }

View File

@@ -1,4 +1,4 @@
import { Misc } from "./misc.js";
import { RdDCombatManager } from "./rdd-combat.js"; import { RdDCombatManager } from "./rdd-combat.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -12,12 +12,12 @@ export class RdDItemCompetenceCreature extends Item {
rollData.competence.system.categorie = "creature" rollData.competence.system.categorie = "creature"
rollData.selectedCarac = rollData.carac.carac_creature rollData.selectedCarac = rollData.carac.carac_creature
if (rollData.competence.system.iscombat) { if (rollData.competence.system.iscombat) {
rollData.arme = RdDItemCompetenceCreature.toActionArme(rollData.competence); rollData.arme = RdDItemCompetenceCreature.armeNaturelle(rollData.competence);
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static toActionArme(competencecreature) { static armeNaturelle(competencecreature) {
if (RdDItemCompetenceCreature.isCompetenceAttaque(competencecreature)) { if (RdDItemCompetenceCreature.isCompetenceAttaque(competencecreature)) {
// si c'est un Item compétence: cloner pour ne pas modifier lma compétence // si c'est un Item compétence: cloner pour ne pas modifier lma compétence
let arme = (competencecreature instanceof Item) ? competencecreature.clone(): competencecreature; let arme = (competencecreature instanceof Item) ? competencecreature.clone(): competencecreature;

View File

@@ -0,0 +1,60 @@
import { RdDItemSheet } from "./item-sheet.js";
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
import { RdDUtility } from "./rdd-utility.js";
export class RdDConteneurItemSheet extends RdDItemSheet {
static get ITEM_TYPE() { return "conteneur" };
async getData() {
const formData = await super.getData();
if (this.actor) {
this.prepareConteneurData(formData);
}
return formData;
}
activateListeners(html) {
super.activateListeners(html);
if (!this.options.editable) return;
this.html.find('.conteneur-name a').click(async event => {
RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event));
this.render(true);
});
}
/* -------------------------------------------- */
prepareConteneurData(formData) {
RdDUtility.filterEquipementParType(formData, this.actor.itemTypes);
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
}
async _onDragStart(event) {
console.log("_onDragStart", event);
if (event.target.classList.contains("entity-link")) return;
const itemId = event.srcElement?.attributes["data-item-id"].value;
const item = this.actor.items.get(itemId);
// Create drag data
const dragData = {
actorId: this.actor.id,
type: "Item",
data: item.system
};
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
}
async _onDropItem(event, dragData) {
if (this.actor) {
const dropParams = RdDSheetUtility.prepareItemDropParameters(this.item.id, this.actor, dragData, this.objetVersConteneur);
await this.actor.processDropItem(dropParams);
await this.render(true);
}
}
}

View File

@@ -0,0 +1,67 @@
import { EnvironmentSheetHelper } from "./environnement.js";
import { RdDItemSheet } from "./item-sheet.js";
import { RdDUtility } from "./rdd-utility.js";
export class RdDFauneItemSheet extends RdDItemSheet {
static get ITEM_TYPE() { return "faune" };
static get defaultOptions() {
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
}
setPosition(options = {}) {
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
}
async getData() {
const formData = await super.getData();
return await EnvironmentSheetHelper.getData(this, formData);
}
activateListeners(html) {
super.activateListeners(html);
if (!this.options.editable) return;
EnvironmentSheetHelper.activateListeners(this);
html.find("a.linked-actor-delete").click(event => this.onDeleteLinkedActor());
html.find("a.preparer-nourriture").click(event => this.preparerNourriture(event));
html.find("a.manger-nourriture").click(event => this.mangerNourriture(event));
}
async _onDropActor(event, dragData) {
console.log('faune:dropActor', event, dragData)
const linkedActor = fromUuidSync(dragData.uuid);
if (linkedActor?.pack) {
this.item.update({
'system.actor.pack': linkedActor.pack,
'system.actor.id': linkedActor._id,
'system.actor.name': linkedActor.name
});
}
else {
ui.notifications.warn(`${linkedActor.name} ne provient pas d'un compendium.
<br>Choisissez une créature du compendium pour représenter un élément de faune générique`)
}
}
async onDeleteLinkedActor() {
this.item.update({
'system.actor.pack': '',
'system.actor.id': '',
'system.actor.name': ''
});
}
async preparerNourriture(event) {
if (this.actor) {
await this.actor.preparerNourriture(this.item);
}
}
async mangerNourriture(event) {
if (this.actor) {
await this.actor.mangerNourriture(this.item);
}
}
}

View File

@@ -0,0 +1,25 @@
import { EnvironmentSheetHelper } from "./environnement.js";
import { RdDItemSheet } from "./item-sheet.js";
export class RdDHerbeItemSheet extends RdDItemSheet {
static get ITEM_TYPE() { return "herbe" };
static get defaultOptions() {
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
}
setPosition(options = {}) {
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
}
async getData() {
const formData = await super.getData();
return await EnvironmentSheetHelper.getData(this, formData);
}
activateListeners(html) {
super.activateListeners(html);
EnvironmentSheetHelper.activateListeners(this);
}
}

View File

@@ -0,0 +1,25 @@
import { EnvironmentSheetHelper } from "./environnement.js";
import { RdDItemSheet } from "./item-sheet.js";
export class RdDIngredientItemSheet extends RdDItemSheet {
static get ITEM_TYPE() { return "ingredient" };
static get defaultOptions() {
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
}
setPosition(options = {}) {
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
}
async getData() {
const formData = await super.getData();
return await EnvironmentSheetHelper.getData(this, formData);
}
activateListeners(html) {
super.activateListeners(html);
EnvironmentSheetHelper.activateListeners(this);
}
}

View File

@@ -2,27 +2,28 @@ import { Misc } from "./misc.js";
import { LOG_HEAD } from "./constants.js"; import { LOG_HEAD } from "./constants.js";
const MONNAIE_ETAIN = { const MONNAIE_ETAIN = {
name: "Etain (1 denier)", type: 'monnaie', name: "Denier (étain)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp", img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
system: { quantite: 0, valeur_deniers: 1, encombrement: 0.001, description: "" } system: { quantite: 0, cout: 0.01, encombrement: 0.001, description: "" }
}; };
const MONNAIE_BRONZE = { const MONNAIE_BRONZE = {
name: "Bronze (10 deniers)", type: 'monnaie', name: "Sou (bronze)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp", img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp",
system: { quantite: 0, valeur_deniers: 10, encombrement: 0.002, description: "" } system: { quantite: 0, cout: 0.10, encombrement: 0.002, description: "" }
}; };
const MONNAIE_ARGENT = { const MONNAIE_ARGENT = {
name: "Argent (1 sol)", type: 'monnaie', name: "Sol (argent)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp", img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp",
system: { quantite: 0, valeur_deniers: 100, encombrement: 0.003, description: "" } system: { quantite: 0, cout: 1, encombrement: 0.003, description: "" }
}; };
const MONNAIE_OR = { const MONNAIE_OR = {
name: "Or (10 sols)", type: 'monnaie', name: "Dreagon (or)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp", img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
system: { quantite: 0, valeur_deniers: 1000, encombrement: 0.004, description: "" } system: { quantite: 0, cout: 10, encombrement: 0.004, description: "" }
}; };
const MONNAIES_STANDARD = [MONNAIE_ETAIN, MONNAIE_BRONZE, MONNAIE_ARGENT, MONNAIE_OR]; const MONNAIES_STANDARD = [MONNAIE_ETAIN, MONNAIE_BRONZE, MONNAIE_ARGENT, MONNAIE_OR];
const VALEUR_DENIERS = sols => Math.max(Math.floor((sols ?? 0) * 100), 0);
export class Monnaie { export class Monnaie {
@@ -32,7 +33,7 @@ export class Monnaie {
static monnaiesManquantes(actor) { static monnaiesManquantes(actor) {
const disponibles = actor.itemTypes['monnaie']; const disponibles = actor.itemTypes['monnaie'];
const manquantes = MONNAIES_STANDARD.filter(standard => !disponibles.find(disponible => Monnaie.deValeur(disponible, standard.system?.valeur_deniers))); const manquantes = MONNAIES_STANDARD.filter(standard => !disponibles.find(disponible => Monnaie.deValeur(disponible, standard.system?.cout)));
if (manquantes.length > 0) { if (manquantes.length > 0) {
console.error(`${LOG_HEAD} monnaiesManquantes pour ${actor.name}`, manquantes, ' avec monnaies', disponibles, MONNAIES_STANDARD); console.error(`${LOG_HEAD} monnaiesManquantes pour ${actor.name}`, manquantes, ' avec monnaies', disponibles, MONNAIES_STANDARD);
} }
@@ -40,15 +41,11 @@ export class Monnaie {
} }
static deValeur(monnaie, valeur) { static deValeur(monnaie, valeur) {
return valeur == monnaie.system.valeur_deniers return VALEUR_DENIERS(valeur) == VALEUR_DENIERS(monnaie.system.cout)
} }
static arrondiDeniers(sols) { static triValeurEntiere() {
return Number(sols).toFixed(2); return Misc.ascending(item => VALEUR_DENIERS(item.system.cout))
}
static triValeurDenier() {
return Misc.ascending(item => item.system.valeur_deniers)
} }
static async creerMonnaiesStandard(actor) { static async creerMonnaiesStandard(actor) {
@@ -65,29 +62,57 @@ export class Monnaie {
return deniers; return deniers;
} }
static async optimiser(actor, fortune) { static getFortune(actor) {
let reste = fortune; if (actor) {
Monnaie.validerMonnaies(actor);
return actor.itemTypes['monnaie']
.map(m => Number(m.system.cout) * Number(m.system.quantite))
.reduce(Misc.sum(), 0);
}
return 0;
}
static getFortuneSolsDeniers(actor) {
const fortune = Monnaie.getFortune(actor);
return {
sols: Math.floor(fortune),
deniers: Math.round(100 * (fortune - Math.floor(fortune)))
};
}
static async optimiserFortune(actor, fortune) {
let resteEnDeniers = Math.round(fortune * 100);
let monnaies = actor.itemTypes['monnaie']; let monnaies = actor.itemTypes['monnaie'];
let updates = []; let updates = [];
let parValeur = Misc.classifyFirst(monnaies, it => it.system.valeur_deniers); Monnaie.validerMonnaies(actor);
for (let valeur of [1000, 100, 10, 1]) {
const itemPiece = parValeur[valeur]; let parValeur = Misc.classifyFirst(monnaies, it => VALEUR_DENIERS(it.system.cout));
for (let valeurDeniers of [1000, 100, 10, 1]) {
const itemPiece = parValeur[valeurDeniers];
if (itemPiece) { if (itemPiece) {
const quantite = Math.floor(reste / valeur); const quantite = Math.floor(resteEnDeniers / valeurDeniers);
if (quantite != itemPiece.system.quantite) { if (quantite != itemPiece.system.quantite) {
updates.push({ _id: parValeur[valeur].id, 'system.quantite': quantite }); updates.push({ _id: parValeur[valeurDeniers].id, 'system.quantite': quantite });
} }
reste -= quantite*valeur; resteEnDeniers -= quantite * valeurDeniers;
} }
} }
console.log('Monnaie.optimiser', actor.name, 'total', fortune, 'parValeur', parValeur, 'updates', updates, 'reste', reste); console.log('Monnaie.optimiserFortune', actor.name, 'total', fortune, 'parValeur', parValeur, 'updates', updates, 'reste', resteEnDeniers);
if (updates.length > 0) { if (updates.length > 0) {
await actor.updateEmbeddedDocuments('Item', updates); await actor.updateEmbeddedDocuments('Item', updates);
} }
if (reste > 0){ if (resteEnDeniers > 0) {
// créer le reste en deniers fortune en deniers // créer le reste en deniers fortune en deniers
await Monnaie.creerMonnaiesDeniers(actor, reste); await Monnaie.creerMonnaiesDeniers(actor, resteEnDeniers);
} }
} }
static validerMonnaies(actor) {
actor.itemTypes['monnaie'].filter(it => VALEUR_DENIERS(it.system.cout) == 0)
.map(it => `La monnaie ${it.name} de l'acteur ${actor.name} a une valeur de 0!`)
.forEach(message => {
ui.notifications.warn(message);
console.warn(message);
});
}
} }

View File

@@ -1,29 +1,16 @@
import { RdDRencontre } from "./item-rencontre.js"; import { RdDRencontre } from "./item-rencontre.js";
import { RdDItemSheet } from "./item-sheet.js";
/** export class RdDRencontreItemSheet extends RdDItemSheet {
* Item sheet pour configurer les rencontres
* @extends {ItemSheet} static get ITEM_TYPE() { return "rencontre" };
*/
export class RdDRencontreItemSheet extends ItemSheet {
/** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return mergeObject(super.defaultOptions, {
classes: ["rdd", "sheet", "item"],
template: "systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html",
width: 500,
height: 500,
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }] tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }]
}); });
} }
/* -------------------------------------------- */
_getHeaderButtons() {
let buttons = super._getHeaderButtons();
buttons.unshift({ class: "post", icon: "fas fa-comment", onclick: ev => this.item.postItem() });
return buttons;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
setPosition(options = {}) { setPosition(options = {}) {
@@ -34,18 +21,10 @@ export class RdDRencontreItemSheet extends ItemSheet {
return position; return position;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
const formData = duplicate(this.item); const formData = await super.getData();
mergeObject(formData, { mergeObject(formData, {
title: formData.name,
isGM: game.user.isGM,
owner: this.actor?.isOwner,
isOwned: this.actor ? true : false,
actorId: this.actor?.id,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
effets: { effets: {
succes: { succes: {
liste: RdDRencontre.getEffetsSucces(), liste: RdDRencontre.getEffetsSucces(),
@@ -65,15 +44,15 @@ export class RdDRencontreItemSheet extends ItemSheet {
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
if (!this.options.editable) return; if (!this.options.editable) return;
html.find("a.effet-add").click(event => this.onAddEffet(event)); this.html.find("a.effet-add").click(event => this.onAddEffet(event));
html.find("a.effet-delete").click(event => this.onDeleteEffet(event)); this.html.find("a.effet-delete").click(event => this.onDeleteEffet(event));
} }
async onAddEffet(event) { async onAddEffet(event) {
const resultat = $(event.currentTarget)?.data("effet-resultat"); const resultat = this.html.find(event.currentTarget)?.data("effet-resultat");
const keyEffets = `system.${resultat}.effets`; const keyEffets = `system.${resultat}.effets`;
const code = $(event.currentTarget)?.data("effet-code"); const code = this.html.find(event.currentTarget)?.data("effet-code");
const liste = RdDRencontre.getListeEffets(this.item, resultat); const liste = RdDRencontre.getListeEffets(this.item, resultat);
liste.push(code); liste.push(code);
@@ -81,10 +60,10 @@ export class RdDRencontreItemSheet extends ItemSheet {
} }
async onDeleteEffet(event) { async onDeleteEffet(event) {
const resultat = $(event.currentTarget)?.data("effet-resultat"); const resultat = this.html.find(event.currentTarget)?.data("effet-resultat");
const keyEffets = `system.${resultat}.effets`; const keyEffets = `system.${resultat}.effets`;
const pos = $(event.currentTarget)?.data("effet-pos"); const pos = this.html.find(event.currentTarget)?.data("effet-pos");
const liste = RdDRencontre.getListeEffets(this.item, resultat); const liste = RdDRencontre.getListeEffets(this.item, resultat);
liste.splice(pos, 1); liste.splice(pos, 1);
@@ -96,13 +75,4 @@ export class RdDRencontreItemSheet extends ItemSheet {
updates[key] = liste; updates[key] = liste;
this.item.update(updates); this.item.update(updates);
} }
get template() {
/* -------------------------------------------- */
return `systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html`;
}
get title() {
return `Rencontre: ${this.object.name}`;
}
} }

View File

@@ -0,0 +1,81 @@
import { RdDItemSheet } from "./item-sheet.js";
import { Misc } from "./misc.js";
import { RdDUtility } from "./rdd-utility.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
import { DialogItemAchat } from "./dialog-item-achat.js";
import { RdDItem } from "./item.js";
import { RdDItemService } from "./item-service.js";
export class RdDServiceItemSheet extends RdDItemSheet {
static get ITEM_TYPE() { return "service" };
async getData() {
const formData = await super.getData();
formData.disabled = formData.isGM || formData.isOwned ? '' : 'disabled';
return formData;
}
activateListeners(html) {
super.activateListeners(html);
this.html.find('a.rdd-world-content-link').click(async event => {
const itemRef = this.getItemRef(event);
game.items.get(itemRef.id)?.sheet.render(true)
});
this.html.find('a.sub-item-acheter').click(async event => {
const subItem = this.item.findRefItem(this.getItemRef(event));
await this.item.acheter(RdDUtility.getSelectedActor(), subItem);
});
if (!this.options.editable) return;
this.html.find('a.sub-item-vendre').click(async event => {
const subItem = this.item.findRefItem(this.getItemRef(event));
await this.item.vendre(subItem);
});
this.html.find('a.sub-item-delete').click(async event => {
await this.item.removeRefItem(this.getItemRef(event));
});
this.html.find('a.sub-item-quantite-moins').click(async event => await this.item.increaseRefItemQuantite(this.getItemRef(event), -1))
this.html.find('a.sub-item-quantite-plus').click(async event => await this.item.increaseRefItemQuantite(this.getItemRef(event), 1))
this.html.find('input.sub-item-quantite').change(async event => {
const newQuantite = Math.max(0, Number.parseInt(this.html.find(event.currentTarget).val()));
await this.item.updateRefItem(this.getItemRef(event), it => it.system.quantite = newQuantite);
})
this.html.find('input.sub-item-cout').change(async event => {
const newCout = Math.max(0, Number(this.html.find(event.currentTarget).val()));
await this.item.updateRefItem(this.getItemRef(event), it => it.system.cout = newCout);
})
this.html.find('a.sub-item-info-add').click(__ =>
ui.notifications.info(`Utiliser le glisser-déposer pour ajouter des objets depuis un compendium ou les objets du monde`)
);
}
async _onDropItem(event, dragData) {
let linkedItem = fromUuidSync(dragData.uuid);
const existing = this.item.system.items.find(it => it.pack == linkedItem.pack && it.id == linkedItem.id && it.type == linkedItem.type);
if (existing) {
ui.notifications.warn(`${this.item.name} contient déjà un ${existing.name}`);
return;
}
if (linkedItem.pack) {
linkedItem = await SystemCompendiums.loadDocument(linkedItem);
}
if (linkedItem.isInventaire()) {
await this.item.addRefItem(RdDItemService.createSubItem(linkedItem));
}
else {
ui.notifications.warn(`${this.item.name} ne peut pas proposer à la vente de ${Misc.typeName('Item', linkedItem.type)}: ${linkedItem.name}`);
}
}
getItemRef(event) {
const itemRow = this.html.find(event.currentTarget)?.parents('.item.service-item');
return { id: itemRow?.data("item-id"), pack: itemRow?.data("pack") ?? undefined }
}
}

140
module/item-service.js Normal file
View File

@@ -0,0 +1,140 @@
import { DialogItemAchat } from "./dialog-item-achat.js";
import { RdDItem } from "./item.js";
import { Misc } from "./misc.js";
export class RdDItemService extends RdDItem {
static get defaultIcon() {
return "systems/foundryvtt-reve-de-dragon/icons/items/services.webp";
}
/** @override*/
getUserLevel(user) {
const level = super.getUserLevel(user);
if (level == CONST.DOCUMENT_OWNERSHIP_LEVELS.NONE) {
// si quelqu'un a accès au lien d'un service, il peut le voir
return CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED;
}
return level;
}
isService() { return true; }
getChatItemTemplate() { return 'systems/foundryvtt-reve-de-dragon/templates/post-item-service.html'; }
getProprietes() { return []; }
getServiceItem(itemRef) {
if (this.isService()) {
return this.system.items.find(it => it.id == itemRef.id && it.pack == itemRef.pack);
}
return undefined;
}
getQuantiteDisponible(itemRef, max) {
if (this.system.illimite) {
return max;
}
const subItem = this.getServiceItem(itemRef);
return subItem?.system.quantite ?? 0;
}
async venteRefItem(ref, quantite, cout) {
if (this.actor) {
await this.actor.ajouterSols(cout);
}
await this.increaseRefItemQuantite(ref, -quantite);
}
async vendre(subItem) {
const item = await RdDItem.getCorrespondingItem(subItem);
const quantiteMax = this.system.illimite ? undefined : subItem.system.quantite;
await item.proposerVente({ service: this, quantiteMax });
}
async acheter(acheteur, subItem) {
if (!acheteur) {
ui.notifications.warn(`Pas d'acheteur sélectionné`);
return;
}
const nbLots = this.system.illimite ? 1 : subItem.system.quantite;
if (nbLots <= 0) {
ui.notifications.warn(`${this.name} n'a plus de ${subItem.name} en vente`);
return;
}
await DialogItemAchat.onAcheter({
item: await RdDItem.getCorrespondingItem(subItem),
acheteur,
service: this,
quantiteIllimite: this.system.illimite,
nbLots,
tailleLot: 1,
prixLot: subItem.system.cout
});
}
static createSubItem(linkedItem) {
return {
id: linkedItem.id,
pack: linkedItem.pack,
name: linkedItem.name,
img: linkedItem.img,
system: {
quantite: 1,
cout: linkedItem.system.cout ?? 0
}
};
}
static matchRefItem({ id, pack }) {
return it => it.id == id && (pack ? (it.pack == pack) : (!it.pack));
}
findRefItem(ref) {
return this.system.items.find(RdDItemService.matchRefItem(ref));
}
async increaseRefItemQuantite(ref, quantite) {
await this.updateRefItem(ref,
it => it.system.quantite = Math.max(0, it.system.quantite + quantite)
);
}
async updateRefItem(ref, update = it => { }) {
await this.updateRefItems(RdDItemService.matchRefItem(ref), update);
}
async addRefItem(newItem) {
if (!newItem.id) {
ui.notifications.warn(`${newItem?.name ?? '??'} n'a pas d'identifiant`);
return;
}
if (this.system.items.find(RdDItemService.matchRefItem(newItem))) {
ui.notifications.warn(`${newItem?.name ?? newItem.id} est déjà présent ici`);
return;
}
await this.setRefItems([...this.system.items, newItem]);
}
async removeRefItem(ref) {
await this.removeRefItems(RdDItemService.matchRefItem(ref));
}
async removeRefItems(matcher = it => false) {
await this.setRefItems(this.system.items.filter(it => !matcher(it)));
}
async updateRefItems(matcher = it => false, update = it => { }) {
const updatedList = this.system.items.map(it => {
if (matcher(it)) {
update(it);
}
return it;
});
await this.setRefItems(updatedList);
}
async setRefItems(newItems) {
await this.update({ 'system.items': newItems.sort(Misc.ascending(it => it.type + ':' + it.name)) });
}
}

View File

@@ -8,30 +8,55 @@ import { HtmlUtility } from "./html-utility.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js"; import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { SYSTEM_RDD } from "./constants.js"; import { SYSTEM_RDD } from "./constants.js";
import { RdDSheetUtility } from "./rdd-sheet-utility.js"; import { RdDSheetUtility } from "./rdd-sheet-utility.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
import { Misc } from "./misc.js";
/** /**
* Extend the basic ItemSheet with some very simple modifications * Extend the basic ItemSheet for RdD specific items
* @extends {ItemSheet}
*/ */
export class RdDItemSheet extends ItemSheet { export class RdDItemSheet extends ItemSheet {
static get ITEM_TYPE() {
return undefined
}
static defaultTemplate(type) {
return type ?
`systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html` :
"systems/foundryvtt-reve-de-dragon/templates/item-sheet.html";
}
static register(sheetClass) {
Items.registerSheet(SYSTEM_RDD, sheetClass, {
label: Misc.typeName('Item', sheetClass.ITEM_TYPE),
types: [sheetClass.ITEM_TYPE],
makeDefault: true
})
}
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return mergeObject(super.defaultOptions, {
classes: [SYSTEM_RDD, "sheet", "item"], classes: [SYSTEM_RDD, "sheet", "item"],
template: "systems/foundryvtt-reve-de-dragon/templates/item-sheet.html", template: RdDItemSheet.defaultTemplate(RdDItemSheet.ITEM_TYPE),
width: 550, width: 550,
height: 550 height: 550
}); });
} }
/* -------------------------------------------- */
get template() {
return RdDItemSheet.defaultTemplate(this.item.type);
}
get title() {
return `${Misc.typeName('Item', this.item.type)}: ${this.item.name}`;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
_getHeaderButtons() { _getHeaderButtons() {
let buttons = super._getHeaderButtons(); let buttons = super._getHeaderButtons();
// Add "Post to chat" button if (this.item.isInventaire() && this.item.isVideOuNonConteneur()) {
// We previously restricted this to GM and editable items only. If you ever find this comment because it broke something: eh, sorry!
if ("cout" in this.item.system && this.item.isVideOuNonConteneur()) {
buttons.unshift({ buttons.unshift({
class: "vendre", class: "vendre",
icon: "fas fa-comments-dollar", icon: "fas fa-comments-dollar",
@@ -68,32 +93,28 @@ export class RdDItemSheet extends ItemSheet {
system: this.item.system, system: this.item.system,
isGM: game.user.isGM, isGM: game.user.isGM,
actorId: this.actor?.id, actorId: this.actor?.id,
isOwned: this.actor ? true : false,
owner: this.item.isOwner, owner: this.item.isOwner,
editable: this.isEditable, editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked", cssClass: this.isEditable ? "editable" : "locked",
isSoins: false, isSoins: false,
description: await TextEditor.enrichHTML(this.object.system.description, {async: true}), description: await TextEditor.enrichHTML(this.item.system.description, { async: true }),
descriptionmj: await TextEditor.enrichHTML(this.object.system.descriptionmj, {async: true}) descriptionmj: await TextEditor.enrichHTML(this.item.system.descriptionmj, { async: true }),
isComestible: this.item.isComestible()
}
if (this.actor) {
formData.isOwned = true;
if (this.item.type == 'conteneur') {
this.prepareConteneurData(formData);
}
} }
const competences = await SystemCompendiums.getCompetences(this.actor?.type);
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences() formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences()
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') { if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
formData.caracList = duplicate(game.system.model.Actor.personnage.carac) formData.caracList = duplicate(game.system.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve) formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve)
formData.competences = await RdDUtility.loadItems(it => it.isCompetencePersonnage(), RdDItemCompetence.actorCompendium(this.actor?.type)) formData.competences = competences;
} }
if (this.item.type == 'arme') { if (this.item.type == 'arme') {
formData.competences = await RdDUtility.loadItems(it => RdDItemCompetence.isCompetenceArme(it), RdDItemCompetence.actorCompendium(this.actor?.type)) formData.competences = competences.filter(it => RdDItemCompetence.isCompetenceArme(it));
} }
if (['sort', 'sortreserve'].includes(this.item.type)) { if (['sort', 'sortreserve'].includes(this.item.type)) {
formData.competences = await RdDUtility.loadItems(it => RdDItemCompetence.isDraconic(it), RdDItemCompetence.actorCompendium(this.actor?.type)) formData.competences = competences.filter(it => RdDItemCompetence.isDraconic(it));
} }
if (this.item.type == 'recettecuisine') { if (this.item.type == 'recettecuisine') {
formData.ingredients = await TextEditor.enrichHTML(this.object.system.ingredients, { async: true }) formData.ingredients = await TextEditor.enrichHTML(this.object.system.ingredients, { async: true })
@@ -132,106 +153,72 @@ export class RdDItemSheet extends ItemSheet {
return formData; return formData;
} }
/* -------------------------------------------- */
prepareConteneurData(formData) {
RdDUtility.filterEquipementParType(formData, this.actor.itemTypes);
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = html;
if (this.item.type == 'conteneur') { HtmlUtility._showControlWhen(this.html.find(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.item.isOwned);
this.form.ondragstart = (event) => this._onDragStart(event); HtmlUtility._showControlWhen(this.html.find(".item-magique"), this.item.isMagique());
this.form.ondrop = (event) => this._onDrop(event);
}
let itemSheetDialog = this;
HtmlUtility._showControlWhen($(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.item.isOwned);
HtmlUtility._showControlWhen($(".item-magique"), this.item.isMagique());
// Everything below here is only needed if the sheet is editable // Everything below here is only needed if the sheet is editable
if (!this.options.editable) return; if (!this.options.editable) return;
// Select competence categorie this.form.ondragstart = (event) => this._onDragStart(event);
html.find(".categorie").change(event => this._onSelectCategorie(event)); this.form.ondrop = (event) => this._onDrop(event);
html.find('.sheet-competence-xp').change((event) => { // Select competence categorie
this.html.find(".categorie").change(event => this._onSelectCategorie(event));
this.html.find('.sheet-competence-xp').change((event) => {
if (this.item.isCompetencePersonnage()) { if (this.item.isCompetencePersonnage()) {
RdDUtility.checkThanatosXP(this.item.name); RdDUtility.checkThanatosXP(this.item.name);
} }
}); });
this.html.find(".item-cout input[name='system.cout']").change(event => {
if (this.item.isMonnaie()) {
const value = event.currentTarget.value;
if (Number(value) == 0) {
ui.notifications.error(`${this.actor?.name ?? 'Monnaie'}: La monnaie ${this.item.name} a maintenant une valeur de 0, et ne peut plus être utilisée pour payer!`)
}
}
})
html.find('.enchanteDate').change((event) => { this.html.find('.enchanteDate').change((event) => {
let jour = Number($('#jourMois').val()); let jour = Number(this.html.find('[name="splitDate.day"]').val());
let mois = $('#nomMois').val(); let mois = this.html.find('[name="splitDate.month"]').val();
this.dateUpdated = game.system.rdd.calendrier.getIndexFromDate(jour, mois); this.dateUpdated = game.system.rdd.calendrier.getIndexFromDate(jour, mois);
}); });
html.find('.creer-tache-livre').click((event) => { this.html.find('.creer-tache-livre').click((event) => this._getEventActor(event).creerTacheDepuisLivre(this.item));
let actorId = event.currentTarget.attributes['data-actor-id'].value; this.html.find('.consommer-potion').click((event) => this._getEventActor(event).consommerPotion(this.item));
let actor = game.actors.get(actorId); this.html.find('.creer-potion-base').click((event) => this._getEventActor(event).dialogFabriquerPotion(this.item));
actor.creerTacheDepuisLivre(this.item);
});
html.find('.consommer-potion').click((event) => {
let actorId = event.currentTarget.attributes['data-actor-id'].value;
let actor = game.actors.get(actorId);
actor.consommerPotion(this.item);
});
html.find('.creer-potion-base').click((event) => {
let actorId = event.currentTarget.attributes['data-actor-id'].value;
let actor = game.actors.get(actorId);
actor.dialogFabriquerPotion(this.item);
});
html.find('.alchimie-tache a').click((event) => { this.html.find('.alchimie-tache a').click((event) => {
let actorId = event.currentTarget.attributes['data-actor-id'].value; let actor = this._getEventActor(event);
if (actor) {
let recetteId = event.currentTarget.attributes['data-recette-id'].value; let recetteId = event.currentTarget.attributes['data-recette-id'].value;
let tacheName = event.currentTarget.attributes['data-alchimie-tache'].value; let tacheName = event.currentTarget.attributes['data-alchimie-tache'].value;
let tacheData = event.currentTarget.attributes['data-alchimie-data'].value; let tacheData = event.currentTarget.attributes['data-alchimie-data'].value;
let actor = game.actors.get(actorId);
if (actor) {
actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData); actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData);
} else { } else {
ui.notifications.info("Impossible trouver un acteur pour réaliser cette tache Alchimique."); ui.notifications.info("Impossible trouver un acteur pour réaliser cette tache Alchimique.");
} }
}); });
html.find('.item-split').click(async event => { this.html.find('.item-split').click(async event => RdDSheetUtility.splitItem(RdDSheetUtility.getItem(event, this.actor), this.actor, async () => this.render(true)));
const item = RdDSheetUtility.getItem(event, this.actor); this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true));
await RdDSheetUtility.splitItem(item, this.actor, async () => itemSheetDialog.render(true)); this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, RdDSheetUtility.getItem(event, this.actor)));
}); this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente());
html.find('.item-edit').click(async event => { this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItem());
const item = RdDSheetUtility.getItem(event, this.actor); this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor, async () => this.render(true)));
item.sheet.render(true); }
});
html.find('.item-delete').click(async event => { _getEventActor(event) {
const li = RdDSheetUtility.getEventElement(event); let actorId = event.currentTarget.attributes['data-actor-id'].value;
const item = this.actor.getObjet(li.data("item-id")); let actor = game.actors.get(actorId);
RdDUtility.confirmerSuppressionItem(this, item, li); return actor;
});
html.find('.item-vendre').click(async event => {
const item = RdDSheetUtility.getItem(event, this.actor);
item?.proposerVente();
});
html.find('.item-montrer').click(async event => {
const item = RdDSheetUtility.getItem(event, this.actor);
item?.postItem();
});
html.find('.item-action').click(async event => {
const item = RdDSheetUtility.getItem(event, this.actor);
this.actor.actionItem(item, async () => itemSheetDialog.render(true));
});
html.find('.conteneur-name a').click(async event => {
RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event));
this.render(true);
});
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -241,70 +228,56 @@ export class RdDItemSheet extends ItemSheet {
if (this.item.isCompetence()) { if (this.item.isCompetence()) {
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value); let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
this.item.system.base = level; this.item.system.base = level;
$("#base").val(level); this.html.find('[name="system.base"]').val(level);
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
get template() {
let type = this.item.type
return `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html`;
}
/* -------------------------------------------- */
/** @override */ /** @override */
_updateObject(event, formData) { _updateObject(event, formData) {
if (this.item.type == 'sort') {
// Données de bonus de cases ? // Données de bonus de cases ?
formData['system.bonuscase'] = RdDItemSort.buildBonusCaseStringFromFormData(formData.bonusValue, formData.caseValue); formData['system.bonuscase'] = RdDItemSort.buildBonusCaseStringFromFormData(formData.bonusValue, formData.caseValue);
}
return this.item.update(formData); return this.item.update(formData);
} }
/* -------------------------------------------- */
async _onDragStart(event) { async _onDragStart(event) {
console.log("_onDragStart", event);
if (event.target.classList.contains("entity-link")) return;
const itemId = event.srcElement?.attributes["data-item-id"].value;
const item = this.actor.items.get(itemId);
// Create drag data
const dragData = {
actorId: this.actor.id,
type: "Item",
data: item.system
};
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
} }
async _onDrop(event) { async _onDrop(event) {
// Try to extract the dragData // Try to extract the dragData
let dragData; let dragData = RdDItemSheet.$extractDragData(event);
try { if (!dragData) return false;
dragData = JSON.parse(event.dataTransfer.getData('text/plain'));
} catch (err) {
return false;
}
const allowed = Hooks.call("dropActorSheetData", this.actor, this, dragData); const allowed = Hooks.call("dropActorSheetData", this.actor, this, dragData);
if (allowed === false) return; if (allowed === false) return false;
// Handle different dragData types // Handle different dragData types
switch (dragData.type) { switch (dragData.type) {
case "Item": case "Item":
return this._onDropItem(event, dragData); return this._onDropItem(event, dragData);
case "Actor":
return this._onDropActor(event, dragData);
} }
return super._onDrop(event); return super._onDrop(event);
} }
/* -------------------------------------------- */ static $extractDragData(event) {
try {
const eventData = event?.dataTransfer?.getData('text/plain');
if (eventData) {
return JSON.parse(eventData);
}
} catch (err) { }
return undefined;
}
async _onDropItem(event, dragData) { async _onDropItem(event, dragData) {
if (this.actor) {
const dropParams = RdDSheetUtility.prepareItemDropParameters(this.item.id, this.actor.id, dragData, this.objetVersConteneur);
await this.actor.processDropItem(dropParams);
await this.render(true);
}
} }
async _onDropActor(event, dragData) {
}
} }

View File

@@ -1,29 +1,14 @@
import { SYSTEM_RDD } from "./constants.js"; import { RdDItemSheet } from "./item-sheet.js";
import { RdDItemSigneDraconique } from "./item-signedraconique.js"; import { RdDItemSigneDraconique } from "./item-signedraconique.js";
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
/** /**
* Item sheet pour signes draconiques * Item sheet pour signes draconiques
* @extends {ItemSheet} * @extends {RdDItemSheet}
*/ */
export class RdDSigneDraconiqueItemSheet extends ItemSheet { export class RdDSigneDraconiqueItemSheet extends RdDItemSheet {
/** @override */ static get ITEM_TYPE() { return "signedraconique" }
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: [SYSTEM_RDD, "sheet", "item"],
template: "systems/foundryvtt-reve-de-dragon/templates/item-signedraconique-sheet.html",
width: 550,
height: 550
});
}
/* -------------------------------------------- */
_getHeaderButtons() {
let buttons = super._getHeaderButtons();
buttons.unshift({ class: "post", icon: "fas fa-comment", onclick: ev => this.item.postItem() });
return buttons;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
@@ -38,18 +23,9 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
const formData = duplicate(this.item); const formData = await super.getData();
this.tmrs = TMRUtility.buildSelectionTypesTMR(this.item.system.typesTMR); this.tmrs = TMRUtility.buildSelectionTypesTMR(this.item.system.typesTMR);
mergeObject(formData, { formData.tmrs = this.tmrs;
tmrs: this.tmrs,
title: formData.name,
isGM: game.user.isGM,
owner: this.actor?.isOwner,
isOwned: this.actor ? true : false,
actorId: this.actor?.id,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
});
return formData; return formData;
} }
@@ -61,12 +37,13 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet {
if (!this.options.editable) return; if (!this.options.editable) return;
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire()); html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
html.find("input.select-tmr").change((event) => this.onSelectTmr(event)); html.find("input.select-tmr").change(event => this.onSelectTmr(event));
html.find(".signe-xp-sort").change((event) => this.onValeurXpSort(event.currentTarget.attributes['data-typereussite']?.value, Number(event.currentTarget.value))); html.find(".signe-xp-sort").change(event => this.onValeurXpSort(event.currentTarget.attributes['data-typereussite']?.value, Number(event.currentTarget.value)));
} }
async setSigneAleatoire() { async setSigneAleatoire() {
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique(); const newSigne = await RdDItemSigneDraconique.randomSigneDraconique();
newSigne.name = this.item.name;
this.item.update(newSigne); this.item.update(newSigne);
} }
@@ -88,12 +65,4 @@ export class RdDSigneDraconiqueItemSheet extends ItemSheet {
await this.item.update({ 'system.valeur': newValeur }); await this.item.update({ 'system.valeur': newValeur });
} }
/* -------------------------------------------- */
get template() {
return `systems/foundryvtt-reve-de-dragon/templates/item-signedraconique-sheet.html`;
}
get title() {
return `Signe draconique: ${this.object.name}`;
}
} }

View File

@@ -1,15 +1,18 @@
import { DialogItemVente } from "./dialog-item-vente.js"; import { DialogItemVente } from "./dialog-item-vente.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { RdDHerbes } from "./rdd-herbes.js"; import { RdDHerbes } from "./rdd-herbes.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
const typesObjetsEquipement = [ const typesObjetsInventaire = [
"arme", "arme",
"armure", "armure",
"conteneur", "conteneur",
"gemme", "gemme",
"herbe", "herbe",
"ingredient", "ingredient",
"faune",
"livre", "livre",
"monnaie", "monnaie",
"munition", "munition",
@@ -35,6 +38,7 @@ export const defaultItemImg = {
conteneur: "systems/foundryvtt-reve-de-dragon/icons/objets/sac_a_dos.webp", conteneur: "systems/foundryvtt-reve-de-dragon/icons/objets/sac_a_dos.webp",
sort: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp", sort: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
herbe: "systems/foundryvtt-reve-de-dragon/icons/botanique/Endorlotte.webp", herbe: "systems/foundryvtt-reve-de-dragon/icons/botanique/Endorlotte.webp",
faune: "systems/foundryvtt-reve-de-dragon/icons/faune/rongeur.webp",
ingredient: "systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp", ingredient: "systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp",
livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp", livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp",
potion: "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp", potion: "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp",
@@ -54,39 +58,100 @@ export const defaultItemImg = {
poison: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp", poison: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp",
oeuvre: "systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp", oeuvre: "systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp",
nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp", nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
service: "systems/foundryvtt-reve-de-dragon/icons/items/services.webp",
signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp", signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp",
gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp", gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp",
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp", possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp", sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp", extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp",
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDItem extends Item { export class RdDItem extends Item {
constructor(itemData, context) { static getDefaultImg(itemType) {
if (!itemData.img) { return game.system.rdd.itemClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
itemData.img = defaultItemImg[itemData.type];
}
super(itemData, context);
} }
static getTypesObjetsEquipement() { static isFieldInventaireModifiable(type, field) {
return typesObjetsEquipement switch (field) {
case 'quantite':
if (['conteneur'].includes(type)) {
return false;
}
break;
case 'cout':
if (['monnaie'].includes(type)) {
return game.user.isGM;
}
break;
}
return true;
}
static async getCorrespondingItem(itemRef) {
if (itemRef.pack) {
return await SystemCompendiums.loadDocument(itemRef)
}
return game.items.get(itemRef.id ?? itemRef._id);
}
static getItemTypesInventaire() {
return typesObjetsInventaire
} }
static getTypesOeuvres() { static getTypesOeuvres() {
return typesObjetsOeuvres return typesObjetsOeuvres
} }
isCompetencePersonnage() { constructor(docData, context = {}) {
return this.type == 'competence' if (!context.rdd?.ready) {
mergeObject(context, { rdd: { ready: true } });
const ItemConstructor = game.system.rdd.itemClasses[docData.type];
if (ItemConstructor) {
if (!docData.img) {
docData.img = ItemConstructor.defaultIcon;
} }
return new ItemConstructor(docData, context);
}
}
if (!docData.img) {
docData.img = RdDItem.getDefaultImg(docData.type);
}
super(docData, context);
}
static get defaultIcon() {
return undefined;
}
getUniteQuantite() {
switch (this.type) {
case "monnaie": return "(Pièces)"
case "herbe":
switch (this.system.categorie) {
case 'Alchimie': case 'Repos': case 'Soin':
return "(Brins)"
case 'Cuisine': return '';
}
return '';
case "ingredient": return "(Pépins ou Brins)"
}
return '';
}
isCompetencePersonnage() { return this.type == 'competence' }
isCompetenceCreature() { return this.type == 'competencecreature' }
isConteneur() { return this.type == 'conteneur'; }
isMonnaie() { return this.type == 'monnaie'; }
isNourritureBoisson() { return this.type == 'nourritureboisson'; }
isService() { return this.type == 'service'; }
isCompetence() { isCompetence() {
return typesObjetsCompetence.includes(this.type) return typesObjetsCompetence.includes(this.type)
} }
isEquipement() { isInventaire() {
return typesObjetsEquipement.includes(this.type) return typesObjetsInventaire.includes(this.type);
} }
isOeuvre() { isOeuvre() {
return typesObjetsOeuvres.includes(this.type) return typesObjetsOeuvres.includes(this.type)
@@ -100,12 +165,10 @@ export class RdDItem extends Item {
isConnaissance() { isConnaissance() {
return typesObjetsConnaissance.includes(this.type) return typesObjetsConnaissance.includes(this.type)
} }
isConteneur() {
return this.type == 'conteneur';
}
getItemGroup() { getItemGroup() {
if (this.isEquipement()) return "equipement"; if (this.isInventaire()) return "equipement";
if (this.isOeuvre()) return "oeuvre"; if (this.isOeuvre()) return "oeuvre";
if (this.isDraconique()) return "draconique"; if (this.isDraconique()) return "draconique";
if (this.isConnaissance()) return "connaissance"; if (this.isConnaissance()) return "connaissance";
@@ -126,9 +189,21 @@ export class RdDItem extends Item {
return !this.isConteneur() || (this.system.contenu?.length ?? 0) == 0; return !this.isConteneur() || (this.system.contenu?.length ?? 0) == 0;
} }
isAlcool() { isComestible() {
return this.type == 'nourritureboisson' && this.system.boisson && this.system.alcoolise; switch (this.type) {
case 'nourritureboisson': return 'pret';
case 'herbe':
return this.system.categorie == 'Cuisine' && this.system.sust > 0 ? 'brut' : '';
case 'faune':
return this.system.sust > 0 ? 'brut' : '';
} }
return '';
}
isAlcool() {
return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise;
}
isHerbeAPotion() { isHerbeAPotion() {
return this.type == 'herbe' && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); return this.type == 'herbe' && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos');
} }
@@ -144,7 +219,7 @@ export class RdDItem extends Item {
} }
getQuantite() { getQuantite() {
return Math.round(this.isConteneur() ? 1 : (this.system.quantite ?? 0)) return Math.round(this.system.quantite ?? 0)
} }
getEncTotal() { getEncTotal() {
@@ -154,24 +229,33 @@ export class RdDItem extends Item {
getEnc() { getEnc() {
switch (this.type) { switch (this.type) {
case 'herbe': case 'herbe':
return encBrin; return this.getEncHerbe();
case 'gemme': case 'gemme':
return encPepin * this.system.taille; return encPepin * this.system.taille;
} }
return Math.max(this.system.encombrement ?? 0, 0); return Math.max(this.system.encombrement ?? 0, 0);
} }
prixTotalDeniers() { getEncHerbe() {
return this.getQuantite() * this.valeurDeniers() switch (this.system.categorie) {
case 'Repos': case 'Soin': case 'Alchimie':
return encBrin;
}
return this.system.encombrement;
} }
valeurDeniers() { valeurTotale() {
return Math.max(Math.round(this.system.cout ? (this.system.cout * 100) : (this.system.valeur_deniers ?? 0)), 0) return this.getQuantite() * this.valeur()
}
valeur() {
return this.system.cout ?? 0
} }
prepareDerivedData() { prepareDerivedData() {
super.prepareDerivedData(); super.prepareDerivedData();
if (this.isEquipement()) { if (this.isInventaire()) {
this.system.encTotal = this.getEncTotal(); this.system.encTotal = this.getEncTotal();
if (this.isPotion()) { if (this.isPotion()) {
this.prepareDataPotion() this.prepareDataPotion()
@@ -192,18 +276,42 @@ export class RdDItem extends Item {
} }
getActionPrincipale(options = { warnIfNot: true }) { getActionPrincipale(options = { warnIfNot: true }) {
switch (this.type) {
case 'conteneur': return 'Ouvrir';
}
if (this.actor?.isPersonnage()) {
const warn = options.warnIfNot; const warn = options.warnIfNot;
if (this.isComestible() == 'brut') {
return 'Utiliser';
}
switch (this.type) { switch (this.type) {
case 'nourritureboisson': return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn); case 'nourritureboisson': return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
case 'potion': return this._actionOrWarnQuantiteZero('Boire', warn); case 'potion': return this._actionOrWarnQuantiteZero('Boire', warn);
case 'livre': return this._actionOrWarnQuantiteZero('Lire', warn); case 'livre': return this._actionOrWarnQuantiteZero('Lire', warn);
case 'conteneur': return 'Ouvrir';
case 'herbe': return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined; case 'herbe': return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
case 'queue': case 'ombre': return this.system.refoulement > 0 ? 'Refouler' : undefined; case 'queue': case 'ombre': return this.system.refoulement > 0 ? 'Refouler' : undefined;
} }
}
return undefined; return undefined;
} }
/* -------------------------------------------- */
async actionPrincipale(actor, onActionItem = async () => { }) {
if (!this.getActionPrincipale()) {
return;
}
if (await actor.actionNourritureboisson(this, onActionItem)) {
return;
}
switch (this.type) {
case 'potion': return await actor.consommerPotion(this, onActionItem);
case 'livre': return await actor.actionLire(this);
case 'conteneur': return await this.sheet.render(true);
case 'herbe': return await actor.actionHerbe(this);
case 'queue': case 'ombre': return await actor.actionRefoulement(this);
}
}
_actionOrWarnQuantiteZero(actionName, warn) { _actionOrWarnQuantiteZero(actionName, warn) {
if ((this.system.quantite ?? 0) <= 0) { if ((this.system.quantite ?? 0) <= 0) {
if (warn) { if (warn) {
@@ -221,6 +329,42 @@ export class RdDItem extends Item {
await this.quantiteIncDec(-nombre, options); await this.quantiteIncDec(-nombre, options);
} }
async onCreateDecoupeComestible(actor) {
if (actor && this.isComestible() == 'brut' && this.system.sust != 1) {
if (this.system.sust < 1) {
await actor.updateEmbeddedDocuments('Item', [{
_id: this.id,
'system.sust': 0
}])
}
else {
const sust = Math.floor(this.system.sust);
await actor.updateEmbeddedDocuments('Item', [{
_id: this.id,
'system.quantite': this.system.quantite * sust,
'system.encombrement': Misc.keepDecimals(this.system.encombrement / sust, 2),
'system.cout': Misc.keepDecimals(this.system.cout / sust, 2),
'system.sust': 1
}])
}
}
}
async empiler(item) {
if (this.isComestible() == 'brut') {
const sust = this.system.sust + item.system.sust;
const encombrement = this.system.encombrement + item.system.encombrement;
await this.update({
"system.sust": sust,
"system.encombrement": encombrement
});
}
else {
await this.quantiteIncDec(item.system.quantite);
}
await item.delete();
}
async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) { async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
const quantite = Number(this.system.quantite ?? -1); const quantite = Number(this.system.quantite ?? -1);
if (quantite >= 0) { if (quantite >= 0) {
@@ -244,11 +388,10 @@ export class RdDItem extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
// détermine si deux équipements sont similaires: de même type, et avec les même champs hormis la quantité // détermine si deux équipements sont similaires: de même type, et avec les même champs hormis la quantité
isEquipementEmpilable(other) { isInventaireEmpilable(other) {
if (!other || !this.isEquipement()) { if (!other || !this.isInventaire()) {
return [false, undefined]; return [false, undefined];
} }
if (this.system.quantite == undefined) { if (this.system.quantite == undefined) {
return [false, `Impossible de regrouper des ${this.type}, ils ne sont pas empilables`]; return [false, `Impossible de regrouper des ${this.type}, ils ne sont pas empilables`];
} }
@@ -259,8 +402,13 @@ export class RdDItem extends Item {
return [false, `Impossible de regrouper ${this.name} avec ${other.name}`]; return [false, `Impossible de regrouper ${this.name} avec ${other.name}`];
} }
else { else {
const differences = Object.entries(this.system) const excludedProperties = ['quantite', 'cout', 'encTotal'];
.filter(([key, value]) => !['quantite', 'cout', 'encTotal'].includes(key) && value != other.system[key]); if (this.isComestible()) {
excludedProperties.push('sust', 'encombrement');
}
let differences = Object.entries(this.system)
.filter(([key, value]) => !excludedProperties.includes(key))
.filter(([key, value]) => value != other.system[key])
if (differences.length > 0) { if (differences.length > 0) {
let message = `Impossible de regrouper les ${this.type} ${this.name}: `; let message = `Impossible de regrouper les ${this.type} ${this.name}: `;
for (const [key, value] of differences) { for (const [key, value] of differences) {
@@ -272,13 +420,17 @@ export class RdDItem extends Item {
return [true, undefined]; return [true, undefined];
} }
async proposerVente() { async proposerVente({ service = undefined, quantiteMax = undefined }) {
console.log(this); console.log(this);
if (this.isConteneurNonVide()) { if (this.isConteneurNonVide()) {
ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`); ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`);
return; return;
} }
await DialogItemVente.display(this, async (vente) => { await DialogItemVente.display({
item: this,
service,
quantiteMax,
callback: async (vente) => {
vente["properties"] = this.getProprietes(); vente["properties"] = this.getProprietes();
if (vente.isOwned) { if (vente.isOwned) {
if (vente.quantiteNbLots * vente.tailleLot > vente.quantiteMax) { if (vente.quantiteNbLots * vente.tailleLot > vente.quantiteMax) {
@@ -288,15 +440,18 @@ export class RdDItem extends Item {
} }
vente.jsondata = JSON.stringify(vente.item); vente.jsondata = JSON.stringify(vente.item);
console.log(vente);
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente); let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
ChatMessage.create(RdDUtility.chatDataSetup(html)); ChatMessage.create(RdDUtility.chatDataSetup(html));
}
}); });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getProprietes() { getProprietes() {
return this[`_${this.type}ChatData`](); if (this[`_${this.type}ChatData`]) {
return this[`_${this.type}ChatData`]().filter(it => it != undefined);
}
return [];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -314,35 +469,44 @@ export class RdDItem extends Item {
payload: chatData, payload: chatData,
}); });
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-item.html', chatData).then(html => { renderTemplate(this.getChatItemTemplate(), chatData).then(html => {
let chatOptions = RdDUtility.chatDataSetup(html, modeOverride); let chatOptions = RdDUtility.chatDataSetup(html, modeOverride);
ChatMessage.create(chatOptions) ChatMessage.create(chatOptions)
}); });
} }
static propertyIfDefined(name, val, condition = (it) => true) { getChatItemTemplate() {
return condition ? [`<b>${name}</b>: ${val}`] : []; switch (this.type) {
case 'service': return 'systems/foundryvtt-reve-de-dragon/templates/post-item-service.html';
}
return 'systems/foundryvtt-reve-de-dragon/templates/post-item.html';
} }
static propertyIfDefined(name, val, condition = true) {
return condition ? `<b>${name}</b>: ${val}` : undefined;
}
_inventaireTemplateChatData() {
return [
RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite != 0),
RdDItem.propertyIfDefined('Encombrement', this.system.encombrement)
// cout et quantité masqués
]
}
/* -------------------------------------------- */ /* -------------------------------------------- */
_objetChatData() { _objetChatData() {
return [].concat( return this._inventaireTemplateChatData()
RdDItem.propertyIfDefined('Résistance', this.system.resistance, this.system.resistance),
RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite),
RdDItem.propertyIfDefined('Encombrement', this.system.encombrement),
);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_nourritureboissonChatData() { _nourritureboissonChatData() {
return [].concat( return [
RdDItem.propertyIfDefined('Sustentation', this.system.sust, this.system.sust > 0), RdDItem.propertyIfDefined('Sustentation', this.system.sust, this.system.sust > 0),
RdDItem.propertyIfDefined('Désaltère', this.system.desaltere, this.system.boisson), RdDItem.propertyIfDefined('Désaltère', this.system.desaltere, this.system.boisson),
RdDItem.propertyIfDefined('Force alcool', this.system.force, this.system.boisson && this.system.alcoolise), RdDItem.propertyIfDefined('Force alcool', this.system.force, this.system.boisson && this.system.alcoolise),
RdDItem.propertyIfDefined('Exotisme', this.system.exotisme, this.system.exotisme < 0), RdDItem.propertyIfDefined('Exotisme', this.system.exotisme, this.system.exotisme < 0),
RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite), ...this._inventaireTemplateChatData()
RdDItem.propertyIfDefined('Encombrement', this.system.encombrement), ]
);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_armeChatData() { _armeChatData() {
@@ -351,21 +515,19 @@ export class RdDItem extends Item {
`<b>Dommages</b>: ${this.system.dommages}`, `<b>Dommages</b>: ${this.system.dommages}`,
`<b>Force minimum</b>: ${this.system.force}`, `<b>Force minimum</b>: ${this.system.force}`,
`<b>Resistance</b>: ${this.system.resistance}`, `<b>Resistance</b>: ${this.system.resistance}`,
`<b>Encombrement</b>: ${this.system.encombrement}` ...this._inventaireTemplateChatData()
] ]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_conteneurChatData() { _conteneurChatData() {
return [ return [
`<b>Capacité</b>: ${this.system.capacite} Enc.`, `<b>Capacité</b>: ${this.system.capacite} Enc.`,
`<b>Encombrement</b>: ${this.system.encombrement}` ...this._inventaireTemplateChatData()
] ]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_munitionChatData() { _munitionChatData() {
return [ return this._inventaireTemplateChatData()
`<b>Encombrement</b>: ${this.system.encombrement}`
]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_armureChatData() { _armureChatData() {
@@ -373,7 +535,7 @@ export class RdDItem extends Item {
`<b>Protection</b>: ${this.system.protection}`, `<b>Protection</b>: ${this.system.protection}`,
`<b>Détérioration</b>: ${this.system.deterioration}`, `<b>Détérioration</b>: ${this.system.deterioration}`,
`<b>Malus armure</b>: ${this.system.malus}`, `<b>Malus armure</b>: ${this.system.malus}`,
`<b>Encombrement</b>: ${this.system.encombrement}` ...this._inventaireTemplateChatData()
] ]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -407,16 +569,24 @@ export class RdDItem extends Item {
_herbeChatData() { _herbeChatData() {
return [ return [
`<b>Milieu</b>: ${this.system.milieu}`, `<b>Milieu</b>: ${this.system.milieu}`,
`<b>Rareté</b>: ${this.system.rarete}`,
`<b>Catégorie</b>: ${this.system.categorie}`, `<b>Catégorie</b>: ${this.system.categorie}`,
...this._inventaireTemplateChatData()
] ]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_ingredientChatData() { _ingredientChatData() {
return [ return [
`<b>Milieu</b>: ${this.system.milieu}`, `<b>Milieu</b>: ${this.system.milieu}`,
`<b>Rareté</b>: ${this.system.rarete}`,
`<b>Catégorie</b>: ${this.system.categorie}`, `<b>Catégorie</b>: ${this.system.categorie}`,
...this._inventaireTemplateChatData()
]
}
/* -------------------------------------------- */
_fauneChatData() {
return [
`<b>Sustentation</b>: ${this.system.sust}`,
`<b>Milieu</b>: ${this.system.milieu}`,
...this._inventaireTemplateChatData()
] ]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -426,12 +596,9 @@ export class RdDItem extends Item {
`<b>Compétence</b>: ${this.system.competence}`, `<b>Compétence</b>: ${this.system.competence}`,
`<b>Périodicité</b>: ${this.system.periodicite}`, `<b>Périodicité</b>: ${this.system.periodicite}`,
`<b>Fatigue</b>: ${this.system.fatigue}`, `<b>Fatigue</b>: ${this.system.fatigue}`,
`<b>Difficulté</b>: ${this.system.difficulte}` `<b>Difficulté</b>: ${this.system.difficulte}`,
].concat([ RdDItem.propertyIfDefined('Points de Tâche', this.system.points_de_tache, this.system.cacher_points_de_tache),
this.system.cacher_points_de_tache ? [] :`<b>Points de Tâche</b>: ${this.system.points_de_tache}`
]).concat([
`<b>Points de Tâche atteints</b>: ${this.system.points_de_tache_courant}`] `<b>Points de Tâche atteints</b>: ${this.system.points_de_tache_courant}`]
);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_livreChatData() { _livreChatData() {
@@ -439,8 +606,8 @@ export class RdDItem extends Item {
`<b>Compétence</b>: ${this.system.competence}`, `<b>Compétence</b>: ${this.system.competence}`,
`<b>Auteur</b>: ${this.system.auteur}`, `<b>Auteur</b>: ${this.system.auteur}`,
`<b>Difficulté</b>: ${this.system.difficulte}`, `<b>Difficulté</b>: ${this.system.difficulte}`,
`<b>Points de Tâche</b>: ${this.system.points_de_tache}`, RdDItem.propertyIfDefined('Points de Tâche', this.system.points_de_tache, this.system.cacher_points_de_tache),
`<b>Encombrement</b>: ${this.system.encombrement}` ...this._inventaireTemplateChatData()
] ]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -448,32 +615,44 @@ export class RdDItem extends Item {
return [ return [
`<b>Rareté</b>: ${this.system.rarete}`, `<b>Rareté</b>: ${this.system.rarete}`,
`<b>Catégorie</b>: ${this.system.categorie}`, `<b>Catégorie</b>: ${this.system.categorie}`,
`<b>Encombrement</b>: ${this.system.encombrement}`, ...this._inventaireTemplateChatData()
] ]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_queueChatData() { _queueChatData() {
function label(categorie) {
switch (categorie) {
case 'ideefixe': return 'Idée fixe';
case 'lancinant': return 'Désir lancinant';
}
return ''
}
return [ return [
`<b>Refoulement</b>: ${this.system.refoulement}` `<b>Refoulement</b>: ${this.system.refoulement}`,
`<b>Catégorie</b>: ${label(this.system.categorie)}`,
`<b>Affecte</b>: ${this.system.hautrevant ? 'les haut-rêvants' : 'tout le monde'}`,
] ]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_ombreChatData() { _ombreChatData() {
return [ return this._queueChatData()
`<b>Refoulement</b>: ${this.system.refoulement}`
]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_souffleChatData() { _souffleChatData() {
return []; return [
`<b>Affecte</b>: ${this.system.hautrevant ? 'les haut-rêvants' : 'tout le monde'}`,
];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_teteChatData() { _teteChatData() {
return []; return [
`<b>Affecte</b>: ${this.system.hautrevant ? 'les haut-rêvants' : 'tout le monde'}`,
];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_tarotChatData() { _tarotChatData() {
return [ return [
RdDItem.propertyIfDefined('Carte', RdDUtility.linkCompendium(this.pack, this.id, this.name), this.pack),
`<b>Concept</b>: ${this.system.concept}`, `<b>Concept</b>: ${this.system.concept}`,
`<b>Aspect</b>: ${this.system.aspect}`, `<b>Aspect</b>: ${this.system.aspect}`,
] ]
@@ -487,10 +666,7 @@ export class RdDItem extends Item {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_monnaieChatData() { _monnaieChatData() {
return [ return this._inventaireTemplateChatData()
`<b>Valeur en Deniers</b>: ${this.system.valeur_deniers}`,
`<b>Encombrement</b>: ${this.system.encombrement}`
]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_meditationChatData() { _meditationChatData() {
@@ -514,9 +690,9 @@ export class RdDItem extends Item {
] ]
} }
return [ return [
`<b>Force</b>: ${this.system.force}`, `<b>Force</b>: ${this.system.formule}`,
`<b>Refoulement</b>: ${this.system.refoulement}`, `<b>Refoulement</b>: ${this.system.refoulement}`,
`<b>Présent de cités</b>: ${this.system.presentCite}`, RdDItem.propertyIfDefined('<b>Présent de cités</b>', '', this.system.presentCite),
] ]
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -531,15 +707,12 @@ export class RdDItem extends Item {
if (!this.system.identifie) { if (!this.system.identifie) {
return [`<b>Inconnue</b>`] return [`<b>Inconnue</b>`]
} }
let properties = [ return [
`<b>Malignité</b>: ${this.system.malignite}`, `<b>Malignité</b>: ${this.system.malignite}`,
`<b>Périodicité</b>: ${this.system.periodicite}`, `<b>Périodicité</b>: ${this.system.periodicite}`,
`<b>Dommages</b>: ${this.system.dommages}` `<b>Dommages</b>: ${this.system.dommages}`,
RdDItem.propertyIfDefined('<b>Remedes</b>', this.system.remedes, this.system.remedesconnus),
] ]
if (this.system.remedesconnus) {
properties.push(`<b>Remedes</b>: ${this.system.remedes}`)
}
return properties;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -554,9 +727,7 @@ export class RdDItem extends Item {
`<b>Taille</b>: ${this.system.taille}`, `<b>Taille</b>: ${this.system.taille}`,
`<b>Inertie</b>: ${this.system.inertie}`, `<b>Inertie</b>: ${this.system.inertie}`,
`<b>Enchantabilité</b>: ${this.system.enchantabilite}`, `<b>Enchantabilité</b>: ${this.system.enchantabilite}`,
`<b>Prix</b>: ${this.system.cout}`, ...this._inventaireTemplateChatData()
] ]
} }
} }

View File

@@ -1,6 +1,6 @@
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js"; import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
import { Environnement } from "./environnement.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
class Migration { class Migration {
get code() { return "sample"; } get code() { return "sample"; }
@@ -29,6 +29,39 @@ class Migration {
} }
class _1_5_34_migrationPngWebp {
get code() { return "migrationPngWebp"; }
get version() { return "1.5.34"; }
async migrate() {
const regexOldPngJpg = /(systems\/foundryvtt-reve-de-dragon\/icons\/.*)\.(png|jpg)/;
const replaceWithWebp = '$1.webp';
function convertImgToWebp(img) {
return img.replace(regexOldPngJpg, replaceWithWebp);
}
function prepareDocumentsImgUpdate(documents) {
return documents.filter(it => it.img && it.img.match(regexOldPngJpg))
.map(it => {
return { _id: it.id, img: convertImgToWebp(it.img) }
});
}
const itemsUpdates = prepareDocumentsImgUpdate(game.items);
const actorsUpdates = prepareDocumentsImgUpdate(game.actors);
//Migrate system png to webp
await Item.updateDocuments(itemsUpdates);
await Actor.updateDocuments(actorsUpdates);
game.actors.forEach(actor => {
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
actor.update({ "token.img": convertImgToWebp(actor.token.img) });
}
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
});
}
}
class _10_0_16_MigrationSortsReserve extends Migration { class _10_0_16_MigrationSortsReserve extends Migration {
get code() { return "creation-item-sort-reserve"; } get code() { return "creation-item-sort-reserve"; }
get version() { return "10.0.16"; } get version() { return "10.0.16"; }
@@ -180,14 +213,132 @@ class _10_2_5_ArmesTirLancer extends Migration {
} }
} }
class _10_2_10_DesirLancinant_IdeeFixe extends Migration {
get code() { return "desir-lancinat-idee-fixe"; }
get version() { return "10.2.10"; }
migrateQueue(it) {
let categorie = undefined
let name = it.name
if (Grammar.toLowerCaseNoAccent(name).includes('desir')) {
categorie = 'lancinant';
name = it.name.replace('Désir lancinant : ', '');
}
if (Grammar.toLowerCaseNoAccent(name).includes('idee fixe')) {
categorie = 'ideefixe';
name = it.name.replace('Idée fixe : ', '')
}
return {
_id: it.id, name: name,
'system.ideefixe': undefined,
'system.lancinant': undefined,
'system.categorie': categorie
}
}
async migrate() {
await this.applyItemsUpdates(items => items
.filter(it => ['queue', 'ombre'].includes(it.type))
.map(it => this.migrateQueue(it))
);
}
}
class _10_3_0_Inventaire extends Migration {
get code() { return "migration-equipement-inventaire"; }
get version() { return "10.3.0"; }
async migrate() {
await this.applyItemsUpdates(items => {
return this._updatesMonnaies(items)
.concat(this._updatesNonEquipe(items))
.concat(this._updatesObjets(items))
});
}
_updatesNonEquipe(items) {
return items
.filter(it => ['munition'].includes(it.type))
.map(it => { return { _id: it.id, 'system.equipe': undefined } });
}
_updatesObjets(items) {
return items
.filter(it => ['objet'].includes(it.type))
.map(it => { return { _id: it.id, 'system.resistance': undefined, 'system.equipe': undefined } });
}
_updatesMonnaies(items) {
return items
.filter(it => ['monnaie'].includes(it.type) && it.system.valeur_deniers != undefined)
.map(it => { return { _id: it.id, 'system.cout': it.system.valeur_deniers / 100, 'system.valeur_deniers': undefined } });
}
}
class _10_3_0_FrequenceEnvironnement extends Migration {
get code() { return "migration-frequence-resources"; }
get version() { return "10.3.0"; }
async migrate() {
await this.applyItemsUpdates(items => items.filter(it => ['herbe', 'ingredient'].includes(it.type))
.map(it => this._updatesFrequences(it)));
}
_updatesFrequences(it) {
return {
_id: it.id,
'system.rarete': undefined,
'system.environnement': [{ milieu: it.system.milieu, rarete: it.system.rarete, frequence: Environnement.getFrequenceRarete(it.system.rarete, 'frequence') }]
}
}
}
class _10_3_17_Monnaies extends Migration {
constructor() {
super();
this.mapValeur = {
"Etain (1 denier)": { name: 'Denier (étain)', system: { cout: 0.01 } },
"Bronze (10 deniers)": { name: "Sou (bronze)", system: { cout: 0.1 } },
"Argent (1 sol)": { name: "Sol (argent)", system: { cout: 1 } },
"Or (10 sols)": { name: "Dragon (or)", system: { cout: 10 } }
};
}
get code() { return "migration-monnaies"; }
get version() { return "10.3.17"; }
async migrate() {
await this.applyItemsUpdates(items => this._updatesMonnaies(items));
}
_updatesMonnaies(items) {
return items
.filter(it => 'monnaie' == it.type)
.filter(it => this.mapValeur[it.name] != undefined)
.map(it => {
const correction = this.mapValeur[it.name];
return {
_id: it.id,
'name': correction.name,
'system.cout': correction.system.cout,
'system.valeur_deniers': undefined
}
});
}
}
export class Migrations { export class Migrations {
static getMigrations() { static getMigrations() {
return [ return [
new _1_5_34_migrationPngWebp(),
new _10_0_16_MigrationSortsReserve(), new _10_0_16_MigrationSortsReserve(),
new _10_0_17_MigrationCompetenceCreature(), new _10_0_17_MigrationCompetenceCreature(),
new _10_0_21_VehiculeStructureResistanceMax(), new _10_0_21_VehiculeStructureResistanceMax(),
new _10_0_33_MigrationNomsDraconic(), new _10_0_33_MigrationNomsDraconic(),
new _10_2_5_ArmesTirLancer(), new _10_2_5_ArmesTirLancer(),
new _10_2_10_DesirLancinant_IdeeFixe(),
new _10_3_0_Inventaire(),
new _10_3_0_FrequenceEnvironnement(),
new _10_3_17_Monnaies()
]; ];
} }
@@ -202,11 +353,9 @@ export class Migrations {
} }
migrate() { migrate() {
const currentVersion = game.settings.get( const currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion");
SYSTEM_RDD,
"systemMigrationVersion"
);
if (isNewerVersion(game.system.version, currentVersion)) { if (isNewerVersion(game.system.version, currentVersion)) {
//if (true) { /* comment previous and uncomment here to test before upgrade */
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion)); const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
if (migrations.length > 0) { if (migrations.length > 0) {
migrations.sort((a, b) => migrations.sort((a, b) =>

View File

@@ -24,7 +24,7 @@ export class Misc {
} }
static sum() { static sum() {
return (a, b) => a + b; return (a, b) => Number(a) + Number(b);
} }
static ascending(orderFunction = x => x) { static ascending(orderFunction = x => x) {
@@ -41,6 +41,11 @@ export class Misc {
return 0; return 0;
} }
static typeName(type, subType) {
return subType ? game.i18n.localize(`${type.toUpperCase()}.Type${Misc.upperFirst(subType)}`)
: '';
}
/** /**
* Converts the value to an integer, or to 0 if undefined/null/not representing integer * Converts the value to an integer, or to 0 if undefined/null/not representing integer
* @param {*} value value to convert to an integer using parseInt * @param {*} value value to convert to an integer using parseInt
@@ -68,6 +73,19 @@ export class Misc {
} }
} }
static indexLowercase(list) {
const obj = {};
const addToObj = (map, val) => {
const key = Grammar.toLowerCaseNoAccent(val);
if (key && !map[key]) map[key] = val
}
list.forEach(it => addToObj(obj, it))
return obj;
}
static concat(lists) {
return lists.reduce((a, b) => a.concat(b), []);
}
static classify(items, classifier = it => it.type) { static classify(items, classifier = it => it.type) {
let itemsBy = {} let itemsBy = {}
Misc.classifyInto(itemsBy, items, classifier) Misc.classifyInto(itemsBy, items, classifier)
@@ -102,7 +120,11 @@ export class Misc {
} }
static join(params, separator = '') { static join(params, separator = '') {
return params?.reduce((a, b) => a + separator + b) ?? ''; return params?.reduce(Misc.joining(separator)) ?? '';
}
static joining(separator = '') {
return (a, b) => a + separator + b;
} }
static connectedGMOrUser(ownerId = undefined) { static connectedGMOrUser(ownerId = undefined) {
@@ -112,13 +134,20 @@ export class Misc {
return Misc.firstConnectedGM()?.id ?? game.user.id; return Misc.firstConnectedGM()?.id ?? game.user.id;
} }
static isRollModeHiddenToPlayer() {
switch (game.settings.get("core", "rollMode")) {
case CONST.DICE_ROLL_MODES.BLIND:
case CONST.DICE_ROLL_MODES.SELF: return true;
}
return false
}
static getActiveUser(id) { static getActiveUser(id) {
return game.users.find(u => u.id == id && u.active); return game.users.find(u => u.id == id && u.active);
} }
static firstConnectedGM() { static firstConnectedGM() {
return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active); return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
} }
static isOwnerPlayer(actor, user=undefined) { static isOwnerPlayer(actor, user=undefined) {

View File

@@ -1,44 +0,0 @@
Le courant du Fleuve
Te domine et te Porte
Avant que tu te moeuves
Combat le, ou il t'emporte
A vous qui faites ripaille
sourds aux damnés de la faim
à vous qui livrez
une inégale bataille
à ceux qui vous tendent la main
Ils sont tout près ! - Tenons fermée
<br>Cette salle, où nous les narguons.
<br>Quel bruit dehors ! Hideuse armée
<br>De vampires et de dragons !
<br>La poutre du toit descellée
<br>Ploie ainsi qu'une herbe mouillée,
<br>Et la vieille porte rouillée
<br>Tremble, à déraciner ses gonds !`),
https://www.poetica.fr/poeme-1423/guy-de-maupassant-le-sommeil-du-mandarin/
Le monde est un rêve de Dragons. Nous
ne savons pas qui sont les Dragons ni à quoi
ils ressemblent, en dépit de lantique iconographie qui les dépeint comme de gigantesques créatures ailées capables de cracher
feu et flammes.
Car parmi les humains, autre nom lui est donné,
Nom sinistre parmi tous, nom funèbre, c'est la mort!
Un ami disparu... Thanatos est passé...
Messieurs, ne crachez pas de jurons ni d'ordure
Au visage fardé de cette pauvre impure
Que déesse Famine a par un soir d'hiver,
Contrainte à relever ses jupons en plein air.

View File

@@ -15,13 +15,19 @@
// Common conf // Common conf
let dialogConf = { content: html, title: "Editeur d'Astrologie", buttons: myButtons, default: "saveButton" }; let dialogConf = { content: html, title: "Editeur d'Astrologie", buttons: myButtons, default: "saveButton" };
let dialogOptions = { classes: ["rdddialog"], width: 600, height: 300, 'z-index': 99999 } let dialogOptions = { classes: ["rdd-roll-dialog"], width: 600, height: 300, 'z-index': 99999 }
super(dialogConf, dialogOptions) super(dialogConf, dialogOptions)
this.calendrier = calendrier; this.calendrier = calendrier;
this.updateData( calendrierData ); this.updateData( calendrierData );
} }
activateListeners(html) {
super.activateListeners(html);
this.html = html;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async resetNombreAstraux() { async resetNombreAstraux() {
game.system.rdd.calendrier.resetNombreAstral(); game.system.rdd.calendrier.resetNombreAstral();
@@ -39,15 +45,4 @@
this.calendrierData = duplicate(calendrierData); this.calendrierData = duplicate(calendrierData);
} }
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
let astrologieData = this.astrologieData;
$(function () {
});
}
} }

View File

@@ -20,7 +20,7 @@ export class RdDAstrologieJoueur extends Dialog {
astrologie: RdDItemCompetence.findCompetence(actor.items, 'Astrologie') astrologie: RdDItemCompetence.findCompetence(actor.items, 'Astrologie')
} }
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', dialogData); const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', dialogData);
let options = { classes: ["rdddialog"], width: 600, height: 500, 'z-index': 99999 }; let options = { classes: ["rdd-roll-dialog"], width: 600, height: 500, 'z-index': 99999 };
if (dialogConfig.options) { if (dialogConfig.options) {
mergeObject(options, dialogConfig.options, { overwrite: true }); mergeObject(options, dialogConfig.options, { overwrite: true });
} }
@@ -29,21 +29,35 @@ export class RdDAstrologieJoueur extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
constructor(html, actor, dialogData) { constructor(html, actor, dialogData) {
const dialogConf = {
let myButtons = { title: "Nombres Astraux",
content: html,
default: "saveButton",
buttons: {
saveButton: { label: "Fermer", callback: html => this.quitDialog() } saveButton: { label: "Fermer", callback: html => this.quitDialog() }
},
}; };
const dialogOptions = { classes: ["rdd-roll-dialog"], width: 600, height: 300, 'z-index': 99999 };
// Get all n
// Common conf
let dialogConf = { content: html, title: "Nombres Astraux", buttons: myButtons, default: "saveButton" };
let dialogOptions = { classes: ["rdddialog"], width: 600, height: 300, 'z-index': 99999 };
super(dialogConf, dialogOptions); super(dialogConf, dialogOptions);
this.actor = actor; this.actor = actor;
this.dataNombreAstral = duplicate(dialogData); this.dataNombreAstral = duplicate(dialogData);
} }
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
this.html = html;
this.html.find(function () {
this.html.find("[name='diffConditions']").val(0);
});
this.html.find('[name="jet-astrologie"]').click((event) => {
this.requestJetAstrologie();
});
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static organizeNombres(actor) { static organizeNombres(actor) {
let itemNombres = actor.listItemsData('nombreastral'); let itemNombres = actor.listItemsData('nombreastral');
@@ -68,8 +82,8 @@ export class RdDAstrologieJoueur extends Dialog {
carac_vue: this.actor.system.carac['vue'].value, carac_vue: this.actor.system.carac['vue'].value,
etat: this.dataNombreAstral.etat, etat: this.dataNombreAstral.etat,
astrologie: this.dataNombreAstral.astrologie, astrologie: this.dataNombreAstral.astrologie,
conditions: $("#diffConditions").val(), conditions: this.html.find('[name="diffConditions"]').val(),
date: $("#joursAstrologie").val(), date: this.html.find('[name="joursAstrologie"]').val(),
userId: game.user.id userId: game.user.id
} }
if (Misc.isUniqueConnectedGM()) { if (Misc.isUniqueConnectedGM()) {
@@ -87,17 +101,4 @@ export class RdDAstrologieJoueur extends Dialog {
quitDialog() { quitDialog() {
} }
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
$(function () {
$("#diffConditions").val(0);
});
html.find('#jet-astrologie').click((event) => {
this.requestJetAstrologie();
});
}
} }

View File

@@ -16,21 +16,31 @@ export class RdDCalendrierEditeur extends Dialog {
}, },
default: "save" default: "save"
}; };
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 'fit-content', 'z-index': 99999 } let dialogOptions = { classes: ["rdd-dialog-calendar-editor"], width: 400, height: 'fit-content', 'z-index': 99999 }
super(dialogConf, dialogOptions) super(dialogConf, dialogOptions)
this.calendrier = calendrier; this.calendrier = calendrier;
this.calendrierData = calendrierData; this.calendrierData = calendrierData;
} }
activateListeners(html) {
super.activateListeners(html);
this.html = html;
this.html.find("input[name='nomMois']").val(this.calendrierData.moisKey);
this.html.find("select[name='nomHeure']").val(this.calendrierData.heureKey);
this.html.find("select[name='jourMois']").val(this.calendrierData.jourMois);
this.html.find("select[name='minutesRelative']").val(this.calendrierData.minutesRelative);
this.html.find("select[name='annee']").val(this.calendrierData.annee);
}
/* -------------------------------------------- */ /* -------------------------------------------- */
fillData() { fillData() {
this.calendrierData.moisKey = $("#nomMois").val(); this.calendrierData.annee = this.html.find("input[name='annee']").val();
this.calendrierData.heureKey = $("#nomHeure").val(); this.calendrierData.moisKey = this.html.find("select[name='nomMois']").val();
this.calendrierData.jourMois = $("#jourMois").val(); this.calendrierData.heureKey = this.html.find("select[name='nomHeure']").val();
this.calendrierData.minutesRelative = $("#minutesRelative").val(); this.calendrierData.jourMois = this.html.find("select[name='jourMois']").val();
this.calendrierData.minutesRelative = this.html.find("select[name='minutesRelative']").val();
console.log("UPDATE ", this.calendrierData);
this.calendrier.saveEditeur(this.calendrierData) this.calendrier.saveEditeur(this.calendrierData)
} }
@@ -39,20 +49,4 @@ export class RdDCalendrierEditeur extends Dialog {
this.calendrierData = duplicate(calendrierData); this.calendrierData = duplicate(calendrierData);
} }
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
let calendrierData = this.calendrierData;
$(function () {
console.log(calendrierData);
$("#nomMois").val(calendrierData.moisKey);
$("#nomHeure").val(calendrierData.heureKey);
$("#jourMois").val(calendrierData.jourMois);
$("#minutesRelative").val(calendrierData.minutesRelative);
});
}
} }

View File

@@ -43,6 +43,14 @@ const MAX_NOMBRE_ASTRAL = 12;
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDCalendrier extends Application { export class RdDCalendrier extends Application {
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html",
popOut: false,
resizable: false
});
}
static createCalendrierPos() { static createCalendrierPos() {
return { top: 200, left: 200 }; return { top: 200, left: 200 };
} }
@@ -116,24 +124,107 @@ export class RdDCalendrier extends Application {
game.settings.set(SYSTEM_RDD, "calendrier", this.calendrier); game.settings.set(SYSTEM_RDD, "calendrier", this.calendrier);
this.listeNombreAstral = this.getListeNombreAstral(); this.listeNombreAstral = this.getListeNombreAstral();
this.rebuildListeNombreAstral(false); // Ensure always up-to-date this.rebuildListeNombreAstral(HIDE_DICE); // Ensure always up-to-date
} }
console.log('RdDCalendrier.constructor()', this.calendrier, this.calendrierPos, this.listeNombreAstral); console.log('RdDCalendrier.constructor()', this.calendrier, this.calendrierPos, this.listeNombreAstral);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getListeNombreAstral() { /** @override */
return game.settings.get(SYSTEM_RDD, "liste-nombre-astral") ?? []; async activateListeners(html) {
super.activateListeners(html);
this.html = html;
this.updateDisplay();
this.html.find('.ajout-chronologie').click(ev => DialogChronologie.create());
this.html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));
this.html.find('.calendar-btn-edit').click(ev => {
ev.preventDefault();
this.showCalendarEditor();
});
this.html.find('.astrologie-btn-edit').click(ev => {
ev.preventDefault();
this.showAstrologieEditor();
});
this.html.find('#calendar-move-handle').mousedown(ev => {
ev.preventDefault();
ev = ev || window.event;
let isRightMB = false;
if ("which" in ev) { // Gecko (Firefox), WebKit (Safari/Chrome) & Opera
isRightMB = ev.which == 3;
} else if ("button" in ev) { // IE, Opera
isRightMB = ev.button == 2;
} }
/* -------------------------------------------- */ if (!isRightMB) {
static get defaultOptions() { dragElement(document.getElementById("calendar-time-container"));
return mergeObject(super.defaultOptions, { let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
template: "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html",
popOut: false, function dragElement(elmnt) {
resizable: false elmnt.onmousedown = dragMouseDown;
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
elmnt.style.bottom = undefined
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
// stop moving when mouse button is released:
elmnt.onmousedown = undefined;
document.onmouseup = undefined;
document.onmousemove = undefined;
let xPos = (elmnt.offsetLeft - pos1) > window.innerWidth ? window.innerWidth - 200 : (elmnt.offsetLeft - pos1);
let yPos = (elmnt.offsetTop - pos2) > window.innerHeight - 20 ? window.innerHeight - 100 : (elmnt.offsetTop - pos2)
xPos = xPos < 0 ? 0 : xPos;
yPos = yPos < 0 ? 0 : yPos;
if (xPos != (elmnt.offsetLeft - pos1) || yPos != (elmnt.offsetTop - pos2)) {
elmnt.style.top = (yPos) + "px";
elmnt.style.left = (xPos) + "px";
}
game.system.rdd.calendrier.calendrierPos.top = yPos;
game.system.rdd.calendrier.calendrierPos.left = xPos;
if (game.user.isGM) {
game.settings.set(SYSTEM_RDD, "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos));
}
}
}
} else if (isRightMB) {
game.system.rdd.calendrier.calendrierPos.top = 200;
game.system.rdd.calendrier.calendrierPos.left = 200;
if (game.user.isGM) {
game.settings.set(SYSTEM_RDD, "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos));
}
this.setPos(game.system.rdd.calendrier.calendrierPos);
}
}); });
} }
/* -------------------------------------------- */
getListeNombreAstral() {
return game.settings.get(SYSTEM_RDD, "liste-nombre-astral") ?? [];
}
/* -------------------------------------------- */ /* -------------------------------------------- */
getDateFromIndex(index) { getDateFromIndex(index) {
@@ -210,12 +301,13 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
getNombreAstral(indexDate) { getNombreAstral(indexDate) {
let astralData = this.getListeNombreAstral().find((nombreAstral, i) => nombreAstral.index == indexDate); const listNombreAstral = this.getListeNombreAstral();
let astralData = listNombreAstral.find((nombreAstral, i) => nombreAstral.index == indexDate);
return astralData?.nombreAstral; return astralData?.nombreAstral;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rebuildListeNombreAstral(showDice = SHOW_DICE) { async rebuildListeNombreAstral(showDice = HIDE_DICE) {
if (Misc.isUniqueConnectedGM()) { if (Misc.isUniqueConnectedGM()) {
let jourCourant = this.getCurrentDayIndex(); let jourCourant = this.getCurrentDayIndex();
let newList = []; let newList = [];
@@ -228,9 +320,8 @@ export class RdDCalendrier extends Application {
newList[i] = await this.ajouterNombreAstral(dayIndex, showDice); newList[i] = await this.ajouterNombreAstral(dayIndex, showDice);
} }
} }
//console.log("SAVE list", newList, jourCourant); game.settings.set(SYSTEM_RDD, "liste-nombre-astral", newList);
this.listeNombreAstral = newList; this.listeNombreAstral = newList;
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.listeNombreAstral);
} }
} }
@@ -323,6 +414,7 @@ export class RdDCalendrier extends Application {
formData.moisKey = mois.key; formData.moisKey = mois.key;
formData.jourMois = this.calendrier.jour + 1; formData.jourMois = this.calendrier.jour + 1;
formData.nomMois = mois.label; // heures et mois nommés identiques formData.nomMois = mois.label; // heures et mois nommés identiques
formData.annee = this.calendrier.annee;
formData.iconMois = dossierIconesHeures + mois.icon; formData.iconMois = dossierIconesHeures + mois.icon;
formData.nomHeure = heure.label; formData.nomHeure = heure.label;
formData.iconHeure = dossierIconesHeures + heure.icon; formData.iconHeure = dossierIconesHeures + heure.icon;
@@ -471,7 +563,7 @@ export class RdDCalendrier extends Application {
updateDisplay() { updateDisplay() {
let calendrier = this.fillCalendrierData(); let calendrier = this.fillCalendrierData();
// Rebuild text du calendrier // Rebuild text du calendrier
let dateHTML = `Jour ${calendrier.jourMois} de ${calendrier.nomMois} (${calendrier.nomSaison})` let dateHTML = `${calendrier.jourMois} ${calendrier.nomMois} ${calendrier.annee} (${calendrier.nomSaison})`
if (game.user.isGM) { if (game.user.isGM) {
dateHTML = dateHTML + " - NA: " + (this.getCurrentNombreAstral() ?? "indéterminé"); dateHTML = dateHTML + " - NA: " + (this.getCurrentNombreAstral() ?? "indéterminé");
} }
@@ -494,6 +586,7 @@ export class RdDCalendrier extends Application {
this.calendrier.minutesRelative = Number(calendrierData.minutesRelative); this.calendrier.minutesRelative = Number(calendrierData.minutesRelative);
this.calendrier.jour = Number(calendrierData.jourMois) - 1; this.calendrier.jour = Number(calendrierData.jourMois) - 1;
this.calendrier.moisRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.moisKey); this.calendrier.moisRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.moisKey);
this.calendrier.annee = Number(calendrierData.annee);
this.calendrier.heureRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.heureKey); this.calendrier.heureRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.heureKey);
game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier)); game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier));
@@ -553,97 +646,4 @@ export class RdDCalendrier extends Application {
astrologieEditeur.updateData(calendrierData); astrologieEditeur.updateData(calendrierData);
astrologieEditeur.render(true); astrologieEditeur.render(true);
} }
/* -------------------------------------------- */
/** @override */
async activateListeners(html) {
super.activateListeners(html);
this.updateDisplay();
html.find('.ajout-chronologie').click(ev => DialogChronologie.create());
html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));
html.find('.calendar-btn-edit').click(ev => {
ev.preventDefault();
this.showCalendarEditor();
});
html.find('.astrologie-btn-edit').click(ev => {
ev.preventDefault();
this.showAstrologieEditor();
});
html.find('#calendar-move-handle').mousedown(ev => {
ev.preventDefault();
ev = ev || window.event;
let isRightMB = false;
if ("which" in ev) { // Gecko (Firefox), WebKit (Safari/Chrome) & Opera
isRightMB = ev.which == 3;
} else if ("button" in ev) { // IE, Opera
isRightMB = ev.button == 2;
}
if (!isRightMB) {
dragElement(document.getElementById("calendar-time-container"));
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
function dragElement(elmnt) {
elmnt.onmousedown = dragMouseDown;
function dragMouseDown(e) {
e = e || window.event;
e.preventDefault();
pos3 = e.clientX;
pos4 = e.clientY;
document.onmouseup = closeDragElement;
document.onmousemove = elementDrag;
}
function elementDrag(e) {
e = e || window.event;
e.preventDefault();
// calculate the new cursor position:
pos1 = pos3 - e.clientX;
pos2 = pos4 - e.clientY;
pos3 = e.clientX;
pos4 = e.clientY;
// set the element's new position:
elmnt.style.bottom = undefined
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
}
function closeDragElement() {
// stop moving when mouse button is released:
elmnt.onmousedown = undefined;
document.onmouseup = undefined;
document.onmousemove = undefined;
let xPos = (elmnt.offsetLeft - pos1) > window.innerWidth ? window.innerWidth - 200 : (elmnt.offsetLeft - pos1);
let yPos = (elmnt.offsetTop - pos2) > window.innerHeight - 20 ? window.innerHeight - 100 : (elmnt.offsetTop - pos2)
xPos = xPos < 0 ? 0 : xPos;
yPos = yPos < 0 ? 0 : yPos;
if (xPos != (elmnt.offsetLeft - pos1) || yPos != (elmnt.offsetTop - pos2)) {
elmnt.style.top = (yPos) + "px";
elmnt.style.left = (xPos) + "px";
}
game.system.rdd.calendrier.calendrierPos.top = yPos;
game.system.rdd.calendrier.calendrierPos.left = xPos;
if (game.user.isGM) {
game.settings.set(SYSTEM_RDD, "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos));
}
}
}
} else if (isRightMB) {
game.system.rdd.calendrier.calendrierPos.top = 200;
game.system.rdd.calendrier.calendrierPos.left = 200;
if (game.user.isGM) {
game.settings.set(SYSTEM_RDD, "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos));
}
this.setPos(game.system.rdd.calendrier.calendrierPos);
}
});
}
} }

View File

@@ -52,6 +52,11 @@ export class RdDCarac {
return selectedCarac?.label?.toLowerCase()?.match(/r(e|ê)ve(( |-)actuel)?/); return selectedCarac?.label?.toLowerCase()?.match(/r(e|ê)ve(( |-)actuel)?/);
} }
static isActionPhysique(selectedCarac) {
return !selectedCarac ||
selectedCarac?.label.match(/(Apparence|Force|Agilité|Dextérité|Vue|Ouïe|Odorat-Goût|Empathie|Dérobée|Mêlée|Tir|Lancer)/);
}
static isIgnoreEtatGeneral(rollData) { static isIgnoreEtatGeneral(rollData) {
const selectedCarac = rollData.selectedCarac; const selectedCarac = rollData.selectedCarac;
return !selectedCarac || return !selectedCarac ||

View File

@@ -1,5 +1,6 @@
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js";
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { DialogSelectTarget } from "./dialog-select-target.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { RdDItemArme } from "./item-arme.js"; import { RdDItemArme } from "./item-arme.js";
import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetence } from "./item-competence.js";
@@ -11,6 +12,7 @@ import { RdDRoll } from "./rdd-roll.js";
import { RdDRollTables } from "./rdd-rolltables.js"; import { RdDRollTables } from "./rdd-rolltables.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js"; import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { STATUSES } from "./settings/status-effects.js"; import { STATUSES } from "./settings/status-effects.js";
import { Targets } from "./targets.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
const premierRoundInit = [ const premierRoundInit = [
@@ -82,7 +84,6 @@ export class RdDCombatManager extends Combat {
console.log(`${game.system.title} | Combat.rollInitiative()`, ids, formula, messageOptions); console.log(`${game.system.title} | Combat.rollInitiative()`, ids, formula, messageOptions);
ids = typeof ids === "string" ? [ids] : ids; ids = typeof ids === "string" ? [ids] : ids;
const currentId = this.combatant._id;
// calculate initiative // calculate initiative
for (let cId = 0; cId < ids.length; cId++) { for (let cId = 0; cId < ids.length; cId++) {
const combatant = this.combatants.get(ids[cId]); const combatant = this.combatants.get(ids[cId]);
@@ -156,12 +157,13 @@ export class RdDCombatManager extends Combat {
let actions = []; let actions = [];
for (const arme of armes) { for (const arme of armes) {
if (arme.system.equipe) { if (arme.system.equipe) {
const dommages = arme.system.dommages; const dommages = arme.system.dommages.toString();
const tableauDommages = dommages.includes("/") ? dommages.split("/") : [dommages, dommages]; const tableauDommages = dommages.includes("/") ? dommages.split("/") : [dommages, dommages];
if (arme.system.unemain && arme.system.deuxmains && !dommages.includes("/")) { if (arme.system.unemain && arme.system.deuxmains && !dommages.includes("/")) {
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)"); ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
} }
if (arme.system.unemain && arme.system.competence) { if ((arme.system.unemain && arme.system.competence) ||
(arme.system.competence.toLowerCase().includes("corps à corps"))) {
actions.push(RdDCombatManager.$prepareAttaqueArme({ actions.push(RdDCombatManager.$prepareAttaqueArme({
arme: arme, arme: arme,
infoMain: "(1 main)", infoMain: "(1 main)",
@@ -220,12 +222,11 @@ export class RdDCombatManager extends Combat {
static listActionsCreature(competences) { static listActionsCreature(competences) {
return competences.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it)) return competences.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
.map(it => RdDItemCompetenceCreature.toActionArme(it)); .map(it => RdDItemCompetenceCreature.armeNaturelle(it));
} }
static listActionsPossessions(actor) { static listActionsPossessions(actor) {
return RdDCombatManager._indexActions(actor.getPossessions().map(p => return RdDCombatManager._indexActions(actor.getPossessions().map(p => {
{
return { return {
name: p.name, name: p.name,
action: 'conjurer', action: 'conjurer',
@@ -244,7 +245,7 @@ export class RdDCombatManager extends Combat {
if (actions.length > 0) { if (actions.length > 0) {
return actions; return actions;
} }
if (actor.isCreature()) { if (actor.isCreatureEntite()) {
actions = actions.concat(RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature'])); actions = actions.concat(RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']));
} else { } else {
// Recupération des items 'arme' // Recupération des items 'arme'
@@ -469,49 +470,30 @@ export class RdDCombat {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static createUsingTarget(attacker) { static rddCombatTarget(target, attacker) {
const target = RdDCombat.getTarget()
if (target == undefined) {
ui.notifications.warn((game.user.targets?.size ?? 0) > 1
? "Vous devez choisir <strong>une seule</strong> cible à attaquer!"
: "Vous devez choisir une cible à attaquer!");
}
else {
const defender = target?.actor; const defender = target?.actor;
const defenderTokenId = target?.id; const defenderTokenId = target?.id;
if ( defender.type == 'entite' && defender.system.definition.typeentite == ENTITE_NONINCARNE) {
ui.notifications.warn("Vous ne pouvez pas cibler une entité non incarnée !!!!");
} else {
return this.create(attacker, defender, defenderTokenId, target)
}
}
}
/* -------------------------------------------- */
static getTarget() {
if (game.user.targets && game.user.targets.size == 1) {
for (let target of game.user.targets) {
return target;
}
}
return undefined;
}
/* -------------------------------------------- */
static create(attacker, defender, defenderTokenId, target = undefined) {
return new RdDCombat(attacker, defender, defenderTokenId, target) return new RdDCombat(attacker, defender, defenderTokenId, target)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static createForAttackerAndDefender(attackerId, defenderTokenId) { static rddCombatForAttackerAndDefender(attackerId, defenderTokenId) {
const attacker = game.actors.get(attackerId); const attacker = game.actors.get(attackerId);
if (defenderTokenId) { let defender = defenderTokenId ? canvas.tokens.get(defenderTokenId)?.actor : undefined;
const defenderToken = canvas.tokens.get(defenderTokenId); let target = undefined
const defender = defenderToken.actor; if (!defenderTokenId || !defender) {
console.warn(`RdDCombat.rddCombatForAttackerAndDefender: appel avec defenderTokenId ${defenderTokenId} incorrect, ou pas de defender correspondant`);
return RdDCombat.create(attacker, defender, defenderTokenId); target = Targets.getTarget()
if (!target) {
return;
} }
return RdDCombat.createUsingTarget(attacker) defenderTokenId = target.id;
defender = target.actor;
if (!defenderTokenId || !defender) {
return;
}
}
return new RdDCombat(attacker, defender, defenderTokenId, target)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -522,7 +504,7 @@ export class RdDCombat {
let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined; let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined;
defender.encaisserDommages(attackerRoll, attacker); defender.encaisserDommages(attackerRoll, attacker);
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId); const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
rddCombat?.removeChatMessageActionsPasseArme(attackerRoll.passeArme); rddCombat?.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
} }
} }
@@ -531,7 +513,7 @@ export class RdDCombat {
static onMsgDefense(msg) { static onMsgDefense(msg) {
let defenderToken = canvas.tokens.get(msg.defenderTokenId); let defenderToken = canvas.tokens.get(msg.defenderTokenId);
if (defenderToken && Misc.isUniqueConnectedGM()) { if (defenderToken && Misc.isUniqueConnectedGM()) {
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId); const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme); rddCombat?.removeChatMessageActionsPasseArme(msg.defenderRoll.passeArme);
rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll); rddCombat?._chatMessageDefense(msg.paramChatDefense, msg.defenderRoll);
} }
@@ -558,11 +540,10 @@ export class RdDCombat {
'#echec-total-attaque', '#echec-total-attaque',
]) { ]) {
html.on("click", button, event => { html.on("click", button, event => {
const rddCombat = RdDCombat.createForAttackerAndDefender( const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(
event.currentTarget.attributes['data-attackerId']?.value, event.currentTarget.attributes['data-attackerId']?.value,
event.currentTarget.attributes['data-defenderTokenId']?.value); event.currentTarget.attributes['data-defenderTokenId']?.value);
if (rddCombat) { if (rddCombat) {
rddCombat.onEvent(button, event); rddCombat.onEvent(button, event);
event.preventDefault(); event.preventDefault();
} }
@@ -714,7 +695,8 @@ export class RdDCombat {
if (this.defender.isEntite([ENTITE_BLURETTE])) { if (this.defender.isEntite([ENTITE_BLURETTE])) {
ChatMessage.create({ ChatMessage.create({
content: `<strong>La cible est une blurette, l'arme à distance sera perdue dans le blurêve`, content: `<strong>La cible est une blurette, l'arme à distance sera perdue dans le blurêve`,
whisper: ChatMessage.getWhisperRecipients("GM")}) whisper: ChatMessage.getWhisperRecipients("GM")
})
} }
else { else {
const defenderToken = canvas.tokens.get(this.defenderTokenId); const defenderToken = canvas.tokens.get(this.defenderTokenId);
@@ -784,7 +766,7 @@ export class RdDCombat {
// whisper: ChatMessage.getWhisperRecipients("GM")}) // whisper: ChatMessage.getWhisperRecipients("GM")})
// } // }
if (!await this.accorderEntite('avant-attaque')) { if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
return; return;
} }
if (arme.system.cac == 'empoignade' && this.attacker.isCombatTouche()) { if (arme.system.cac == 'empoignade' && this.attacker.isCombatTouche()) {
@@ -807,10 +789,8 @@ export class RdDCombat {
await this.proposerAjustementTirLancer(rollData) await this.proposerAjustementTirLancer(rollData)
const dialog = await RdDRoll.create(this.attacker, rollData, const dialog = await RdDRoll.create(this.attacker, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
{ {
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
options: { height: 540 }
}, {
name: 'jet-attaque', name: 'jet-attaque',
label: 'Attaque: ' + (arme?.name ?? competence.name), label: 'Attaque: ' + (arme?.name ?? competence.name),
callbacks: [ callbacks: [
@@ -836,10 +816,11 @@ export class RdDCombat {
competence: competence, competence: competence,
surprise: this.attacker.getSurprise(true), surprise: this.attacker.getSurprise(true),
surpriseDefenseur: this.defender.getSurprise(true), surpriseDefenseur: this.defender.getSurprise(true),
targetToken: Targets.extractTokenData(this.target),
essais: {} essais: {}
}; };
if (this.attacker.isCreature()) { if (this.attacker.isCreatureEntite()) {
RdDItemCompetenceCreature.setRollDataCreature(rollData); RdDItemCompetenceCreature.setRollDataCreature(rollData);
} }
else if (arme) { else if (arme) {
@@ -904,7 +885,7 @@ export class RdDCombat {
} }
await RdDResolutionTable.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.html'); await RdDResolutionTable.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.html');
if (!await this.accorderEntite('avant-defense')) { if (!await this.attacker.accorder(this.defender, 'avant-defense')) {
return; return;
} }
@@ -1057,8 +1038,7 @@ export class RdDCombat {
const arme = this.defender.getArmeParade(armeParadeId); const arme = this.defender.getArmeParade(armeParadeId);
console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme); console.log("RdDCombat.parade >>>", attackerRoll, armeParadeId, arme);
const competence = arme?.system?.competence; const competence = arme?.system?.competence;
if (competence == undefined) if (competence == undefined) {
{
console.error("Pas de compétence de parade associée à ", arme?.name, armeParadeId); console.error("Pas de compétence de parade associée à ", arme?.name, armeParadeId);
return; return;
} }
@@ -1066,10 +1046,8 @@ export class RdDCombat {
let rollData = this._prepareParade(attackerRoll, arme, competence); let rollData = this._prepareParade(attackerRoll, arme, competence);
const dialog = await RdDRoll.create(this.defender, rollData, const dialog = await RdDRoll.create(this.defender, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
{ {
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
options: { height: 540 }
}, {
name: 'jet-parade', name: 'jet-parade',
label: 'Parade: ' + (arme ? arme.name : rollData.competence.name), label: 'Parade: ' + (arme ? arme.name : rollData.competence.name),
callbacks: [ callbacks: [
@@ -1100,7 +1078,7 @@ export class RdDCombat {
show: {} show: {}
}; };
if (this.defender.isCreature()) { if (this.defender.isCreatureEntite()) {
RdDItemCompetenceCreature.setRollDataCreature(defenderRoll); RdDItemCompetenceCreature.setRollDataCreature(defenderRoll);
} }
@@ -1149,7 +1127,8 @@ export class RdDCombat {
let rollData = this._prepareEsquive(attackerRoll, esquive); let rollData = this._prepareEsquive(attackerRoll, esquive);
const dialog = await RdDRoll.create(this.defender, rollData, const dialog = await RdDRoll.create(this.defender, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' }, { { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
{
name: 'jet-esquive', name: 'jet-esquive',
label: 'Esquiver', label: 'Esquiver',
callbacks: [ callbacks: [
@@ -1178,7 +1157,7 @@ export class RdDCombat {
show: {} show: {}
}; };
if (this.defender.isCreature()) { if (this.defender.isCreatureEntite()) {
RdDItemCompetenceCreature.setRollDataCreature(rollData); RdDItemCompetenceCreature.setRollDataCreature(rollData);
} }
return rollData; return rollData;
@@ -1339,35 +1318,6 @@ export class RdDCombat {
this.removeChatMessageActionsPasseArme(attackerRoll.passeArme); this.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
} }
/* -------------------------------------------- */
/* retourne true si on peut continuer, false si on ne peut pas continuer */
async accorderEntite(when = 'avant-encaissement') {
if (when != game.settings.get(SYSTEM_RDD, "accorder-entite-cauchemar")
|| this.defender == undefined
|| !this.defender.isEntite([ENTITE_INCARNE])
|| this.defender.isEntiteAccordee(this.attacker)) {
return true;
}
let rolled = await RdDResolutionTable.roll(this.attacker.getReveActuel(), - Number(this.defender.system.carac.niveau.value));
let message = {
content: "Jet de points actuels de rêve à " + rolled.finalLevel + RdDResolutionTable.explain(rolled) + "<br>",
whisper: ChatMessage.getWhisperRecipients(this.attacker.name)
};
if (rolled.isSuccess) {
await this.defender.setEntiteReveAccordee(this.attacker);
message.content += this.attacker.name + " s'est accordé avec " + this.defender.name;
}
else {
message.content += this.attacker.name + " n'est pas accordé avec " + this.defender.name;
}
ChatMessage.create(message);
return rolled.isSuccess;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async displayActorCombatStatus(combat, actor) { static async displayActorCombatStatus(combat, actor) {
let formData = { let formData = {

View File

@@ -3,7 +3,6 @@
import { DialogChronologie } from "./dialog-chronologie.js"; import { DialogChronologie } from "./dialog-chronologie.js";
import { DialogCreateSigneDraconique } from "./dialog-create-signedraconique.js"; import { DialogCreateSigneDraconique } from "./dialog-create-signedraconique.js";
import { DialogStress } from "./dialog-stress.js"; import { DialogStress } from "./dialog-stress.js";
import { Grammar } from "./grammar.js";
import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetence } from "./item-competence.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDCarac } from "./rdd-carac.js"; import { RdDCarac } from "./rdd-carac.js";
@@ -14,7 +13,7 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js"; import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
import { RdDRollTables } from "./rdd-rolltables.js"; import { RdDRollTables } from "./rdd-rolltables.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
import { TMRRencontres } from "./tmr-rencontres.js"; import { CompendiumTableHelpers } from "./settings/system-compendiums.js";
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/; const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
@@ -23,55 +22,99 @@ const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
export class RdDCommands { export class RdDCommands {
static init() { static init() {
if (!game.system.rdd.commands) {
const rddCommands = new 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(true), descr: "Tire une Queue de Dragon" });
rddCommands.registerCommand({ path: ["/table", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe(true), descr: "Tire une Idée fixe" });
rddCommands.registerCommand({ path: ["/table", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant(true), descr: "Tire un Désir Lancinant" });
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: ["/meteo"], func: (content, msg, params) => rddCommands.getMeteo(msg, params), descr: "Propose une météo marine" });
rddCommands.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
rddCommands.registerCommand({ Hooks.on("chatMessage", (html, content, msg) => {
path: ["/tmr"], func: (content, msg, params) => rddCommands.findTMR(msg, params), if (content[0] == '/') {
let regExp = /(\S+)/g;
let commands = content.match(regExp);
if (rddCommands.processChatCommand(commands, content, msg)) {
return false;
}
}
return true;
});
game.system.rdd.commands = rddCommands;
}
constructor() {
this.commandsTable = undefined;
}
_registerCommands() {
this.commandsTable = {}
this.registerCommand({ path: ["/aide"], func: (content, msg, params) => this.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
this.registerCommand({ path: ["/help"], func: (content, msg, params) => this.help(msg), descr: "Affiche l'aide pour toutes les commandes" });
this.registerCommand({ path: ["/liste", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence('liste'), descr: "Affiche la liste des compétences" });
this.registerCommand({ path: ["/table", "queue"], func: (content, msg, params) => RdDRollTables.getQueue('liste'), descr: "Affiche la table des Queues de Dragon" });
this.registerCommand({ path: ["/table", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre('liste'), descr: "Affiche la table des Ombres de Thanatos" });
this.registerCommand({ path: ["/table", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR('liste'), descr: "Affiche la table des Têtes de Dragon pour Hauts Revants" });
this.registerCommand({ path: ["/table", "tete"], func: (content, msg, params) => RdDRollTables.getTete('liste'), descr: "Affiche la table des Tête de Dragon pour tous" });
this.registerCommand({ path: ["/table", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle('liste'), descr: "Affiche la table des Souffles de Dragon" });
this.registerCommand({ path: ["/table", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot('liste'), descr: "Affiche la table les cartes du Tarot Draconique" });
this.registerCommand({ path: ["/table", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe('liste'), descr: "Affiche la table des Idées fixes" });
this.registerCommand({ path: ["/table", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant('liste'), descr: "Affiche la table des Désirs Lancinants" });
this.registerCommand({
path: ["/table", "rencontre"], func: (content, msg, params) => this.tableRencontres(msg, params),
descr: `Affiche la table des Rencontres
<br><strong>/table rencontre deso</strong> affiche la table des rencontres en Désolation
<br><strong>/table rencontre mauvaise</strong> affiche la table des mauvaises rencontres`
});
this.registerCommand({ path: ["/table", "milieu"], func: (content, msg, params) => this.tableMilieu(msg, params, 'liste'), descr: "Affiche la table des ressource naturelles pour un milieu donné" });
this.registerCommand({ path: ["/tirer", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence('chat'), descr: "Tire une compétence au hasard" });
this.registerCommand({ path: ["/tirer", "queue"], func: (content, msg, params) => RdDRollTables.getQueue('chat'), descr: "Tire une Queue de Dragon" });
this.registerCommand({ path: ["/tirer", "ombre"], func: (content, msg, params) => RdDRollTables.getOmbre('chat'), descr: "Tire une Ombre de Thanatos" });
this.registerCommand({ path: ["/tirer", "tetehr"], func: (content, msg, params) => RdDRollTables.getTeteHR('chat'), descr: "Tire une Tête de Dragon pour Hauts Revants" });
this.registerCommand({ path: ["/tirer", "tete"], func: (content, msg, params) => RdDRollTables.getTete('chat'), descr: "Tire une Tête de Dragon" });
this.registerCommand({ path: ["/tirer", "souffle"], func: (content, msg, params) => RdDRollTables.getSouffle('chat'), descr: "Tire un Souffle de Dragon" });
this.registerCommand({ path: ["/tirer", "tarot"], func: (content, msg, params) => RdDRollTables.getTarot('chat'), descr: "Tire une carte du Tarot Draconique" });
this.registerCommand({ path: ["/tirer", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe('chat'), descr: "Tire une Idée fixe" });
this.registerCommand({ path: ["/tirer", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant('chat'), descr: "Tire un Désir Lancinant" });
this.registerCommand({ path: ["/tirer", "rencontre"], func: (content, msg, params) => this.getRencontreTMR(params), descr: `Détermine une rencontre dans les TMR (synonyme de "/tmrr")` });
this.registerCommand({ path: ["/tirer", "milieu"], func: (content, msg, params) => this.tableMilieu(msg, params, 'chat'), descr: "Effectue un tirage dans la table desressource naturelles pour un milieu donné" });
this.registerCommand({ path: ["/meteo"], func: (content, msg, params) => this.getMeteo(msg, params), descr: "Propose une météo marine" });
this.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
this.registerCommand({
path: ["/tmr"], func: (content, msg, params) => this.findTMR(msg, params),
descr: `Cherche où se trouve une case des Terres médianes descr: `Cherche où se trouve une case des Terres médianes
<br><strong>/tmr sord</strong> indique que la cité Sordide est en D13 <br><strong>/tmr sord</strong> indique que la cité Sordide est en D13
<br><strong>/tmr foret</strong> donne la liste des TMR dont le nom contient "foret" (donc, toutes les forêts)` }); <br><strong>/tmr foret</strong> donne la liste des TMR dont le nom contient "foret" (donc, toutes les forêts)`
rddCommands.registerCommand({ });
path: ["/tmra"], func: (content, msg, params) => rddCommands.getTMRAleatoire(msg, params), this.registerCommand({
path: ["/tmra"], func: (content, msg, params) => this.getTMRAleatoire(msg, params),
descr: `Tire une case aléatoire des Terres médianes descr: `Tire une case aléatoire des Terres médianes
<br><strong>/tmra forêt</strong> détermine une 'forêt' aléatoire <br><strong>/tmra forêt</strong> détermine une 'forêt' aléatoire
<br><strong>/tmra</strong> détermine une case aléatoire dans toutes les TMR` }); <br><strong>/tmra</strong> détermine une case aléatoire dans toutes les TMR`
rddCommands.registerCommand({ });
path: ["/tmrr"], func: (content, msg, params) => rddCommands.getRencontreTMR(params), this.registerCommand({
descr: `Détermine une rencontre dans un type de case path: ["/tmrr"], func: (content, msg, params) => this.getRencontreTMR(params),
descr: `Détermine une rencontre dans les TMR
<br><strong>/tmrr forêt</strong> détermine une rencontre aléatoire en 'forêt' <br><strong>/tmrr forêt</strong> détermine une rencontre aléatoire en 'forêt'
<br><strong>/tmrr mauvaise</strong> détermine une mauvaise rencontre aléatoire <br><strong>/tmrr mauvaise</strong> détermine une mauvaise rencontre aléatoire
<br><strong>/tmrr for 47</strong> détermine la rencontre en 'forêt' pour un jet de dé de 47` <br><strong>/tmrr for 47</strong> détermine la rencontre en 'forêt' pour un jet de dé de 47`
}); });
rddCommands.registerCommand({ this.registerCommand({
path: ["/xp", "comp"], func: (content, msg, params) => rddCommands.getCoutXpComp(msg, params), path: ["/xp", "comp"], func: (content, msg, params) => this.getCoutXpComp(msg, params),
descr: `Détermine le coût d'expérience pour augmenter une compétence. Exemples: descr: `Détermine le coût d'expérience pour augmenter une compétence. Exemples:
<br>/xp comp -6 1: pour passer de -6 à +1 <br>/xp comp -6 1: pour passer de -6 à +1
<br>/xp comp +4: pour atteindre le niveau 4 (depuis +3)` <br>/xp comp +4: pour atteindre le niveau 4 (depuis +3)`
}); });
rddCommands.registerCommand({ this.registerCommand({
path: ["/xp", "carac"], func: (content, msg, params) => rddCommands.getCoutXpCarac(msg, params), path: ["/xp", "carac"], func: (content, msg, params) => this.getCoutXpCarac(msg, params),
descr: `Détermine le coût d'expérience pour augmenter une caractéristique. Exemples: descr: `Détermine le coût d'expérience pour augmenter une caractéristique. Exemples:
<br>/xp carac 15: coût pour atteindre 15 (depuis 14)` <br>/xp carac 15: coût pour atteindre 15 (depuis 14)`
}); });
rddCommands.registerCommand({ this.registerCommand({
path: ["/rdd"], func: (content, msg, params) => rddCommands.rollRdd(msg, params), path: ["/rdd"], func: (content, msg, params) => this.rollRdd(msg, params),
descr: `Effectue un jet de dés dans la table de résolution. Exemples: descr: `Effectue un jet de dés dans la table de résolution. Exemples:
<br><strong>/rdd</strong> ouvre la table de résolution <br><strong>/rdd</strong> ouvre la table de résolution
<br><strong>/rdd 10 3</strong> effectue un jet 10 à +3 <br><strong>/rdd 10 3</strong> effectue un jet 10 à +3
@@ -81,15 +124,15 @@ export class RdDCommands {
<br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés <br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés
` `
}); });
rddCommands.registerCommand({ path: ["/ddr"], func: (content, msg, params) => rddCommands.rollDeDraconique(msg), descr: "Lance un Dé Draconique" }); this.registerCommand({ path: ["/ddr"], func: (content, msg, params) => this.rollDeDraconique(msg), descr: "Lance un Dé Draconique" });
rddCommands.registerCommand({ this.registerCommand({
path: ["/payer"], func: (content, msg, params) => RdDUtility.afficherDemandePayer(params[0], params[1]), path: ["/payer"], func: (content, msg, params) => RdDUtility.afficherDemandePayer(params[0], params[1]),
descr: `Demande aux joueurs de payer un montant. Exemples: descr: `Demande aux joueurs de payer un montant. Exemples:
<br><strong>/payer 5s 10d</strong> permet d'envoyer un message pour payer 5 sols et 10 deniers <br><strong>/payer 5s 10d</strong> permet d'envoyer un message pour payer 5 sols et 10 deniers
<br><strong>/payer 10d</strong> permet d'envoyer un message pour payer 10 deniers` <br><strong>/payer 10d</strong> permet d'envoyer un message pour payer 10 deniers`
}); });
rddCommands.registerCommand({ this.registerCommand({
path: ["/astro"], func: (content, msg, params) => RdDUtility.afficherHeuresChanceMalchance(Misc.join(params, ' ')), path: ["/astro"], func: (content, msg, params) => RdDUtility.afficherHeuresChanceMalchance(Misc.join(params, ' ')),
descr: `Affiche les heures de chance et de malchance selon l'heure de naissance donnée en argument. Exemples pour l'heure de la Lyre: descr: `Affiche les heures de chance et de malchance selon l'heure de naissance donnée en argument. Exemples pour l'heure de la Lyre:
<br><strong>/astro 7</strong> <br><strong>/astro 7</strong>
@@ -97,18 +140,18 @@ export class RdDCommands {
<br><strong>/astro Lyr</strong>` <br><strong>/astro Lyr</strong>`
}); });
rddCommands.registerCommand({ this.registerCommand({
path: ["/signe", "+"], func: (content, msg, params) => rddCommands.creerSignesDraconiques(), path: ["/signe", "+"], func: (content, msg, params) => this.creerSignesDraconiques(),
descr: "Crée un signe draconique et l'ajoute aux haut-rêvants choisis." descr: "Crée un signe draconique et l'ajoute aux haut-rêvants choisis."
}); });
rddCommands.registerCommand({ this.registerCommand({
path: ["/signe", "-"], func: (content, msg, params) => rddCommands.supprimerSignesDraconiquesEphemeres(), path: ["/signe", "-"], func: (content, msg, params) => this.supprimerSignesDraconiquesEphemeres(),
descr: "Supprime les signes draconiques éphémères" descr: "Supprime les signes draconiques éphémères"
}); });
rddCommands.registerCommand({ this.registerCommand({
path: ["/stress"], func: (content, msg, params) => rddCommands.distribuerStress(params), path: ["/stress"], func: (content, msg, params) => this.distribuerStress(params),
descr: `Distribue du stress aux personnages. Exemples: descr: `Distribue du stress aux personnages. Exemples:
<br><strong>/stress</strong> : Ouvre une fenêtre pour donner du stress ou de l'expérience à un ensemble de personnages <br><strong>/stress</strong> : Ouvre une fenêtre pour donner du stress ou de l'expérience à un ensemble de personnages
<br><strong>/stress 6</strong> : Distribue 6 points des Stress à tout les personnages joueurs, sans raison renseignée <br><strong>/stress 6</strong> : Distribue 6 points des Stress à tout les personnages joueurs, sans raison renseignée
@@ -116,16 +159,10 @@ export class RdDCommands {
<br><strong>/stress 6 Glou Paulo</strong> : Distribue 6 points de Stress au personnage Paulon ou au personnage joueur Paulo, à cause d'un Glou` <br><strong>/stress 6 Glou Paulo</strong> : Distribue 6 points de Stress au personnage Paulon ou au personnage joueur Paulo, à cause d'un Glou`
}); });
rddCommands.registerCommand({ this.registerCommand({
path: ["/chrono"], func: (content, msg, params) => DialogChronologie.create(), path: ["/chrono"], func: (content, msg, params) => DialogChronologie.create(),
descr: `Enregistre une entrée de chronologie dans un article de journal` descr: `Enregistre une entrée de chronologie dans un article de journal`
}); });
game.system.rdd.commands = rddCommands;
}
}
constructor() {
this.commandsTable = {};
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -167,18 +204,29 @@ export class RdDCommands {
processChatCommand(commandLine, content = '', msg = {}) { processChatCommand(commandLine, content = '', msg = {}) {
// Setup new message's visibility // Setup new message's visibility
let rollMode = game.settings.get("core", "rollMode"); let rollMode = game.settings.get("core", "rollMode");
if (["gmroll", "blindroll"].includes(rollMode)) msg["whisper"] = ChatMessage.getWhisperRecipients("GM"); if (["gmroll", "blindroll"].includes(rollMode)) {
if (rollMode === "blindroll") msg["blind"] = true; msg["whisper"] = ChatMessage.getWhisperRecipients("GM");
}
if (rollMode === "blindroll"){
msg["blind"] = true;
}
msg["type"] = 0; msg["type"] = 0;
let command = commandLine[0].toLowerCase(); if (!this.commandsTable) {
let params = commandLine.slice(1); this._registerCommands();
return this.process(command, params, content, msg);
} }
process(command, params, content, msg) { let command = commandLine[0].toLowerCase();
return this._processCommand(this.commandsTable, command, params, content, msg); if (this._isCommandHandled(command)) {
let params = commandLine.slice(1);
this._processCommand(this.commandsTable, command, params, content, msg);
return true;
}
return false;
}
_isCommandHandled(command){
return this.commandsTable[command] != undefined;
} }
async _processCommand(commandsTable, name, params, content = '', msg = {}, path = "") { async _processCommand(commandsTable, name, params, content = '', msg = {}, path = "") {
@@ -186,18 +234,20 @@ export class RdDCommands {
path = path + name + " "; path = path + name + " ";
if (command && command.subTable) { if (command && command.subTable) {
if (params[0]) { if (params[0]) {
return this._processCommand(command.subTable, params[0], params.slice(1), content, msg, path) this._processCommand(command.subTable, params[0], params.slice(1), content, msg, path)
} }
else { else {
this.help(msg, command.subTable); this.help(msg, command.subTable);
}
return true; return true;
} }
}
if (command && command.func) { if (command && command.func) {
new Promise(async () => {
const result = await command.func(content, msg, params); const result = await command.func(content, msg, params);
if (result == false) { if (result == false) {
RdDCommands._chatAnswer(msg, command.descr); RdDCommands._chatAnswer(msg, command.descr);
} }
});
return true; return true;
} }
return false; return false;
@@ -208,10 +258,10 @@ export class RdDCommands {
this.help(msg, undefined); this.help(msg, undefined);
} }
async help(msg, table) { async help(msg, table) {
let list = [] let commands = []
this._buildSubTableHelp(list, table || this.commandsTable); this._buildSubTableHelp(commands, table ?? this.commandsTable);
let html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/settings/dialog-aide-commands.html", { commands: list }); let html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/settings/dialog-aide-commands.html", { commands: commands });
let d = new Dialog( let d = new Dialog(
{ {
title: "Commandes disponibles dans le tchat", title: "Commandes disponibles dans le tchat",
@@ -249,7 +299,7 @@ export class RdDCommands {
/* -------------------------------------------- */ /* -------------------------------------------- */
async getRencontreTMR(params) { async getRencontreTMR(params) {
if (params.length == 1 || params.length == 2) { if (params.length == 1 || params.length == 2) {
return TMRRencontres.rollRencontre(params[0], params[1]) return game.system.rdd.rencontresTMR.rollRencontre(params[0], params[1])
} }
return false; return false;
} }
@@ -281,7 +331,7 @@ export class RdDCommands {
diff = 0; diff = 0;
} }
const caracName = params[0]; const caracName = params[0];
let competence = length > 1 ? actors[0].getCompetence(Misc.join(params.slice(1, length), ' ')) : undefined; let competence = length > 1 ? actors[0].getCompetence(Misc.join(params.slice(1, length), ' ')) : {name:undefined};
if (competence) { if (competence) {
for (let actor of actors) { for (let actor of actors) {
await actor.rollCaracCompetence(caracName, competence.name, diff); await actor.rollCaracCompetence(caracName, competence.name, diff);
@@ -336,6 +386,44 @@ export class RdDCommands {
return false; return false;
} }
async tableRencontres(msg, params) {
if (params && params.length > 0) {
const search = Misc.join(params, ' ');
const solvedTerrain = TMRUtility.findTMRLike(search);
if (solvedTerrain == undefined) {
return RdDCommands._chatAnswer(msg, 'Aucune TMR correspondant à ' + search);
}
return await game.system.rdd.rencontresTMR.chatTable(solvedTerrain);
}
return false;
}
async tableMilieu(msg, params, toChat) {
if (params && params.length > 0) {
const search = Misc.join(params, ' ');
const milieux = await game.system.rdd.environnement.findEnvironnementsLike(search);
if (milieux.length == 0) {
const tous = Object.values(await game.system.rdd.environnement.milieux());
return RdDCommands._chatAnswer(msg, `<strong>Aucun milieu correspondant à '${search}'.</strong>
<br>Milieux disponibles:
<br><ul class="chat-list"><li>${tous.reduce(Misc.joining('</li><li>'))}</li></ul>`);
}
if (milieux.length > 1) {
ui.notifications.warn(`<strong>Plusieurs milieux correspondent à '${search}'</strong>:
<br><ul class="chat-list"><li>${milieux.reduce(Misc.joining('</li><li>'))}</li></ul>`);
}
const tableName = `ressources en ${milieux.reduce(Misc.joining(', '))}`;
if (toChat == 'liste') {
return await game.system.rdd.environnement.searchToChatMessage(milieux, tableName);
}
else {
const row = await game.system.rdd.environnement.getRandom(milieux, tableName);
await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item');
return true;
}
}
return false;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
getCoutXpComp(msg, params) { getCoutXpComp(msg, params) {
if (params && (params.length == 1 || params.length == 2)) { if (params && (params.length == 1 || params.length == 2)) {

View File

@@ -45,7 +45,7 @@ export class RdDConfirm {
return { return {
"actionSave": { "actionSave": {
icon: '<i class="fas fa-user-check"></i>', icon: '<i class="fas fa-user-check"></i>',
label: "Toujours "+ options.buttonLabel.toLowerCase(), label: options.buttonLabel + "<br>et ne plus demander",
callback: () => { callback: () => {
ReglesOptionelles.set(options.settingConfirmer, false); ReglesOptionelles.set(options.settingConfirmer, false);
options.onAction(); options.onAction();

View File

@@ -1,6 +1,7 @@
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
import { RdDCalendrier } from "./rdd-calendrier.js"; import { RdDCalendrier } from "./rdd-calendrier.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDHerbes extends Item { export class RdDHerbes extends Item {
@@ -12,9 +13,8 @@ export class RdDHerbes extends Item {
} }
static async listCategorieHerbes(categorie) { static async listCategorieHerbes(categorie) {
return await RdDUtility.loadItems( const herbes = await SystemCompendiums.getWorldOrCompendiumItems('herbe', 'faune-flore-mineraux');
it => it.type == 'herbe' && it.system.categorie.toLowerCase() == categorie.toLowerCase(), return herbes.filter(it => Grammar.equalsInsensitive(it.system.categorie, categorie));
'foundryvtt-reve-de-dragon.botanique');
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@@ -1,4 +1,3 @@
import { Misc } from "./misc.js";
export class RdDHotbar { export class RdDHotbar {

View File

@@ -1,13 +1,3 @@
/**
* RdD system
* Author: LeRatierBretonnien
* Software License: GNU GPLv3
*/
/* -------------------------------------------- */
/* -------------------------------------------- */
// Import Modules
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { RdDActor } from "./actor.js"; import { RdDActor } from "./actor.js";
import { RdDItemSheet } from "./item-sheet.js"; import { RdDItemSheet } from "./item-sheet.js";
@@ -26,7 +16,6 @@ import { ChatUtility } from "./chat-utility.js";
import { StatusEffects } from "./settings/status-effects.js"; import { StatusEffects } from "./settings/status-effects.js";
import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js"; import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js";
import { ReglesOptionelles } from "./settings/regles-optionelles.js"; import { ReglesOptionelles } from "./settings/regles-optionelles.js";
import { TMRRencontres } from "./tmr-rencontres.js";
import { RdDHotbar } from "./rdd-hotbar-drop.js" import { RdDHotbar } from "./rdd-hotbar-drop.js"
import { EffetsDraconiques } from "./tmr/effets-draconiques.js"; import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { RdDHerbes } from "./rdd-herbes.js"; import { RdDHerbes } from "./rdd-herbes.js";
@@ -39,26 +28,48 @@ import { Migrations } from './migrations.js';
import { DialogChronologie } from "./dialog-chronologie.js"; import { DialogChronologie } from "./dialog-chronologie.js";
import { SystemCompendiums } from "./settings/system-compendiums.js"; import { SystemCompendiums } from "./settings/system-compendiums.js";
import { RdDRencontreItemSheet } from "./item-rencontre-sheet.js"; import { RdDRencontreItemSheet } from "./item-rencontre-sheet.js";
import { TMRRencontres } from "./tmr-rencontres.js";
import { RdDHerbeItemSheet } from "./item-herbe-sheet.js";
import { Environnement } from "./environnement.js";
import { RdDIngredientItemSheet } from "./item-ingredient-sheet.js";
import { RdDFauneItemSheet } from "./item-faune-sheet.js";
import { RdDConteneurItemSheet } from "./item-conteneur-sheet.js";
import { RdDServiceItemSheet } from "./item-service-sheet.js";
import { RdDItemService } from "./item-service.js";
/**
* RdD system
* Author: LeRatierBretonnien
* Software License: GNU GPLv3
*/
export class SystemReveDeDragon {
static start() {
const system = new SystemReveDeDragon();
Hooks.once('init', async () => await system.onInit());
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d));
}
constructor() {
this.RdDUtility = RdDUtility;
this.RdDHotbar = RdDHotbar;
this.itemClasses = {
service: RdDItemService
}
this.actorClasses = {
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
/* -------------------------------------------- */ /* -------------------------------------------- */
async onInit() {
game.system.rdd = this;
/************************************************************************************/
Hooks.once("init", async function () {
console.log(`Initializing Reve de Dragon System`); console.log(`Initializing Reve de Dragon System`);
// preload handlebars templates // preload handlebars templates
RdDUtility.preloadHandlebarsTemplates(); RdDUtility.preloadHandlebarsTemplates();
// Create useful storage space
game.system.rdd = {
TMRUtility,
RdDUtility,
RdDHotbar,
RdDPossession,
}
/* -------------------------------------------- */ /* -------------------------------------------- */
game.settings.register(SYSTEM_RDD, "accorder-entite-cauchemar", { game.settings.register(SYSTEM_RDD, "accorder-entite-cauchemar", {
@@ -84,15 +95,6 @@ Hooks.once("init", async function () {
type: Object type: Object
}); });
/* -------------------------------------------- */
game.settings.register(SYSTEM_RDD, "migration-png-webp-1.5.34", {
name: "calendrier",
scope: "world",
config: false,
default: false,
type: Boolean
});
/* -------------------------------------------- */ /* -------------------------------------------- */
game.settings.register(SYSTEM_RDD, "liste-nombre-astral", { game.settings.register(SYSTEM_RDD, "liste-nombre-astral", {
name: "liste-nombre-astral", name: "liste-nombre-astral",
@@ -184,21 +186,20 @@ Hooks.once("init", async function () {
Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true }); Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true });
Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true }); Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true });
Items.unregisterSheet("core", ItemSheet); Items.unregisterSheet("core", ItemSheet);
Items.registerSheet(SYSTEM_RDD, RdDSigneDraconiqueItemSheet, {
label: "Signe draconique", RdDItemSheet.register(RdDSigneDraconiqueItemSheet);
types: ["signedraconique"], RdDItemSheet.register(RdDRencontreItemSheet);
makeDefault: true RdDItemSheet.register(RdDConteneurItemSheet);
}); RdDItemSheet.register(RdDHerbeItemSheet);
Items.registerSheet(SYSTEM_RDD, RdDRencontreItemSheet, { RdDItemSheet.register(RdDFauneItemSheet);
label: "Rencontre", RdDItemSheet.register(RdDIngredientItemSheet);
types: ["rencontre"], RdDItemSheet.register(RdDServiceItemSheet);
makeDefault: true
});
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, { Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
types: [ types: [
"competence", "competencecreature", "competence", "competencecreature",
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre", "recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
"objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "objet", "arme", "armure", "livre", "potion", "munition",
"monnaie", "nourritureboisson", "gemme", "monnaie", "nourritureboisson", "gemme",
"meditation", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve", "meditation", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
"nombreastral", "tache", "maladie", "poison", "possession", "nombreastral", "tache", "maladie", "poison", "possession",
@@ -223,49 +224,23 @@ Hooks.once("init", async function () {
TMRUtility.init(); TMRUtility.init();
RdDHotbar.initDropbar(); RdDHotbar.initDropbar();
RdDPossession.init(); RdDPossession.init();
}); TMRRencontres.init();
Environnement.init();
/* -------------------------------------------- */ Hooks.once('ready', () => this.onReady());
function messageDeBienvenue() {
if (game.user.isGM) {
ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">');
ChatMessage.create({
user: game.user.id,
content: `<div id="message-bienvenue-rdd"><span class="rdd-roll-part">Bienvenue dans le Rêve des Dragons !</span>
<br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs}
<br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div>
` });
}
} }
/* -------------------------------------------- */ async onReady() {
// Register world usage statistics
function registerUsageCount( registerKey ) {
if ( game.user.isGM ) {
game.settings.register("world", "world-key", {
name: "Unique world key",
scope: "world",
config: false,
default: "NONE",
type: String
});
let worldKey = game.settings.get("world", "world-key")
if ( worldKey == undefined || worldKey == "" ) {
worldKey = randomID(32)
game.settings.set("world", "world-key", worldKey )
}
let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.version}"`
$.ajax(regURL)
/* -------------------------------------------- */
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
/* -------------------------------------------- */ /* -------------------------------------------- */
Hooks.once("ready", async function () { // CSS patch for v9
await migrationPngWebp_1_5_34() if (game.version) {
let sidebar = document.getElementById("sidebar");
sidebar.style.width = "min-content";
}
if (Misc.isUniqueConnectedGM()) { if (Misc.isUniqueConnectedGM()) {
new Migrations().migrate(); new Migrations().migrate();
} }
@@ -292,63 +267,48 @@ Hooks.once("ready", async function () {
}); });
} }
if (Misc.isUniqueConnectedGM()) { if (Misc.isUniqueConnectedGM()) {
messageDeBienvenue(); this.messageDeBienvenue();
registerUsageCount( SYSTEM_RDD ); this.registerUsageCount(SYSTEM_RDD);
} }
});
async function migrationPngWebp_1_5_34() {
if (!game.settings.get(SYSTEM_RDD, "migration-png-webp-1.5.34")) {
const regexOldPngJpg = /(systems\/foundryvtt-reve-de-dragon\/icons\/.*)\.(png|jpg)/;
const replaceWithWebp = '$1.webp';
function convertImgToWebp(img) {
return img.replace(regexOldPngJpg, replaceWithWebp);
}
function prepareDocumentsImgUpdate(documents) {
return documents.filter(it => it.img && it.img.match(regexOldPngJpg))
.map(it => {
return { _id: it.id, img: convertImgToWebp(it.img) }
});
}
const itemsUpdates = prepareDocumentsImgUpdate(game.items);
const actorsUpdates = prepareDocumentsImgUpdate(game.actors);
//Migrate system png to webp
await Item.updateDocuments(itemsUpdates);
await Actor.updateDocuments(actorsUpdates);
game.actors.forEach(actor => {
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
actor.update({ "token.img": convertImgToWebp(actor.token.img) });
}
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
});
game.settings.set(SYSTEM_RDD, "migration-png-webp-1.5.34", true)
}
// CSS patch for v9
if (game.version) {
let sidebar = document.getElementById("sidebar");
sidebar.style.width = "min-content";
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Dice-so-nice ready */ messageDeBienvenue() {
/* -------------------------------------------- */ if (game.user.isGM) {
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d)); ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">');
ChatMessage.create({
user: game.user.id,
content: `<div id="message-bienvenue-rdd"><span class="rdd-roll-part">Bienvenue dans le Rêve des Dragons !</span>
<br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs}
<br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div>
` });
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Foundry VTT chat message */ // Register world usage statistics
/* -------------------------------------------- */ async registerUsageCount(registerKey) {
Hooks.on("chatMessage", (html, content, msg) => { if (game.user.isGM) {
if (content[0] == '/') { game.settings.register("world", "world-key", {
let regExp = /(\S+)/g; name: "Unique world key",
let commands = content.match(regExp); scope: "world",
if (game.system.rdd.commands.processChatCommand(commands, content, msg)) { config: false,
return false; default: "NONE",
} type: String
}
return true;
}); });
let worldKey = game.settings.get("world", "world-key")
if (worldKey == undefined || worldKey == "") {
worldKey = randomID(32)
game.settings.set("world", "world-key", worldKey)
}
let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.version}"`
$.ajax(regURL)
/* -------------------------------------------- */
}
}
}
SystemReveDeDragon.start();

View File

@@ -3,6 +3,7 @@ import { RdDCombat } from "./rdd-combat.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDRoll } from "./rdd-roll.js"; import { RdDRoll } from "./rdd-roll.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { Targets } from "./targets.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
/* On part du principe qu'une entité démarre tjs /* On part du principe qu'une entité démarre tjs
@@ -27,7 +28,139 @@ export class RdDPossession {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static updateEtatPossession(possession) { static async onAttaquePossession(target, attacker, competence, suitePossession = undefined) {
const defender = target.actor;
const fromEntite = RdDPossession.searchPossessionFromEntite(attacker, defender);
const isNouvelle = !suitePossession && ! fromEntite;
const possession = (suitePossession ?? fromEntite ?? (await RdDPossession.createPossession(attacker, defender)));
RdDPossession.$updateEtatPossession(possession)
let rollData = {
mode: "possession",
isECNIDefender: false,
competence: competence,
possession: possession,
attacker: attacker,
defender: defender,
targetToken: Targets.extractTokenData(target)
};
if (attacker.isCreatureEntite()) {
RdDItemCompetenceCreature.setRollDataCreature(rollData)
}
await RdDPossession.$rollAttaquePossession(attacker, rollData, isNouvelle);
}
/* -------------------------------------------- */
static async onConjurerPossession(attacker, competence, possession) {
possession = duplicate(possession);
RdDPossession.$updateEtatPossession(possession)
let rollData = {
mode: "possession",
isECNIDefender: true,
competence: competence,
possession: possession,
attacker: attacker,
defender: game.actors.get(possession.system.possesseurid)
};
await RdDPossession.$rollAttaquePossession(attacker, rollData);
}
/* -------------------------------------------- */
static async onDefensePossession(attackerId, defenderId, possessionId) {
let attacker = game.actors.get(attackerId)
let possession = attacker?.getPossession(possessionId)
defenderId = defenderId ?? possession?.system.possesseurid ?? undefined
let defender = game.actors.get(defenderId)
possession = possession ?? defender?.getPossession(possessionId) ?? undefined;
if (!possession) {
ui.notifications.warn("Une erreur s'est produite : Aucune possession trouvée !!")
return
}
possession = duplicate(possession)
// Update for draconic roll
let rollData = {
mode: "conjuration",
isECNIDefender: defender.type == "entite",
possession: possession,
attacker: attacker,
defender: defender,
competence: defender.getDraconicOuPossession(),
selectedCarac: defender.system.carac.reve,
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } }
}
rollData.competence.system.defaut_carac = 'reve-actuel'
await RdDPossession.$rollDefensePossession(defender, rollData);
}
/* -------------------------------------------- */
static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) {
const dialog = await RdDRoll.create(attacker, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
{
name: 'jet-possession',
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',
callbacks: [
{ condition: r => (r.rolled.isSuccess), action: async (r) => await RdDPossession.$onRollPossession(r, true, isNouvelle) },
{ condition: r => (r.rolled.isEchec), action: async (r) => await RdDPossession.$onRollPossession(r, false, isNouvelle) },
]
});
dialog.render(true);
}
/* -------------------------------------------- */
static async $onRollPossession(rollData, isSuccess, isNouvelle = false) {
rollData.possession.isSuccess = isSuccess;
RdDPossession.$updateEtatPossession(rollData.possession);
if (isNouvelle) {
// Creer la possession sur le defenseur
rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()])
}
await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html');
}
/* -------------------------------------------- */
static async $rollDefensePossession(defender, rollData) {
const dialog = await RdDRoll.create(defender, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html' },
{
name: 'conjurer',
label: 'Conjurer une Possession',
callbacks: [
{ action: async (r) => await RdDPossession.$onRollConjuration(r) }
]
}
);
dialog.render(true);
}
/* -------------------------------------------- */
static async $onRollConjuration(rollData) {
let actor = game.actors.get(rollData.possession.system.possedeid)
if (!rollData.rolled.isSuccess) {
if (rollData.isECNIDefender) {
rollData.possession.system.compteur--
} else {
rollData.possession.system.compteur++
}
let update = { _id: rollData.possession._id, "system.compteur": rollData.possession.system.compteur }
await actor.updateEmbeddedDocuments('Item', [update])
}
RdDPossession.$updateEtatPossession(rollData.possession)
await RdDResolutionTable.displayRollData(rollData,rollData.defender, 'chat-resultat-possession.html')
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
// conjuration
actor.deleteEmbeddedDocuments("Item", [rollData.possession._id])
}
}
/* -------------------------------------------- */
static $updateEtatPossession(possession) {
possession.ptsConjuration = 0 possession.ptsConjuration = 0
possession.ptsPossession = 0 possession.ptsPossession = 0
console.log("Possession", possession) console.log("Possession", possession)
@@ -47,121 +180,16 @@ export class RdDPossession {
} }
} }
/* -------------------------------------------- */
static async resultConjuration(rollData) {
let actor = game.actors.get(rollData.possession.system.possedeid)
if (!rollData.rolled.isSuccess) {
if (rollData.isECNIDefender) {
rollData.possession.system.compteur--
} else {
rollData.possession.system.compteur++
}
let update = { _id: rollData.possession._id, "system.compteur": rollData.possession.system.compteur }
await actor.updateEmbeddedDocuments('Item', [update])
}
this.updateEtatPossession(rollData.possession)
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-possession.html')
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
actor.deleteEmbeddedDocuments("Item", [rollData.possession._id])
}
}
/* -------------------------------------------- */
static async onDefensePossession(attackerId, defenderId, possessionId) {
let attacker = game.actors.get(attackerId)
let defender = game.actors.get(defenderId)
let possession = attacker.getPossession(possessionId) ?? defender.getPossession(possessionId) ;
if (!possession) {
ui.notifications.warn("Une erreur s'est produite : Aucune possession trouvée !!")
return
}
// Update for draconic roll
let rollData = {
mode: "conjuration",
isECNIDefender: defender.type == "entite",
possession: duplicate(possession),
attacker: attacker,
defender: defender,
competence: defender.getDraconicOuPossession(),
selectedCarac: defender.system.carac.reve,
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } }
}
rollData.competence.system.defaut_carac = 'reve-actuel'
const dialog = await RdDRoll.create(defender, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html'
},
{
name: 'conjurer',
label: 'Conjurer une Possession',
callbacks: [
{ action: async r => await this.resultConjuration(r) }
]
}
);
dialog.render(true)
}
/* -------------------------------------------- */
static async onAttaquePossession(attacker, competence, possession = undefined) {
const target = RdDCombat.getTarget()
if (target == undefined) {
ui.notifications.warn((game.user.targets?.size ?? 0) > 1
? "Vous devez choisir <strong>une seule</strong> cible à posséder!"
: "Vous devez choisir une cible à posséder!");
return;
}
const defender = target.actor;
possession = duplicate(possession ?? this.searchPossessionFromEntite(attacker, defender) ??(await this.createPossession(attacker, defender)));
this.updateEtatPossession(possession)
let rollData = {
mode: "possession",
isECNIDefender: defender.type == "entite",
competence: competence,
possession: possession,
attacker: attacker,
defender: defender
};
if (attacker.isCreature()) {
RdDItemCompetenceCreature.setRollDataCreature(rollData)
}
const dialog = await RdDRoll.create(attacker, rollData,
{
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html'
}, {
name: 'jet-possession',
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',
callbacks: [
{ condition: r => (r.rolled.isSuccess), action: async r => await this._onRollPossession(r, true) },
{ condition: r => (r.rolled.isEchec), action: async r => await this._onRollPossession(r, false) },
]
});
dialog.render(true)
}
/* -------------------------------------------- */
static async _onRollPossession(rollData, isSuccess) {
rollData.possession.isSuccess = isSuccess;
this.updateEtatPossession(rollData.possession);
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-possession.html');
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async createPossession(attacker, defender) { static async createPossession(attacker, defender) {
let possessionData = { return await Item.create({
name: "Possession en cours de " + attacker.name, type: 'possession', name: "Possession en cours de " + attacker.name, type: 'possession',
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp", img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
system: { description: "", typepossession: attacker.name, possede: false, possessionid: randomID(16), possesseurid: attacker.id, possedeid: defender.id, date: 0, compteur: 0 } system: { description: "", typepossession: attacker.name, possede: false, possessionid: randomID(16), possesseurid: attacker.id, possedeid: defender.id, date: 0, compteur: 0 }
} },
// Creates only the possession on the personnage side {
let poss = await defender.createEmbeddedDocuments('Item', [possessionData]) temporary: true
return duplicate(poss[0]) })
} }
} }

View File

@@ -42,6 +42,44 @@ export class RdDResolutionTable {
return table; return table;
} }
/* -------------------------------------------- */
static computeChances(carac, level) {
if (level < -16) {
return levelImpossible;
}
if (level < -10) {
return levelDown.find(it => it.level == level);
}
const percentage = RdDResolutionTable.computePercentage(carac, level);
return this._computeCell(level, percentage);
}
/* -------------------------------------------- */
static _computeRow(caracValue) {
let dataRow = [
this._computeCell(-10, Math.max(Math.floor(caracValue / 4), 1)),
this._computeCell(-9, Math.max(Math.floor(caracValue / 2), 1))
]
for (var diff = -8; diff <= 22; diff++) {
dataRow[diff + 10] = this._computeCell(diff, RdDResolutionTable.computePercentage(caracValue, diff));
}
return dataRow;
}
/* -------------------------------------------- */
static _computeCell(niveau, percentage) {
return {
niveau: niveau,
score: percentage,
norm: Math.min(99, percentage),
sign: this._reussiteSignificative(percentage),
part: this._reussitePart(percentage),
epart: this._echecParticulier(percentage),
etotal: this._echecTotal(percentage)
};
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static getResultat(code) { static getResultat(code) {
let resultat = reussites.find(r => code == r.code); let resultat = reussites.find(r => code == r.code);
@@ -51,17 +89,6 @@ export class RdDResolutionTable {
return resultat; return resultat;
} }
/* -------------------------------------------- */
static explain(rolled) {
let message = "<br>Jet : <strong>" + rolled.roll + "</strong> sur " + rolled.score + "% ";
if (rolled.caracValue != undefined && rolled.finalLevel != undefined) {
message += (rolled.diviseurSignificative > 1 ? `(1/${rolled.diviseurSignificative} de ` : "(")
+ rolled.caracValue + " à " + Misc.toSignedString(rolled.finalLevel) + ") ";
}
message += '<strong>' + rolled.quality + '</strong>'
return message;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.html') { static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.html') {
return await ChatUtility.createChatWithRollMode(actor?.userName ?? game.user.name, { return await ChatUtility.createChatWithRollMode(actor?.userName ?? game.user.name, {
@@ -83,7 +110,7 @@ export class RdDResolutionTable {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async roll(caracValue, finalLevel, rollData = {}) { static async roll(caracValue, finalLevel, rollData = {}) {
let chances = this.computeChances(caracValue, finalLevel); let chances = duplicate(this.computeChances(caracValue, finalLevel));
this._updateChancesWithBonus(chances, rollData.bonus, finalLevel); this._updateChancesWithBonus(chances, rollData.bonus, finalLevel);
this._updateChancesFactor(chances, rollData.diviseurSignificative); this._updateChancesFactor(chances, rollData.diviseurSignificative);
chances.showDice = rollData.showDice; chances.showDice = rollData.showDice;
@@ -103,13 +130,24 @@ export class RdDResolutionTable {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static findNiveauNecessaire(caracValue, rollValue) { static findNiveauNecessaire(carac, rolled) {
for (let cell of this.resolutionTable[caracValue]) { if (carac == 0) {
if ( rollValue <= cell.norm) { return NaN;
return cell.niveau;
} }
if (rolled >= carac){
const upper = Math.ceil(rolled/carac);
return 2*upper -10
} }
return 16; // Dummy default if (rolled > Math.floor(carac/2)) {
return -8
}
if (rolled > Math.floor(carac/4)) {
return -9
}
if (rolled > 1) {
return -10
}
return -11;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -149,14 +187,12 @@ export class RdDResolutionTable {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeChances(caracValue, difficulte) { static computePercentage(carac, diff) {
if (difficulte < -16) { if (diff < -16) return 0
return duplicate(levelImpossible); if (diff < -10) return 1
} if (diff == -10) return Math.max(Math.floor(carac / 4), 1)
if (difficulte < -10) { if (diff == -9) return Math.max(Math.floor(carac / 2), 1)
return duplicate(levelDown.find(levelData => levelData.level == difficulte)); return Math.max(Math.floor(carac * (diff + 10) / 2), 1);
}
return duplicate(RdDResolutionTable.resolutionTable[caracValue][difficulte + 10]);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -213,31 +249,6 @@ export class RdDResolutionTable {
return reussite; return reussite;
} }
/* -------------------------------------------- */
static _computeRow(caracValue) {
let dataRow = [
this._computeCell(-10, Math.max(Math.floor(caracValue / 4), 1)),
this._computeCell(-9, Math.max(Math.floor(caracValue / 2), 1))
]
for (var diff = -8; diff <= 22; diff++) {
dataRow[diff + 10] = this._computeCell(diff, Math.max(Math.floor(caracValue * (diff + 10) / 2), 1));
}
return dataRow;
}
/* -------------------------------------------- */
static _computeCell(niveau, percentage) {
return {
niveau: niveau,
score: percentage,
norm: Math.min(99, percentage),
sign: this._reussiteSignificative(percentage),
part: this._reussitePart(percentage),
epart: this._echecParticulier(percentage),
etotal: this._echecTotal(percentage)
};
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static _reussiteSignificative(percentage) { static _reussiteSignificative(percentage) {
return Math.floor(percentage / 2); return Math.floor(percentage / 2);
@@ -261,92 +272,34 @@ export class RdDResolutionTable {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static buildHTMLResults(caracValue, levelValue) { static subTable(carac, level, delta = { carac: 2, level: 5}) {
if (caracValue == undefined || isNaN(caracValue)) caracValue = 10; return {
if (levelValue == undefined || isNaN(levelValue)) levelValue = 0; carac,
level,
let cell = this.computeChances(caracValue, levelValue); minCarac: carac - (delta?.carac ?? 2),
cell.epart = cell.epart > 99 ? 'N/A' : cell.epart; maxCarac: carac + (delta?.carac ?? 2),
cell.etotal = cell.etotal > 100 ? 'N/A' : cell.etotal; minLevel: level - (delta?.level ?? 5),
cell.score = Math.min(cell.score, 99); maxLevel: level + (delta?.level ?? 5)
};
return `
<span class="table-proba-reussite competence-label">
Particulière: <span class="rdd-roll-part">${cell.part}</span>
- Significative: <span class="rdd-roll-sign">${cell.sign}</span>
- Réussite: <span class="rdd-roll-norm">${cell.score}</span>
- Echec Particulier: <span class="rdd-roll-epart">${cell.epart}</span>
- Echec Total: <span class="rdd-roll-etotal">${cell.etotal}</span>
</span>
`
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static buildHTMLTableExtract(caracValue, levelValue) { static async buildHTMLTable({ carac: carac, level: level, minCarac = 1, maxCarac = 21, minLevel = -10, maxLevel = 11 }) {
return this.buildHTMLTable(caracValue, levelValue, caracValue - 2, caracValue + 2, levelValue - 5, levelValue + 5) let colonnes = maxLevel - minLevel;
}
static buildHTMLTable(caracValue, levelValue, minCarac = 1, maxCarac = 21, minLevel = -10, maxLevel = 11) {
return this._buildHTMLTable(caracValue, levelValue, minCarac, maxCarac, minLevel, maxLevel)
}
/* -------------------------------------------- */
static _buildHTMLTable(caracValue, levelValue, minCarac, maxCarac, minLevel, maxLevel) {
let countColonnes = maxLevel - minLevel;
minCarac = Math.max(minCarac, 1); minCarac = Math.max(minCarac, 1);
maxCarac = Math.min(maxCarac, caracMaximumResolution); maxCarac = Math.min(maxCarac, minCarac + 20);
minLevel = Math.max(minLevel, -10); minLevel = Math.max(minLevel, -10);
maxLevel = Math.max(Math.min(maxLevel, 22), minLevel + countColonnes); maxLevel = Math.max(Math.min(maxLevel, 30), minLevel + colonnes);
return await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/resolution-table.html', {
let table = $("<table class='table-resolution'/>") carac: carac,
.append(this._buildHTMLHeader(RdDResolutionTable.resolutionTable[0], minLevel, maxLevel)); difficulte: level,
min: minLevel,
for (var rowIndex = minCarac; rowIndex <= maxCarac; rowIndex++) { rows: RdDResolutionTable.incrementalArray(minCarac, maxCarac),
table.append(this._buildHTMLRow(RdDResolutionTable.resolutionTable[rowIndex], rowIndex, caracValue, levelValue, minLevel, maxLevel)); cols: RdDResolutionTable.incrementalArray(minLevel, maxLevel)
});
} }
table.append("</table>"); static incrementalArray(min, max) {
return table; return Array.from(Array(max-min+1).keys()).map(i=>i+min)
}
/* -------------------------------------------- */
static _buildHTMLHeader(dataRow, minLevel, maxLevel) {
let tr = $("<tr/>");
if (minLevel > -8) {
tr.append($("<th class='table-resolution-level'/>").text("-8"))
}
if (minLevel > -7) {
tr.append($("<th class='table-resolution-level'/>").text("..."));
}
for (let difficulte = minLevel; difficulte <= maxLevel; difficulte++) {
tr.append($("<th class='table-resolution-level'/>").text(Misc.toSignedString(difficulte)));
}
return tr;
}
/* -------------------------------------------- */
static _buildHTMLRow(dataRow, rowIndex, caracValue, levelValue, minLevel, maxLevel) {
let tr = $("<tr/>");
let max = maxLevel;
if (minLevel > -8) {
let score = dataRow[-8 + 10].score;
tr.append($("<td class='table-resolution-carac'/>").text(score))
}
if (minLevel > -7) {
tr.append($("<td/>"))
}
for (let difficulte = minLevel; difficulte <= max; difficulte++) {
let td = $("<td/>");
let score = dataRow[difficulte + 10].score;
if (rowIndex == caracValue && levelValue == difficulte) {
td.addClass('table-resolution-target');
} else if (difficulte == -8) {
td.addClass('table-resolution-carac');
}
tr.append(td.text(score));
}
return tr;
} }
} }

View File

@@ -1,4 +1,5 @@
import { ENTITE_BLURETTE, ENTITE_INCARNE } from "./constants.js"; import { ENTITE_BLURETTE, ENTITE_INCARNE } from "./constants.js";
import { RdDUtility } from "./rdd-utility.js";
/** /**
* Extend the base Dialog entity by defining a custom window to perform roll. * Extend the base Dialog entity by defining a custom window to perform roll.
@@ -6,32 +7,37 @@ import { ENTITE_BLURETTE, ENTITE_INCARNE} from "./constants.js";
*/ */
export class RdDEncaisser extends Dialog { export class RdDEncaisser extends Dialog {
static async encaisser(actor) {
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html',
{ ajustementsEncaissement: RdDUtility.getAjustementsEncaissement() }
);
new RdDEncaisser(html, actor).render(true);
}
/* -------------------------------------------- */ /* -------------------------------------------- */
constructor(html, actor) { constructor(html, actor) {
// Common conf let dialogConf = {
let buttons = {}; title: "Jet d'Encaissement",
content: html,
}
if (!actor.isEntite()) { if (!actor.isEntite()) {
buttons = { dialogConf.default = "mortel";
dialogConf.buttons = {
"mortel": { label: "Mortel", callback: html => this.performEncaisser("mortel") }, "mortel": { label: "Mortel", callback: html => this.performEncaisser("mortel") },
"non-mortel": { label: "Non-mortel", callback: html => this.performEncaisser("non-mortel") }, "non-mortel": { label: "Non-mortel", callback: html => this.performEncaisser("non-mortel") },
"sonne": { label: "Sonné", callback: html => this.actor.setSonne() }, "sonne": { label: "Sonné", callback: html => this.actor.setSonne() },
}; };
} }
else if (actor.isEntite([ENTITE_BLURETTE, ENTITE_INCARNE])) { else if (actor.isEntite([ENTITE_BLURETTE, ENTITE_INCARNE])) {
buttons = { dialogConf.default = "cauchemar"
"cauchemar": { label: "cauchemar", callback: html => this.performEncaisser("cauchemar") } dialogConf.buttons = {
"cauchemar": { label: "Cauchemar", callback: html => this.performEncaisser("cauchemar") }
} }
} }
let dialogConf = {
title: "Jet d'Encaissement",
content: html,
buttons: buttons,
default: "mortel"
}
let dialogOptions = { let dialogOptions = {
classes: ["rdddialog"], classes: ["rdd-roll-dialog"],
width: 320, width: 320,
height: 'fit-content' height: 'fit-content'
} }
@@ -44,7 +50,18 @@ export class RdDEncaisser extends Dialog {
this.encaisserSpecial = "aucun"; this.encaisserSpecial = "aucun";
} }
activateListeners(html) {
super.activateListeners(html);
this.html = html;
this.html.find('[name="modificateurDegats"]').val("0");
this.html.find('[name="modificateurDegats"]').change((event) => {
this.modifier = event.currentTarget.value; // Update the selected bonus/malus
});
this.html.find('[name="encaisserSpecial"]').change((event) => {
this.encaisserSpecial = event.currentTarget.value; // Update the selected bonus/malus
});
}
/* -------------------------------------------- */ /* -------------------------------------------- */
performEncaisser(mortalite) { performEncaisser(mortalite) {
@@ -58,22 +75,4 @@ export class RdDEncaisser extends Dialog {
} }
}); });
} }
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
// Setup everything onload
$(function () {
$("#modificateurDegats").val("0");
});
html.find('#modificateurDegats').change((event) => {
this.modifier = event.currentTarget.value; // Update the selected bonus/malus
});
html.find('#encaisserSpecial').change((event) => {
this.encaisserSpecial = event.currentTarget.value; // Update the selected bonus/malus
});
}
} }

View File

@@ -13,47 +13,33 @@ export class RdDRollDialogEthylisme extends Dialog {
title: "Test d'éthylisme", title: "Test d'éthylisme",
content: html, content: html,
default: "rollButton", default: "rollButton",
buttons: { "rollButton": { label: "Test d'éthylisme", callback: html => this.onButton(html) } } buttons: { "rollButton": { label: "Test d'éthylisme", callback: html => onRoll(this.rollData) } }
}; };
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 'fit-content', 'z-index': 99999 } let dialogOptions = { classes: ["rdd-roll-dialog"], width: 400, height: 'fit-content', 'z-index': 99999 }
super(dialogConf, dialogOptions) super(dialogConf, dialogOptions)
//console.log("ETH", rollData);
this.onRoll = onRoll;
this.rollData = rollData; this.rollData = rollData;
this.actor = actor; this.actor = actor;
} }
async onButton(html) { activateListeners(html) {
this.onRoll(this.rollData); super.activateListeners(html);
this.html = html;
this.bringToTop();
this.html.find(".force-alcool").change((event) => {
this.rollData.forceAlcool = Misc.toInt(event.currentTarget.value);
this.updateRollResult();
});
this.html.find(".force-alcool").val(Misc.toInt(this.rollData.forceAlcool));
this.updateRollResult();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
this.bringToTop(); // Ensure top level
// Get the rollData stuff
var rollData = this.rollData;
var dialog = this;
// Setup everything onload
$(function () {
$("#forceAlcool").val(Misc.toInt(rollData.forceAlcool));
dialog.updateRollResult();
});
// Update !
html.find('#forceAlcool').change((event) => {
rollData.forceAlcool = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus
dialog.updateRollResult();
});
}
async updateRollResult() { async updateRollResult() {
this.html.find(".roll-ethylisme").text(this.rollData.vie + " / " + Misc.toSignedString(Number(this.rollData.etat) + Number(this.rollData.forceAlcool) + this.rollData.diffNbDoses));
// Mise à jour valeurs this.html.find(".table-resolution").remove();
$("#roll-param").text(this.rollData.vie + " / " + Misc.toSignedString(Number(this.rollData.etat) + Number(this.rollData.forceAlcool) + this.rollData.diffNbDoses));
$(".table-resolution").remove();
} }
} }

View File

@@ -9,12 +9,19 @@ const titleTableDeResolution = 'Table de résolution';
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDRollResolutionTable extends Dialog { export class RdDRollResolutionTable extends Dialog {
static resolutionTable = undefined;
/* -------------------------------------------- */ /* -------------------------------------------- */
static async open(rollData = {}) { static async open() {
if (RdDRollResolutionTable.resolutionTable == undefined) {
const rollData = {}
RdDRollResolutionTable._setDefaultOptions(rollData); RdDRollResolutionTable._setDefaultOptions(rollData);
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html', rollData); let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html', rollData);
const dialog = new RdDRollResolutionTable(rollData, html); RdDRollResolutionTable.resolutionTable = new RdDRollResolutionTable(rollData, html);
dialog.render(true); RdDRollResolutionTable.resolutionTable.render(true);
}
else{
RdDRollResolutionTable.resolutionTable.bringToTop();
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -53,11 +60,40 @@ export class RdDRollResolutionTable extends Dialog {
'lancer-fermer': { label: 'Lancer les dés et fermer', callback: html => this.onLancerFermer() } 'lancer-fermer': { label: 'Lancer les dés et fermer', callback: html => this.onLancerFermer() }
} }
}; };
super(conf, { classes: ["rdddialog"], width: 800, height: 'fit-content', 'z-index': 99999 }); super(conf, { classes: ["rdd-roll-dialog"], top: 50, width: 'fit-content', height: 'fit-content', 'z-index': 99999 });
this.rollData = rollData; this.rollData = rollData;
} }
activateListeners(html) {
super.activateListeners(html);
this.html = html;
this.bringToTop();
this.html.find("[name='diffLibre']").val(Misc.toInt(this.rollData.diffLibre));
this.html.find("[name='diffConditions']").val(Misc.toInt(this.rollData.diffConditions));
this.updateRollResult();
this.html.find('.lancer-table-resolution').click((event) => {
this.onLancer();
});
// Update !
this.html.find("[name='diffLibre']").change((event) => {
this.rollData.diffLibre = Misc.toInt(event.currentTarget.value);
this.updateRollResult();
});
this.html.find("[name='diffConditions']").change((event) => {
this.rollData.diffConditions = Misc.toInt(event.currentTarget.value);
this.updateRollResult();
});
this.html.find("[name='carac']").change((event) => {
let caracKey = event.currentTarget.value;
this.rollData.selectedCarac = this.rollData.carac[caracKey];
this.updateRollResult();
});
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async onLancer() { async onLancer() {
await RdDResolutionTable.rollData(this.rollData); await RdDResolutionTable.rollData(this.rollData);
@@ -72,65 +108,36 @@ export class RdDRollResolutionTable extends Dialog {
await RdDResolutionTable.displayRollData(this.rollData); await RdDResolutionTable.displayRollData(this.rollData);
} }
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
this.bringToTop();
var dialog = this;
// Setup everything onload
function onLoad(){
$("#diffLibre").val(Misc.toInt(dialog.rollData.diffLibre));
$("#diffConditions").val(Misc.toInt(dialog.rollData.diffConditions));
dialog.updateRollResult();
}
$(function () { onLoad();});
html.find('#lancer').click((event) => {
this.onLancer();
});
// Update !
html.find('#diffLibre').change((event) => {
this.rollData.diffLibre = Misc.toInt(event.currentTarget.value);
this.updateRollResult();
});
html.find('#diffConditions').change((event) => {
this.rollData.diffConditions = Misc.toInt(event.currentTarget.value);
this.updateRollResult();
});
html.find('#carac').change((event) => {
let caracKey = event.currentTarget.value;
this.rollData.selectedCarac = this.rollData.carac[caracKey];
this.updateRollResult();
});
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async updateRollResult() { async updateRollResult() {
let rollData = this.rollData; let rollData = this.rollData;
rollData.caracValue = parseInt(rollData.selectedCarac.value) rollData.caracValue = parseInt(rollData.selectedCarac.value)
rollData.finalLevel = this._computeFinalLevel(rollData); rollData.finalLevel = this._computeFinalLevel(rollData);
const htmlTable = await RdDResolutionTable.buildHTMLTable({
carac: rollData.caracValue,
level: rollData.finalLevel,
maxCarac: 20,
maxLevel: 10
});
// Mise à jour valeurs // Mise à jour valeurs
$("#carac").val(rollData.caracValue); this.html.find("[name='carac']").val(rollData.caracValue);
$("#roll-param").text(rollData.selectedCarac.value + " / " + Misc.toSignedString(rollData.finalLevel)); this.html.find(".roll-param-resolution").text(rollData.selectedCarac.value + " / " + Misc.toSignedString(rollData.finalLevel));
$(".table-resolution").remove(); this.html.find("div.placeholder-resolution").empty().append(htmlTable)
$(".table-proba-reussite").remove();
$("#tableResolution").append(RdDResolutionTable.buildHTMLTable(rollData.caracValue, rollData.finalLevel));
$("#tableProbaReussite").append(RdDResolutionTable.buildHTMLResults(rollData.caracValue, rollData.finalLevel));
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_computeFinalLevel(rollData) { _computeFinalLevel(rollData) {
const diffConditions = Misc.toInt(rollData.diffConditions); const diffConditions = Misc.toInt(rollData.diffConditions);
const diffLibre = this._computeDiffLibre(rollData); const diffLibre = Misc.toInt(rollData.diffLibre);
return diffLibre + diffConditions; return diffLibre + diffConditions;
} }
/* -------------------------------------------- */ async close() {
_computeDiffLibre(rollData) { await super.close();
return Misc.toInt(rollData.diffLibre); RdDRollResolutionTable.resolutionTable = undefined;
} }
} }

View File

@@ -16,50 +16,42 @@ import { ReglesOptionelles } from "./settings/regles-optionelles.js";
export class RdDRoll extends Dialog { export class RdDRoll extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async create(actor, rollData, dialogConfig, ...actions) { static async create(actor, rollData, dialogConfig, action) {
RdDRoll._ensureCorrectAction(action);
if (actor.isRollWindowsOpened()) {
ui.notifications.warn("Vous avez déja une fenêtre de Test ouverte, il faut la fermer avant d'en ouvrir une autre.")
return;
}
actor.setRollWindowsOpened(true);
RdDRoll._ensureCorrectActions(actions);
RdDRoll._setDefaultOptions(actor, rollData); RdDRoll._setDefaultOptions(actor, rollData);
const html = await renderTemplate(dialogConfig.html, rollData); const html = await renderTemplate(dialogConfig.html, rollData);
let options = { classes: ["rdddialog"], width: 600, height: 'fit-content', 'z-index': 99999 }; let options = { classes: ["rdd-roll-dialog"], width: 600, height: 'fit-content', 'z-index': 99999, close: html => {} };
if (dialogConfig.options) { if (dialogConfig.close) {
mergeObject(options, dialogConfig.options, { overwrite: true }) options.close = dialogConfig.close;
} }
return new RdDRoll(actor, rollData, html, options, actions, dialogConfig.close); return new RdDRoll(actor, rollData, html, options, action);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _setDefaultOptions(actor, rollData) { static _setDefaultOptions(actor, rollData) {
const actorData = actor.system
let defaultRollData = { let defaultRollData = {
alias: actor.name, alias: actor.name,
ajustementsConditions: CONFIG.RDD.ajustementsConditions, ajustementsConditions: CONFIG.RDD.ajustementsConditions,
difficultesLibres: CONFIG.RDD.difficultesLibres, difficultesLibres: CONFIG.RDD.difficultesLibres,
etat: actor.getEtatGeneral(), etat: actor.getEtatGeneral(),
moral: actor.getMoralTotal(), /* La valeur du moral pour les jets de volonté */ moral: actor.getMoralTotal(), /* La valeur du moral pour les jets de volonté */
carac: actorData.carac, carac: actor.system.carac,
finalLevel: 0, finalLevel: 0,
diffConditions: 0, diffConditions: 0,
diffLibre: rollData.competence?.system.default_diffLibre ?? 0, diffLibre: rollData.competence?.system.default_diffLibre ?? 0,
malusArmureValue: actor.getMalusArmure(),
surencMalusValue: actor.computeMalusSurEncombrement(),
useMoral: false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */
perteMoralEchec: false, /* Pour l'affichage dans le chat */ perteMoralEchec: false, /* Pour l'affichage dans le chat */
use: { use: {
moral: false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */
libre: true, libre: true,
conditions: true, conditions: true,
surenc: false, surenc: actor.isSurenc(),
encTotal: false encTotal: true
}, },
isMalusEncombrementTotal: rollData.competence ? RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) : 0, isMalusEncombrementTotal: RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
malusArmureValue: actor.getMalusArmure(),
surencMalusValue: actor.computeMalusSurEncombrement(),
encTotal: actor.getEncTotal(), encTotal: actor.getEncTotal(),
ajustementAstrologique: actor.ajustementAstrologique(), ajustementAstrologique: actor.ajustementAstrologique(),
surprise: actor.getSurprise(false), surprise: actor.getSurprise(false),
@@ -68,8 +60,8 @@ export class RdDRoll extends Dialog {
forceDiceResult: -1 forceDiceResult: -1
} }
// Mini patch :Ajout du rêve actuel // Mini patch :Ajout du rêve actuel
if ( actorData.type == "personnage") { if (actor.system.type == "personnage") {
defaultRollData.carac["reve-actuel"] = actorData.reve.reve defaultRollData.carac["reve-actuel"] = actor.system.reve.reve
} }
mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false }); mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false });
@@ -80,6 +72,7 @@ export class RdDRoll extends Dialog {
RollDataAjustements.calcul(rollData, actor); RollDataAjustements.calcul(rollData, actor);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getDiviseurSignificative(rollData) { static getDiviseurSignificative(rollData) {
let facteurSign = 1; let facteurSign = 1;
@@ -98,172 +91,133 @@ export class RdDRoll extends Dialog {
return facteurSign; return facteurSign;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _ensureCorrectActions(actions) { static _ensureCorrectAction(action) {
if (actions.length == 0) {
throw 'No action defined';
}
actions.forEach(action => {
if (action.callbacks == undefined) { if (action.callbacks == undefined) {
action.callbacks = [{ action: r => console.log(action.name, r) }]; console.warn('No callback defined for ', action.name);
action.callbacks = [{ action: r => console.warn(action.name, r) }];
} }
});
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
constructor(actor, rollData, html, options, actions, close = undefined) { constructor(actor, rollData, html, options, action) {
let conf = { let conf = {
title: actions[0].label, title: action.label,
content: html, content: html,
buttons: {}, buttons: {
default: actions[0].name, "onAction": {
close: close
};
for (let action of actions) {
conf.buttons[action.name] = {
label: action.label, callback: html => { label: action.label, callback: html => {
this.rollData.canClose = true; this.rollData.canClose = true;
this.onAction(action, html) this.onAction(action)
} }
}
},
default: "onAction",
close: options.close
}; };
}
super(conf, options); super(conf, options);
this.actor = actor; this.actor = actor;
this.rollData = rollData; this.rollData = rollData;
} }
close() {
if (this.rollData.canClose) {
this.actor.setRollWindowsOpened(false);
return super.close();
}
ui.notifications.info("Vous devez faire ce jet de dés!");
}
/* -------------------------------------------- */
async onAction(action, html) {
this.rollData.forceDiceResult = Number.parseInt($('#force-dice-result').val()) ?? -1;
await RdDResolutionTable.rollData(this.rollData);
console.log("RdDRoll -=>", this.rollData, this.rollData.rolled);
this.actor.setRollWindowsOpened(false);
if (action.callbacks)
for (let callback of action.callbacks) {
if (callback.condition == undefined || callback.condition(this.rollData)) {
await callback.action(this.rollData);
}
}
}
/* -------------------------------------------- */
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = html;
this.bringToTop(); this.bringToTop();
var dialog = this; console.log('RdDRoll.activateListeners', this.rollData);
function onLoad() {
let rollData = dialog.rollData;
console.log('Ouverture RdDRoll', rollData);
// Update html, according to rollData // Update html, according to rollData
if (rollData.competence) { if (this.rollData.competence) {
const defaut_carac = rollData.competence.system.defaut_carac const defaut_carac = this.rollData.competence.system.defaut_carac
// Set the default carac from the competence item // Set the default carac from the competence item
rollData.selectedCarac = rollData.carac[defaut_carac]; this.rollData.selectedCarac = this.rollData.carac[defaut_carac];
$("#carac").val(defaut_carac); this.html.find("[name='carac']").val(defaut_carac);
} }
if (rollData.selectedSort) { if (this.rollData.selectedSort) {
dialog.setSelectedSort(rollData.selectedSort); this.setSelectedSort(this.rollData.selectedSort);
$(".draconic").val(rollData.selectedSort.system.listIndex); // Uniquement a la selection du sort, pour permettre de changer this.html.find(".draconic").val(this.rollData.selectedSort.system.listIndex); // Uniquement a la selection du sort, pour permettre de changer
}
RdDItemSort.setCoutReveReel(rollData.selectedSort);
$("#diffLibre").val(Misc.toInt(rollData.diffLibre));
$("#diffConditions").val(Misc.toInt(rollData.diffConditions));
dialog.updateRollResult();
} }
RdDItemSort.setCoutReveReel(this.rollData.selectedSort);
this.html.find("[name='diffLibre']").val(Misc.toInt(this.rollData.diffLibre));
this.html.find("[name='diffConditions']").val(Misc.toInt(this.rollData.diffConditions));
this.updateRollResult(html);
// Setup everything onload this.html.find("[name='diffLibre']").change((event) => {
$(function () { onLoad(); });
// Update !
html.find('#diffLibre').change((event) => {
this.rollData.diffLibre = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus this.rollData.diffLibre = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('#diffConditions').change((event) => { this.html.find("[name='diffConditions']").change((event) => {
this.rollData.diffConditions = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus this.rollData.diffConditions = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('#force-dice-result').change((event) => { this.html.find("[name='force-dice-result']").change((event) => {
this.rollData.forceDiceResult = Misc.toInt(event.currentTarget.value); this.rollData.forceDiceResult = Misc.toInt(event.currentTarget.value);
}); });
html.find('#carac').change((event) => { this.html.find("[name='carac']").change((event) => {
let caracKey = event.currentTarget.value; let caracKey = event.currentTarget.value;
this.rollData.selectedCarac = this.rollData.carac[caracKey]; // Update the selectedCarac this.rollData.selectedCarac = this.rollData.carac[caracKey]; // Update the selectedCarac
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('.roll-draconic').change((event) => { this.html.find('.roll-draconic').change((event) => {
let draconicKey = Misc.toInt(event.currentTarget.value); let draconicKey = Misc.toInt(event.currentTarget.value);
this.rollData.competence = this.rollData.draconicList[draconicKey]; // Update the selectedCarac this.rollData.competence = this.rollData.draconicList[draconicKey]; // Update the selectedCarac
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('.roll-sort').change((event) => { this.html.find('.roll-sort').change((event) => {
let sortKey = Misc.toInt(event.currentTarget.value); let sortKey = Misc.toInt(event.currentTarget.value);
this.setSelectedSort(this.rollData.sortList[sortKey]); this.setSelectedSort(this.rollData.sortList[sortKey]);
this.updateRollResult(); this.updateRollResult(html);
$("#diffLibre").val(this.rollData.diffLibre); this.html.find("[name='diffLibre']").val(this.rollData.diffLibre);
}); });
html.find('.roll-carac-competence').change((event) => { this.html.find('.roll-carac-competence').change((event) => {
const competence = event.currentTarget.value; const competence = event.currentTarget.value;
this.rollData.competence = this.rollData.competences.find(it => it.name == competence); this.rollData.competence = this.rollData.competences.find(it => it.name == competence);
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('.roll-signedraconique').change((event) => { this.html.find('.roll-signedraconique').change((event) => {
let sortKey = Misc.toInt(event.currentTarget.value); let sortKey = Misc.toInt(event.currentTarget.value);
this.setSelectedSigneDraconique(this.rollData.signes[sortKey]); this.setSelectedSigneDraconique(this.rollData.signes[sortKey]);
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('#ptreve-variable').change((event) => { this.html.find("[name='ptreve-variable']").change((event) => {
let ptreve = Misc.toInt(event.currentTarget.value); let ptreve = Misc.toInt(event.currentTarget.value);
this.rollData.selectedSort.system.ptreve_reel = ptreve; this.rollData.selectedSort.system.ptreve_reel = ptreve;
console.log("RdDRollSelectDialog - Cout reve", ptreve); console.log("RdDRollSelectDialog - Cout reve", ptreve);
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find("[name='coupsNonMortels']").change((event) => { this.html.find("[name='coupsNonMortels']").change((event) => {
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel"; this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('.cuisine-proportions').change((event) => { this.html.find('.cuisine-proportions').change((event) => {
this.rollData.proportions = Number(event.currentTarget.value); this.rollData.proportions = Number(event.currentTarget.value);
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('.select-by-name').change((event) => { this.html.find('.select-by-name').change((event) => {
const attribute = event.currentTarget.attributes['name'].value; const attribute = event.currentTarget.attributes['name'].value;
this.rollData[attribute] = event.currentTarget.value; this.rollData[attribute] = event.currentTarget.value;
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('.checkbox-by-name').change((event) => { this.html.find('.checkbox-by-name').change((event) => {
const attribute = event.currentTarget.attributes['name'].value; const attribute = event.currentTarget.attributes['name'].value;
this.rollData[attribute] = event.currentTarget.checked; this.rollData[attribute] = event.currentTarget.checked;
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('input.use-encTotal').change((event) => { this.html.find('input.use-encTotal').change((event) => {
this.rollData.use.encTotal = event.currentTarget.checked; this.rollData.use.encTotal = event.currentTarget.checked;
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('input.use-surenc').change((event) => { this.html.find('input.use-surenc').change((event) => {
this.rollData.use.surenc = event.currentTarget.checked; this.rollData.use.surenc = event.currentTarget.checked;
this.updateRollResult(); this.updateRollResult(html);
}); });
html.find('.appel-moral').click((event) => { /* l'appel au moral, qui donne un bonus de +1 */ this.html.find('.appel-moral').click((event) => { /* l'appel au moral, qui donne un bonus de +1 */
this.rollData.useMoral = !this.rollData.useMoral; this.rollData.use.moral = !this.rollData.use.moral;
const appelMoral = html.find('.icon-appel-moral')[0]; const appelMoral = this.html.find('.icon-appel-moral')[0];
const tooltip = html.find('.tooltipAppelAuMoralText')[0]; const tooltip = this.html.find('.tooltipAppelAuMoralText')[0];
if (this.rollData.useMoral) { if (this.rollData.use.moral) {
if (this.rollData.moral > 0) { if (this.rollData.moral > 0) {
tooltip.innerHTML = "Appel au moral"; tooltip.innerHTML = "Appel au moral";
appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-heureux.svg"; appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-heureux.svg";
@@ -275,16 +229,36 @@ export class RdDRoll extends Dialog {
tooltip.innerHTML = "Sans appel au moral"; tooltip.innerHTML = "Sans appel au moral";
appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-neutre.svg"; appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-neutre.svg";
} }
this.updateRollResult(); this.updateRollResult(html);
}); });
// Section Méditation // Section Méditation
html.find('.conditionMeditation').change((event) => { this.html.find('.conditionMeditation').change((event) => {
let condition = event.currentTarget.attributes['id'].value; let condition = event.currentTarget.attributes['name'].value;
this.rollData.conditionMeditation[condition] = event.currentTarget.checked; this.rollData.conditionMeditation[condition] = event.currentTarget.checked;
this.updateRollResult(); this.updateRollResult(html);
}); });
} }
/* -------------------------------------------- */
close() {
if (this.rollData.canClose) {
return super.close();
}
ui.notifications.info("Vous devez faire ce jet de dés!");
}
async onAction(action) {
this.rollData.forceDiceResult = Number.parseInt(this.html.find("[name='force-dice-result']").val()) ?? -1;
await RdDResolutionTable.rollData(this.rollData);
console.log("RdDRoll -=>", this.rollData, this.rollData.rolled);
if (action.callbacks)
for (let callback of action.callbacks) {
if (callback.condition == undefined || callback.condition(this.rollData)) {
await callback.action(this.rollData);
}
}
}
async setSelectedSort(sort) { async setSelectedSort(sort) {
this.rollData.selectedSort = sort; // Update the selectedCarac this.rollData.selectedSort = sort; // Update the selectedCarac
this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.system.draconic); this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.system.draconic);
@@ -292,21 +266,21 @@ export class RdDRoll extends Dialog {
this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7); this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7);
RdDItemSort.setCoutReveReel(sort); RdDItemSort.setCoutReveReel(sort);
const htmlSortDescription = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html", { sort: sort }); const htmlSortDescription = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html", { sort: sort });
$(".sort-ou-rituel").text(sort.system.isrituel ? "rituel" : "sort"); this.html.find(".sort-ou-rituel").text(sort.system.isrituel ? "rituel" : "sort");
$(".bonus-case").text(`${this.rollData.bonus}%`); this.html.find(".bonus-case").text(`${this.rollData.bonus}%`);
$(".details-sort").remove(); this.html.find(".placeholder-description-sort").children().remove();
$(".description-sort").append(htmlSortDescription); this.html.find(".placeholder-description-sort").append(htmlSortDescription);
$(".roll-draconic").val(sort.system.listIndex); this.html.find(".roll-draconic").val(sort.system.listIndex);
$(".div-sort-difficulte-fixe").text(Misc.toSignedString(sort.system.difficulte)); this.html.find(".div-sort-difficulte-fixe").text(Misc.toSignedString(sort.system.difficulte));
$(".div-sort-ptreve-fixe").text(sort.system.ptreve); this.html.find(".div-sort-ptreve-fixe").text(sort.system.ptreve);
const diffVariable = RdDItemSort.isDifficulteVariable(sort); const diffVariable = RdDItemSort.isDifficulteVariable(sort);
const coutVariable = RdDItemSort.isCoutVariable(sort); const coutVariable = RdDItemSort.isCoutVariable(sort);
HtmlUtility._showControlWhen($(".div-sort-non-rituel"), !sort.system.isrituel); HtmlUtility._showControlWhen(this.html.find(".div-sort-non-rituel"), !sort.system.isrituel);
HtmlUtility._showControlWhen($(".div-sort-difficulte-var"), diffVariable); HtmlUtility._showControlWhen(this.html.find(".div-sort-difficulte-var"), diffVariable);
HtmlUtility._showControlWhen($(".div-sort-difficulte-fixe"), !diffVariable); HtmlUtility._showControlWhen(this.html.find(".div-sort-difficulte-fixe"), !diffVariable);
HtmlUtility._showControlWhen($(".div-sort-ptreve-var"), coutVariable); HtmlUtility._showControlWhen(this.html.find(".div-sort-ptreve-var"), coutVariable);
HtmlUtility._showControlWhen($(".div-sort-ptreve-fixe"), !coutVariable); HtmlUtility._showControlWhen(this.html.find(".div-sort-ptreve-fixe"), !coutVariable);
} }
async setSelectedSigneDraconique(signe) { async setSelectedSigneDraconique(signe) {
@@ -316,7 +290,7 @@ export class RdDRoll extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async updateRollResult() { async updateRollResult(html) {
let rollData = this.rollData; let rollData = this.rollData;
rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat()) rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat())
@@ -334,30 +308,27 @@ export class RdDRoll extends Dialog {
RollDataAjustements.calcul(rollData, this.actor); RollDataAjustements.calcul(rollData, this.actor);
rollData.finalLevel = this._computeFinalLevel(rollData); rollData.finalLevel = this._computeFinalLevel(rollData);
HtmlUtility._showControlWhen($(".use-encTotal"), rollData.ajustements.encTotal.visible); const resolutionTable = await RdDResolutionTable.buildHTMLTable(RdDResolutionTable.subTable(rollData.caracValue, rollData.finalLevel))
HtmlUtility._showControlWhen($(".use-surenc"), rollData.ajustements.surenc.visible); const adjustements = await this.buildAjustements(rollData);
HtmlUtility._showControlWhen($(".diffMoral"), rollData.ajustements.moralTotal.used);
HtmlUtility._showControlWhen($(".divAppelAuMoral"), rollData.use.appelAuMoral); HtmlUtility._showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac));
HtmlUtility._showControlWhen($("#etat-general"), !RdDCarac.isIgnoreEtatGeneral(rollData)); HtmlUtility._showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac));
HtmlUtility._showControlWhen($("#ajust-astrologique"), RdDResolutionTable.isAjustementAstrologique(rollData)); HtmlUtility._showControlWhen(this.html.find(".utilisation-moral"), rollData.use.appelAuMoral);
HtmlUtility._showControlWhen(this.html.find(".diffMoral"), rollData.ajustements.moralTotal.used);
HtmlUtility._showControlWhen(this.html.find(".divAppelAuMoral"), rollData.use.appelAuMoral);
// Mise à jour valeurs // Mise à jour valeurs
$(".dialog-roll-title").text(this._getTitle(rollData)); this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
$("[name='coupsNonMortels']").prop('checked', rollData.mortalite == 'non-mortel'); this.html.find("[name='coupsNonMortels']").prop('checked', rollData.mortalite == 'non-mortel');
$(".dmg-arme-actor").text(dmgText); this.html.find(".dmg-arme-actor").text(dmgText);
$('.table-ajustement').remove(); this.html.find("div.placeholder-ajustements").empty().append(adjustements);
$(".table-resolution").remove(); this.html.find("div.placeholder-resolution").empty().append(resolutionTable)
$(".table-proba-reussite").remove();
$("#tableAjustements").append(await this.buildAjustements(rollData));
$("#tableResolution").append(RdDResolutionTable.buildHTMLTableExtract(rollData.caracValue, rollData.finalLevel));
$("#tableProbaReussite").append(RdDResolutionTable.buildHTMLResults(rollData.caracValue, rollData.finalLevel));
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async buildAjustements(rollData) { async buildAjustements(rollData) {
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html`, rollData); return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html`, rollData);
return html;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -375,23 +346,11 @@ export class RdDRoll extends Dialog {
return 0; return 0;
} }
/* -------------------------------------------- */
_computeDiffLibre(rollData) {
let diffLibre = Misc.toInt(rollData.diffLibre);
if (rollData.draconicList && rollData.selectedSort) {
return RdDItemSort.getDifficulte(rollData.selectedSort, diffLibre);
}
return diffLibre;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
_computeMalusArmure(rollData) { _computeMalusArmure(rollData) {
let malusArmureValue = 0; let malusArmureValue = 0;
if (rollData.malusArmureValue && (rollData.selectedCarac.label == "Agilité" || rollData.selectedCarac.label == "Dérobée")) { if (rollData.malusArmureValue && (rollData.selectedCarac.label == "Agilité" || rollData.selectedCarac.label == "Dérobée")) {
$("#addon-message").text("Malus armure appliqué : " + rollData.malusArmureValue);
malusArmureValue = rollData.malusArmureValue; malusArmureValue = rollData.malusArmureValue;
} else {
$("#addon-message").text("");
} }
return malusArmureValue; return malusArmureValue;
} }

View File

@@ -1,4 +1,5 @@
import { SystemCompendiums } from "./settings/system-compendiums.js"; import { Grammar } from "./grammar.js";
import { CompendiumTable, CompendiumTableHelpers, SystemCompendiums } from "./settings/system-compendiums.js";
export class RdDRollTables { export class RdDRollTables {
@@ -6,9 +7,7 @@ export class RdDRollTables {
static async genericGetTableResult(tableName, toChat) { static async genericGetTableResult(tableName, toChat) {
let table = RdDRollTables.getWorldTable(tableName) ?? (await RdDRollTables.getSystemTable(tableName)); let table = RdDRollTables.getWorldTable(tableName) ?? (await RdDRollTables.getSystemTable(tableName));
const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll" }); const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll" });
//console.log("RdDRollTables", tableName, toChat, ":", draw);
return draw.results.length > 0 ? draw.results[0] : undefined; return draw.results.length > 0 ? draw.results[0] : undefined;
} }
static getWorldTable(tableName) { static getWorldTable(tableName) {
@@ -37,52 +36,68 @@ export class RdDRollTables {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getCompetence(toChat = false) { static async getCompetence(toChat = false) {
if (toChat == 'liste') {
return await RdDRollTables.listOrRoll('competences', 'Item', ['competence'], toChat, it => 1);
}
else {
return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat); return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat);
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getSouffle(toChat = false) { static async getSouffle(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Souffles de Dragon", toChat); return await RdDRollTables.listOrRoll('souffles-de-dragon', 'Item', ['souffle'], toChat);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getQueue(toChat = false) { static async getQueue(toChat = false) {
let queue = await RdDRollTables.drawItemFromRollTable("Queues de dragon", toChat); return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat);
if (queue.name.toLowerCase().includes('lancinant') ) {
return await RdDRollTables.getDesirLancinant(toChat);
}
if (queue.name.toLowerCase().includes('fixe') ) {
return await RdDRollTables.getIdeeFixe(toChat);
}
return queue;
} }
static async getDesirLancinant(toChat = false) { static async getDesirLancinant(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Désirs lancinants", toChat); return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat,
it => it.system.frequence,
it => it.system.categorie == 'lancinant');
} }
static async getIdeeFixe(toChat = false) { static async getIdeeFixe(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Idées fixes", toChat); return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat,
it => it.system.frequence,
it => it.system.categorie == 'ideefixe');
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getTeteHR(toChat = false) { static async getTeteHR(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour haut-rêvants", toChat); return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-haut-revants', 'Item', ['tete'], toChat);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getTete(toChat = false) { static async getTete(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Têtes de Dragon pour tous personnages", toChat); return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-tous-personnages', 'Item', ['tete'], toChat);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getOmbre(toChat = false) { static async getOmbre(toChat = false) {
return await RdDRollTables.drawItemFromRollTable("Ombre de Thanatos", toChat); return await RdDRollTables.listOrRoll('ombres-de-thanatos', 'Item', ['ombre'], toChat);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getTarot(toChat = true) { static async getTarot(toChat = true) {
return await RdDRollTables.drawItemFromRollTable("Tarot Draconique", toChat); return await RdDRollTables.listOrRoll('tarot-draconique', 'Item', ['tarot'], toChat);
}
/* -------------------------------------------- */
static async listOrRoll(compendium, type, subTypes, toChat, itemFrequence = it => it.system.frequence, filter = it => true) {
const table = new CompendiumTable(compendium, type, subTypes);
if (toChat == 'liste') {
return await table.toChatMessage(itemFrequence, filter);
}
const row = await table.getRandom(itemFrequence, filter);
if (row) {
await CompendiumTableHelpers.tableRowToChatMessage(row, type);
return row.document;
}
return undefined;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -91,4 +106,5 @@ export class RdDRollTables {
options.arme ? "Maladresse armé" : "Maladresses non armé", options.arme ? "Maladresse armé" : "Maladresses non armé",
options.toChat); options.toChat);
} }
} }

View File

@@ -19,11 +19,12 @@ export class RdDSheetUtility {
return $(event.currentTarget)?.parents(".item"); return $(event.currentTarget)?.parents(".item");
} }
static prepareItemDropParameters(destItemId, actorId, dragData, objetVersConteneur) { static prepareItemDropParameters(destItemId, actor, dragData, objetVersConteneur) {
const item = fromUuidSync(dragData.uuid) const item = fromUuidSync(dragData.uuid)
if (actor.canReceive(item)) {
return { return {
destId: destItemId, destId: destItemId,
targetActorId: actorId, targetActorId: actor.id,
itemId: item.id, itemId: item.id,
sourceActorId: item.actor?.id, sourceActorId: item.actor?.id,
srcId: objetVersConteneur[item.id], srcId: objetVersConteneur[item.id],
@@ -31,6 +32,11 @@ export class RdDSheetUtility {
onAjouterDansConteneur: (itemId, conteneurId) => { objetVersConteneur[itemId] = conteneurId; } onAjouterDansConteneur: (itemId, conteneurId) => { objetVersConteneur[itemId] = conteneurId; }
} }
} }
else {
ui.notifications.warn(`Impossible de donner ${item.name} à ${actor.name}: ${item.type} / ${actor.type}`);
}
return undefined;
}
static async splitItem(item, actor, onSplit = () => { }) { static async splitItem(item, actor, onSplit = () => { }) {
const dialog = await DialogSplitItem.create(item, async (item, split) => { const dialog = await DialogSplitItem.create(item, async (item, split) => {

View File

@@ -5,7 +5,6 @@ import { TMRUtility } from "./tmr-utility.js";
import { tmrConstants } from "./tmr-constants.js"; import { tmrConstants } from "./tmr-constants.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDTMRRencontreDialog } from "./rdd-tmr-rencontre-dialog.js"; import { RdDTMRRencontreDialog } from "./rdd-tmr-rencontre-dialog.js";
import { TMRRencontres } from "./tmr-rencontres.js";
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js";
import { RdDRoll } from "./rdd-roll.js"; import { RdDRoll } from "./rdd-roll.js";
import { Poetique } from "./poetique.js"; import { Poetique } from "./poetique.js";
@@ -198,32 +197,33 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async activateListeners(html) { async activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = html;
document.getElementById("tmrrow1").insertCell(0).append(this.pixiApp.view); document.getElementById("tmrrow1").insertCell(0).append(this.pixiApp.view);
if (this.viewOnly) { if (this.viewOnly) {
html.find('.lancer-sort').remove(); this.html.find('.lancer-sort').remove();
html.find('.lire-signe-draconique').remove(); this.html.find('.lire-signe-draconique').remove();
return; return;
} }
HtmlUtility._showControlWhen($(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue")); HtmlUtility._showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
HtmlUtility._showControlWhen($(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord())); HtmlUtility._showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord()));
// Roll Sort // Roll Sort
html.find('.lancer-sort').click((event) => { this.html.find('.lancer-sort').click((event) => {
this.actor.rollUnSort(this._getActorCoord()); this.actor.rollUnSort(this._getActorCoord());
}); });
html.find('.lire-signe-draconique').click((event) => { this.html.find('.lire-signe-draconique').click((event) => {
this.actor.rollLireSigneDraconique(this._getActorCoord()); this.actor.rollLireSigneDraconique(this._getActorCoord());
}); });
html.find('#dir-top').click((event) => this.moveFromKey("top")); this.html.find('#dir-top').click((event) => this.moveFromKey("top"));
html.find('#dir-top-left').click((event) => this.moveFromKey("top-left")); this.html.find('#dir-top-left').click((event) => this.moveFromKey("top-left"));
html.find('#dir-top-right').click((event) => this.moveFromKey("top-right")); this.html.find('#dir-top-right').click((event) => this.moveFromKey("top-right"));
html.find('#dir-bottom-left').click((event) => this.moveFromKey("bottom-left")); this.html.find('#dir-bottom-left').click((event) => this.moveFromKey("bottom-left"));
html.find('#dir-bottom-right').click((event) => this.moveFromKey("bottom-right")); this.html.find('#dir-bottom-right').click((event) => this.moveFromKey("bottom-right"));
html.find('#dir-bottom').click((event) => this.moveFromKey("bottom")); this.html.find('#dir-bottom').click((event) => this.moveFromKey("bottom"));
// Gestion du cout de montée en points de rêve // 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(); let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse();
@@ -245,7 +245,7 @@ export class RdDTMRDialog extends Dialog {
} }
const coord = this._getActorCoord(); const coord = this._getActorCoord();
HtmlUtility._showControlWhen($(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord)); HtmlUtility._showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
let ptsreve = document.getElementById("tmr-pointsreve-value"); let ptsreve = document.getElementById("tmr-pointsreve-value");
ptsreve.innerHTML = this.actor.system.reve.reve.value; ptsreve.innerHTML = this.actor.system.reve.reve.value;
@@ -280,7 +280,7 @@ export class RdDTMRDialog extends Dialog {
} }
await this.actor.santeIncDec("fatigue", this.cumulFatigue) await this.actor.santeIncDec("fatigue", this.cumulFatigue)
} }
await super.close(); // moving 1 cell costs 1 fatigue await super.close();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -405,6 +405,8 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _tentativeMaitrise(rencData) { async _tentativeMaitrise(rencData) {
this.rencontreState = 'normal';
rencData.reve = this.actor.getReveActuel(); rencData.reve = this.actor.getReveActuel();
rencData.etat = this.actor.getEtatGeneral(); rencData.etat = this.actor.getEtatGeneral();
@@ -450,7 +452,6 @@ export class RdDTMRDialog extends Dialog {
this._tentativeMaitrise(rencData); this._tentativeMaitrise(rencData);
this._deleteTmrMessages(rencData.actor, rencData.nbRounds); this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
}, 2000); }, 2000);
this.rencontreState == 'normal';
} }
formatMessageRencontre(rencData, template) { formatMessageRencontre(rencData, template) {
@@ -575,7 +576,7 @@ export class RdDTMRDialog extends Dialog {
async _jetDeRencontre(tmr) { async _jetDeRencontre(tmr) {
let rencontre = this.lookupRencontreExistente(tmr); let rencontre = this.lookupRencontreExistente(tmr);
if (rencontre) { if (rencontre) {
return TMRRencontres.calculRencontre(rencontre, tmr); return game.system.rdd.rencontresTMR.calculRencontre(rencontre, tmr);
} }
let locTMR = (this.isDemiReveCache() let locTMR = (this.isDemiReveCache()
? TMRUtility.getTMRType(tmr.coord) + " ??" ? TMRUtility.getTMRType(tmr.coord) + " ??"
@@ -584,7 +585,7 @@ export class RdDTMRDialog extends Dialog {
let myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE }); let myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
if (myRoll == 7) { if (myRoll == 7) {
this._tellToUser(myRoll + ": Rencontre en " + locTMR); this._tellToUser(myRoll + ": Rencontre en " + locTMR);
return await TMRRencontres.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre()) return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
} else { } else {
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR); this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
} }
@@ -775,7 +776,6 @@ export class RdDTMRDialog extends Dialog {
const dialog = await RdDRoll.create(this.actor, rollData, const dialog = await RdDRoll.create(this.actor, rollData,
{ {
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html', html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
options: { height: 'fit-content' },
close: html => { this.maximize(); } // Re-display TMR close: html => { this.maximize(); } // Re-display TMR
}, },
{ {

View File

@@ -1,5 +1,4 @@
/* Common useful functions shared between objects */ /* Common useful functions shared between objects */
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js";
import { RdDCombat } from "./rdd-combat.js"; import { RdDCombat } from "./rdd-combat.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
@@ -14,6 +13,9 @@ import { RdDPossession } from "./rdd-possession.js";
import { RdDNameGen } from "./rdd-namegen.js"; import { RdDNameGen } from "./rdd-namegen.js";
import { RdDConfirm } from "./rdd-confirm.js"; import { RdDConfirm } from "./rdd-confirm.js";
import { RdDCalendrier } from "./rdd-calendrier.js"; import { RdDCalendrier } from "./rdd-calendrier.js";
import { Environnement } from "./environnement.js";
import { RdDItemCompetence } from "./item-competence.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
// This table starts at 0 -> niveau -10 // This table starts at 0 -> niveau -10
@@ -124,6 +126,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/header-hautreve.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html',
@@ -168,6 +171,12 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-suivants.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/liens-suivants.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.html',
//Items //Items
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs',
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/boutons-comestible.html',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.html',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.html',
'systems/foundryvtt-reve-de-dragon/templates/header-item.html', 'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html',
@@ -178,6 +187,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/item-sort-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-sort-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-herbe-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-herbe-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-ingredient-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-ingredient-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-faune-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-livre-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-livre-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-tache-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-tache-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-potion-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-potion-sheet.html',
@@ -193,6 +203,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/item-signedraconique-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-signedraconique-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-possession-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-possession-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-extraitpoetique-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-extraitpoetique-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-service-sheet.html',
// partial enums // partial enums
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
@@ -208,10 +219,12 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html',
// Partials // Partials
'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html',
@@ -224,7 +237,11 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-competences.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-competences.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-item-hautrevant.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-item-frequence.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html',
'systems/foundryvtt-reve-de-dragon/templates/roll/explain.hbs',
'systems/foundryvtt-reve-de-dragon/templates/resolution-table.html',
// Dialogs // Dialogs
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
@@ -269,6 +286,9 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html' 'systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html'
]; ];
Handlebars.registerHelper('either', (a, b) => a ?? b);
Handlebars.registerHelper('computeResolutionScore', (row, col) => RdDResolutionTable.computePercentage(row, col));
Handlebars.registerHelper('computeResolutionChances', (row, col) => RdDResolutionTable.computeChances(row, col));
Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null')); Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null'));
Handlebars.registerHelper('lowerFirst', str => Misc.lowerFirst(str ?? 'Null')); Handlebars.registerHelper('lowerFirst', str => Misc.lowerFirst(str ?? 'Null'));
Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? 'NULL'); Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? 'NULL');
@@ -280,48 +300,28 @@ export class RdDUtility {
Handlebars.registerHelper('buildContenu', (objet) => { return new Handlebars.SafeString(RdDUtility.buildContenu(objet, 1, true)); }); Handlebars.registerHelper('buildContenu', (objet) => { return new Handlebars.SafeString(RdDUtility.buildContenu(objet, 1, true)); });
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord)); Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord)); Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
Handlebars.registerHelper('typeTmr-name', coord => TMRUtility.typeTmrName(coord)); Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type));
Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord)); Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
Handlebars.registerHelper('signeHeure', (key, heure) => RdDCalendrier.getSigneAs(key, heure)); Handlebars.registerHelper('signeHeure', (key, heure) => RdDCalendrier.getSigneAs(key, heure));
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1))); Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option)); Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name))); Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
Handlebars.registerHelper('filtreTriCompetences', competences => competences.filter(it => it.system.isVisible) Handlebars.registerHelper('filtreTriCompetences', competences => RdDItemCompetence.triVisible(competences));
.sort((a, b) => { Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name));
if (a.name.startsWith("Survie") && b.name.startsWith("Survie")) { Handlebars.registerHelper('uniteQuantite', (itemId, actorId) => RdDUtility.getItem(itemId, actorId)?.getUniteQuantite());
if (a.name.includes("Cité")) return -1; Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
if (b.name.includes("Cité")) return 1; Handlebars.registerHelper('getFrequenceRarete', (rarete, field) => Environnement.getFrequenceRarete(rarete, field));
if (a.name.includes("Extérieur")) return -1;
if (b.name.includes("Extérieur")) return 1;
return a.name.localeCompare(b.name);
}
if (a.system.categorie.startsWith("melee") && b.system.categorie.startsWith("melee")) {
if (a.name.includes("Corps")) return -1;
if (b.name.includes("Corps")) return 1;
if (a.name.includes("Dague")) return -1;
if (b.name.includes("Dague")) return 1;
if (a.name.includes("Esquive")) return -1;
if (b.name.includes("Esquive")) return 1;
return a.name.localeCompare(b.name);
}
if (a.name.startsWith("Voie") && b.name.startsWith("Voie")) {
if (a.name.includes("Oniros")) return -1;
if (b.name.includes("Oniros")) return 1;
if (a.name.includes("Hypnos")) return -1;
if (b.name.includes("Hypnos")) return 1;
if (a.name.includes("Narcos")) return -1;
if (b.name.includes("Narcos")) return 1;
if (a.name.includes("Thanatos")) return -1;
if (b.name.includes("Thanatos")) return 1;
return a.name.localeCompare(b.name);
}
return a.name.localeCompare(b.name);
})
);
return loadTemplates(templatePaths); return loadTemplates(templatePaths);
} }
static getItem(itemId, actorId = undefined) {
return actorId ? game.actors.get(actorId)?.getObjet(itemId) : game.items.get(itemId);
}
static linkCompendium(pack, id, name) {
return `@Compendium[${pack}.${id}]{${name}}`;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async creerObjet(actorSheet) { static async creerObjet(actorSheet) {
let itemType = $(".item-type").val(); let itemType = $(".item-type").val();
@@ -330,7 +330,7 @@ export class RdDUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async selectObjetType(actorSheet) { static async selectObjetType(actorSheet) {
let typeObjets = RdDItem.getTypesObjetsEquipement(); let typeObjets = RdDItem.getItemTypesInventaire();
let options = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`; let options = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
for (let typeName of typeObjets) { for (let typeName of typeObjets) {
options += `<option value="${typeName}">${typeName}</option>` options += `<option value="${typeName}">${typeName}</option>`
@@ -432,6 +432,7 @@ export class RdDUtility {
formData.oeuvres = this.arrayOrEmpty(itemTypes['oeuvre']); formData.oeuvres = this.arrayOrEmpty(itemTypes['oeuvre']);
formData.jeux = this.arrayOrEmpty(itemTypes['jeu']); formData.jeux = this.arrayOrEmpty(itemTypes['jeu']);
formData.services = this.arrayOrEmpty(itemTypes['service']);
formData.recettescuisine = this.arrayOrEmpty(itemTypes['recettecuisine']); formData.recettescuisine = this.arrayOrEmpty(itemTypes['recettecuisine']);
formData.recettesAlchimiques = this.arrayOrEmpty(itemTypes['recettealchimique']); formData.recettesAlchimiques = this.arrayOrEmpty(itemTypes['recettealchimique']);
formData.maladies = this.arrayOrEmpty(itemTypes['maladie']); formData.maladies = this.arrayOrEmpty(itemTypes['maladie']);
@@ -452,9 +453,9 @@ export class RdDUtility {
formData.livres = this.arrayOrEmpty(itemTypes['livre']); formData.livres = this.arrayOrEmpty(itemTypes['livre']);
formData.potions = this.arrayOrEmpty(itemTypes['potion']); formData.potions = this.arrayOrEmpty(itemTypes['potion']);
formData.ingredients = this.arrayOrEmpty(itemTypes['ingredient']); formData.ingredients = this.arrayOrEmpty(itemTypes['ingredient']);
formData.faunes = this.arrayOrEmpty(itemTypes['faune']);
formData.herbes = this.arrayOrEmpty(itemTypes['herbe']); formData.herbes = this.arrayOrEmpty(itemTypes['herbe']);
formData.monnaie = this.arrayOrEmpty(itemTypes['monnaie']); formData.monnaie = this.arrayOrEmpty(itemTypes['monnaie']).sort(Monnaie.triValeurEntiere());
formData.monnaie.sort(Monnaie.triValeurDenier());
formData.nourritureboissons = this.arrayOrEmpty(itemTypes['nourritureboisson']); formData.nourritureboissons = this.arrayOrEmpty(itemTypes['nourritureboisson']);
formData.gemmes = this.arrayOrEmpty(itemTypes['gemme']); formData.gemmes = this.arrayOrEmpty(itemTypes['gemme']);
@@ -467,6 +468,7 @@ export class RdDUtility {
.concat(formData.potions) .concat(formData.potions)
.concat(formData.ingredients) .concat(formData.ingredients)
.concat(formData.herbes) .concat(formData.herbes)
.concat(formData.faunes)
.concat(formData.monnaie) .concat(formData.monnaie)
.concat(formData.nourritureboissons) .concat(formData.nourritureboissons)
.concat(formData.gemmes); .concat(formData.gemmes);
@@ -540,8 +542,7 @@ export class RdDUtility {
if (!profondeur) profondeur = 1; if (!profondeur) profondeur = 1;
objet.niveau = profondeur; objet.niveau = profondeur;
const display = afficherContenu ? 'item-display-show' : 'item-display-hide'; const display = afficherContenu ? 'item-display-show' : 'item-display-hide';
//console.log("ITEM DISPLAYED", objet ); let strContenu = `<ul class='item-list alterne-list ${display} list-item-margin${Math.min(profondeur,6)}'>`;
let strContenu = `<ul class='item-list alterne-list ${display} list-item-margin${profondeur}'>`;
for (let subItem of objet.subItems) { for (let subItem of objet.subItems) {
strContenu += this.buildConteneur(subItem, profondeur + 1); strContenu += this.buildConteneur(subItem, profondeur + 1);
} }
@@ -758,29 +759,6 @@ export class RdDUtility {
return 0; return 0;
} }
/* -------------------------------------------- */
static async loadItems(filter, compendium) {
let items = game.items.filter(filter);
if (compendium) {
const ids = items.map(it => it.id);
const names = items.map(it => it.name.toLowerCase());
items = items.concat(await RdDUtility.loadCompendium(compendium, it => !ids.includes(it.id) && !names.includes(it.name.toLowerCase()) && filter(it)));
}
return items;
}
/* -------------------------------------------- */
static async loadCompendium(compendium, filter = it => true) {
let compendiumData = await RdDUtility.loadCompendiumData(compendium);
return compendiumData.filter(filter);
}
/* -------------------------------------------- */
static async loadCompendiumData(compendium) {
const pack = game.packs.get(compendium);
return await pack?.getDocuments() ?? [];
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async responseNombreAstral(callData) { static async responseNombreAstral(callData) {
let actor = game.actors.get(callData.id); let actor = game.actors.get(callData.id);
@@ -838,7 +816,7 @@ export class RdDUtility {
// gestion bouton tchat Acheter // gestion bouton tchat Acheter
html.on("click", '.button-acheter', event => { html.on("click", '.button-acheter', event => {
const venteData = DialogItemAchat.venteData(event.currentTarget); const venteData = DialogItemAchat.preparerAchat(event.currentTarget);
if (venteData) { if (venteData) {
DialogItemAchat.onAcheter(venteData); DialogItemAchat.onAcheter(venteData);
} }
@@ -847,20 +825,17 @@ export class RdDUtility {
// Gestion du bouton payer // Gestion du bouton payer
html.on("click", '.payer-button', event => { html.on("click", '.payer-button', event => {
let sumdenier = event.currentTarget.attributes['data-somme-denier']?.value ?? 0; let sommeAPayer = Number(event.currentTarget.attributes['data-somme-a-payer']?.value ?? 0);
let quantite = event.currentTarget.attributes['data-quantite']?.value ?? 1;
let fromActorId = event.currentTarget.attributes['data-actor-id']?.value;
let jsondata = event.currentTarget.attributes['data-jsondata']
let objData
if (jsondata) {
objData = JSON.parse(jsondata.value)
}
let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:"); let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:");
if (actor) { if (actor) {
actor.depenserDeniers(sumdenier, objData, quantite, fromActorId); actor.payerSols(sommeAPayer);
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget)); ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget));
} }
}); });
html.on("click", '.rdd-world-content-link', async event => {
const itemId = html.find(event.currentTarget)?.data("id");
game.items.get(itemId)?.sheet.render(true)
});
} }
static findChatMessageId(current) { static findChatMessageId(current) {
@@ -908,12 +883,12 @@ export class RdDUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static createMonnaie(name, valeur_deniers, img = "", enc = 0.01) { static createMonnaie(name, cout, img = "", enc = 0.01) {
let piece = { let piece = {
name: name, type: 'monnaie', img: img, _id: randomID(16), name: name, type: 'monnaie', img: img, _id: randomID(16),
dasystemta: { dasystemta: {
quantite: 0, quantite: 0,
valeur_deniers: valeur_deniers, cout: cout,
encombrement: enc, encombrement: enc,
description: "" description: ""
} }
@@ -925,20 +900,20 @@ export class RdDUtility {
static afficherDemandePayer(som1, som2) { static afficherDemandePayer(som1, som2) {
som1 = (som1) ? som1.toLowerCase() : "0d"; som1 = (som1) ? som1.toLowerCase() : "0d";
som2 = (som2) ? som2.toLowerCase() : "0d"; som2 = (som2) ? som2.toLowerCase() : "0d";
let regExp = /(\d+)(\w+)/g; let regExp1 = /(\d+)(\w+)/g;
let p1 = regExp.exec(som1); let p1 = regExp1.exec(som1);
regExp = /(\d+)(\w+)/g; let regExp2 = /(\d+)(\w+)/g;
let p2 = regExp.exec(som2); let p2 = regExp2.exec(som2);
let sumd = 0; let deniers = 0;
let sums = 0; let sols = 0;
if (p1[2] == 'd') sumd += Number(p1[1]); if (p1[2] == 'd') deniers += Number(p1[1]);
if (p1[2] == 's') sums += Number(p1[1]); if (p1[2] == 's') sols += Number(p1[1]);
if (p2[2] == 'd') sumd += Number(p2[1]); if (p2[2] == 'd') deniers += Number(p2[1]);
if (p2[2] == 's') sums += Number(p2[1]); if (p2[2] == 's') sols += Number(p2[1]);
let sumtotald = sumd + (sums * 100); let sommeAPayer = sols + deniers/100;
let msgPayer = "La somme de " + sums + " Sols et " + sumd + " Deniers est à payer, cliquer sur le lien ci-dessous si besoin.<br>"; let msgPayer = `La somme de ${sols} Sols et ${deniers} Deniers est à payer<br>
msgPayer += "<a class='payer-button chat-card-button' data-somme-denier='" + sumtotald + "'>Payer</a>" <a class='payer-button chat-card-button' data-somme-a-payer='${sommeAPayer}'>Payer</a>`
ChatMessage.create({ content: msgPayer }); ChatMessage.create({ content: msgPayer });
} }
@@ -978,7 +953,7 @@ export class RdDUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async confirmerSuppressionItem(sheet, item, htmlToDelete) { static async confirmActorItemDelete(sheet, item, htmlToDelete) {
const itemId = item.id; const itemId = item.id;
const confirmationSuppression = { const confirmationSuppression = {
settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(), settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(),
@@ -1013,7 +988,7 @@ export class RdDUtility {
} }
static slideOnDelete(sheet, htmlToDelete) { static slideOnDelete(sheet, htmlToDelete) {
return htmlToDelete.slideUp(200, () => sheet.render(false)); return htmlToDelete?.slideUp(200, () => sheet.render(false));
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@@ -62,20 +62,20 @@ export const referenceAjustements = {
getValue: (rollData, actor) => actor.getMalusArmure() getValue: (rollData, actor) => actor.getMalusArmure()
}, },
encTotal: { encTotal: {
isVisible: (rollData, actor) => RdDItemCompetence.isMalusEncombrementTotal(rollData.competence), isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
isUsed: (rollData, actor) => rollData.use.encTotal, isUsed: (rollData, actor) => !rollData.oeuvre && RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) && rollData.use.encTotal,
getLabel: (rollData, actor) => 'Encombrement total', getLabel: (rollData, actor) => 'Encombrement total',
getValue: (rollData, actor) => -actor.getEncTotal() getValue: (rollData, actor) => -actor.getEncTotal()
}, },
surenc: { surenc: {
isVisible: (rollData, actor) => actor.isSurenc(), isVisible: (rollData, actor) => actor.isSurenc(),
isUsed: (rollData, actor) => rollData.use.surenc, isUsed: (rollData, actor) => rollData.use?.surenc,
getLabel: (rollData, actor) => 'Sur-encombrement', getLabel: (rollData, actor) => 'Sur-encombrement',
getValue: (rollData, actor) => actor.computeMalusSurEncombrement() getValue: (rollData, actor) => actor.computeMalusSurEncombrement()
}, },
moral: { moral: {
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac) && rollData.useMoral, isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac) && rollData.use?.moral,
isUsed: (rollData, actor) => rollData.useMoral, isUsed: (rollData, actor) => rollData.use?.moral,
getLabel: (rollData, actor) => 'Appel au moral', getLabel: (rollData, actor) => 'Appel au moral',
getValue: (rollData, actor) => 1 getValue: (rollData, actor) => 1
}, },

View File

@@ -18,6 +18,7 @@ const listeReglesOptionelles = [
{ group: 'Règles générales', name: 'appliquer-fatigue', descr: "Appliquer les règles de fatigue"}, { group: 'Règles générales', name: 'appliquer-fatigue', descr: "Appliquer les règles de fatigue"},
{ group: 'Règles générales', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false }, { group: 'Règles générales', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false },
{ group: 'Confirmations', name: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"}, { group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-refouler', descr: "Confirmer avant de refouler", scope: "client"}, { group: 'Confirmations', name: 'confirmation-refouler', descr: "Confirmer avant de refouler", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"}, { group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"},

View File

@@ -1,4 +1,7 @@
import { SYSTEM_RDD } from "../constants.js"; import { HIDE_DICE, SYSTEM_RDD } from "../constants.js";
import { RdDItem } from "../item.js";
import { Misc } from "../misc.js";
import { RdDDice } from "../rdd-dice.js";
const COMPENDIUM_SETTING_PREFIX = 'compendium-'; const COMPENDIUM_SETTING_PREFIX = 'compendium-';
@@ -13,8 +16,13 @@ const CONFIGURABLE_COMPENDIUMS = {
'rencontres': { label: "Rencontres dans les TMR", type: "Item" }, 'rencontres': { label: "Rencontres dans les TMR", type: "Item" },
'tetes-de-dragon-pour-haut-revants': { label: "Têtes de dragons (haut-rêvant)", type: "Item" }, 'tetes-de-dragon-pour-haut-revants': { label: "Têtes de dragons (haut-rêvant)", type: "Item" },
'tetes-de-dragon-pour-tous-personnages': { label: "Têtes de dragons (tous)", type: "Item" }, 'tetes-de-dragon-pour-tous-personnages': { label: "Têtes de dragons (tous)", type: "Item" },
'faune-flore-mineraux': { label: "Herbes & plantes", type: "Item" },
'equipement': { label: "Equipements", type: "Item" },
} }
/**
* ======= Gestion des accès aux compendiums systèmes (ou surchargés) =======
*/
export class SystemCompendiums extends FormApplication { export class SystemCompendiums extends FormApplication {
static init() { static init() {
Object.keys(CONFIGURABLE_COMPENDIUMS).forEach(compendium => { Object.keys(CONFIGURABLE_COMPENDIUMS).forEach(compendium => {
@@ -44,10 +52,10 @@ export class SystemCompendiums extends FormApplication {
} }
static getPack(compendium) { static getPack(compendium) {
return game.packs.get(SystemCompendiums.getCompendium(compendium)); return game.packs.get(SystemCompendiums.getCompendium(compendium)) ?? game.packs.get(SystemCompendiums._getDefaultCompendium(compendium));
} }
static async getContent(compendium, docType) { static async getPackContent(compendium, docType) {
const pack = SystemCompendiums.getPack(compendium); const pack = SystemCompendiums.getPack(compendium);
if (pack.metadata.type == docType) { if (pack.metadata.type == docType) {
return await pack.getDocuments(); return await pack.getDocuments();
@@ -55,9 +63,47 @@ export class SystemCompendiums extends FormApplication {
return []; return [];
} }
static async getCompetences(actorType) {
switch (actorType ?? 'personnage') {
case 'personnage': return await SystemCompendiums.getWorldOrCompendiumItems('competence', 'competences');
case 'creature': return await SystemCompendiums.getWorldOrCompendiumItems('competencecreature', 'competences-creatures');
case 'entite': return await SystemCompendiums.getWorldOrCompendiumItems('competencecreature', 'competences-entites');
case 'vehicule': return [];
}
}
/* -------------------------------------------- */
static async getWorldOrCompendiumItems(itemType, compendium) {
let items = game.items.filter(it => it.type == itemType);
if (compendium) {
const ids = items.map(it => it.id);
const names = items.map(it => it.name.toLowerCase());
const compendiumItems = await SystemCompendiums.getItems(compendium);
items = items.concat(compendiumItems
.filter(it => it.type == itemType)
.filter(it => !ids.includes(it.id))
.filter(it => !names.includes(it.name.toLowerCase())));
}
return items;
}
static async loadDocument(document) {
const pack = game.packs.get(document.pack);
return await pack.getDocument(document.id ?? document._id);
}
static async getItems(compendium, itemType = undefined) { static async getItems(compendium, itemType = undefined) {
const items = await SystemCompendiums.getContent(compendium, 'Item'); const items = await SystemCompendiums.getPackContent(compendium, 'Item');
return itemType ? items.filter(it => it.type == itemType) : items; return (itemType ? items.filter(it => it.type == itemType) : items);
}
static async getContent(compendium, type, filter, itemFrequence, sorting) {
let elements = await SystemCompendiums.getPackContent(compendium, type);
elements = elements.filter(filter).filter(it => itemFrequence(it) > 0);
if (sorting) {
elements = elements.sort(sorting);
}
return elements;
} }
static async getDefaultItems(compendium) { static async getDefaultItems(compendium) {
@@ -102,11 +148,13 @@ export class SystemCompendiums extends FormApplication {
getData() { getData() {
const systemCompendiums = Object.values(CONFIGURABLE_COMPENDIUMS) const systemCompendiums = Object.values(CONFIGURABLE_COMPENDIUMS)
.map(it => mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) })); .map(it => mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) }));
const availableCompendiums = game.packs.map(pack => { return { const availableCompendiums = game.packs.map(pack => {
return {
name: pack.collection, name: pack.collection,
path: pack.collection.replace('.', " / "), path: pack.collection.replace('.', " / "),
type: pack.metadata.type type: pack.metadata.type
} }); }
});
return mergeObject(super.getData(), { return mergeObject(super.getData(), {
systemCompendiums: systemCompendiums, systemCompendiums: systemCompendiums,
availableCompendiums: availableCompendiums availableCompendiums: availableCompendiums
@@ -122,5 +170,123 @@ export class SystemCompendiums extends FormApplication {
game.settings.set(SYSTEM_RDD, systemCompendium.setting, value); game.settings.set(SYSTEM_RDD, systemCompendium.setting, value);
}); });
} }
}
/**
* ======= Gestion de jets dans une table correspondant à un compendium =======
*/
export class CompendiumTable {
constructor(compendium, type, subTypes, sorting = undefined) {
this.compendium = compendium;
this.type = type;
this.subTypes = subTypes;
this.sorting = sorting ?? Misc.ascending(it => it.name);
}
async getContent(itemFrequence = it => it.system.frequence, filter = it => true) {
return await SystemCompendiums.getContent(this.compendium,
this.type,
it => this.subTypes.includes(it.type) && filter(it),
itemFrequence,
this.sorting);
}
async buildTable(itemFrequence = it => it.system.frequence, filter = it => true) {
const elements = await this.getContent(filter, itemFrequence);
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
}
async getRandom(itemFrequence = it => it.system.frequence, filter = it => true, forcedRoll = undefined) {
const table = await this.buildTable(itemFrequence, filter);
return await CompendiumTableHelpers.getRandom(table, this.type, this.subTypes, forcedRoll, SystemCompendiums.getCompendium(compendium));
}
async toChatMessage(itemFrequence = it => it.system.frequence, filter = it => true, typeName = undefined) {
const table = await this.buildTable(itemFrequence, filter);
await CompendiumTableHelpers.tableToChatMessage(table, this.type, this.subTypes, typeName);
return true;
}
}
/**
* ======= Gestion de tables correspondant à un compendium =======
*/
export class CompendiumTableHelpers {
static buildTable(elements, itemFrequence) {
let max = 0;
const total = elements.map(it => itemFrequence(it)).reduce(Misc.sum(), 0);
return elements.map(it => {
const frequence = itemFrequence(it);
let row = { document: it, frequence: frequence, min: max + 1, max: max + frequence, total: total };
max += frequence;
return row;
});
}
static async getRandom(table, type, subTypes, forcedRoll = undefined, localisation = undefined) {
if (table.length == 0) {
ui.notifications.warn(`Aucun ${Misc.typeName(type, subTypes[0])} trouvé dans ${localisation ?? ' les compendiums'}`);
return undefined;
}
return await CompendiumTableHelpers.selectRow(table, forcedRoll);
}
/* -------------------------------------------- */
static async selectRow(table, forcedRoll = undefined) {
if (table.length == 0) {
return undefined
}
const total = table[0].total;
const formula = `1d${total}`;
if (forcedRoll == undefined && (forcedRoll > total || forcedRoll <= 0)) {
ui.notifications.warn(`Jet de rencontre ${forcedRoll} en dehors de la table [1..${total}], le jet est relancé`);
forcedRoll = undefined;
}
const roll = forcedRoll ? { total: forcedRoll, formula } : await RdDDice.roll(formula, { showDice: HIDE_DICE });
const row = table.find(it => it.min <= roll.total && roll.total <= it.max);
row.roll = roll;
return row;
}
/* -------------------------------------------- */
static async tableRowToChatMessage(row, type = 'Item') {
if (!row) {
return;
}
const percentages = (row.total == 100) ? '%' : ''
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table-roll.html', {
roll: row.roll,
document: row.document,
percentages,
typeName: Misc.typeName(type, row.document.type),
isGM: game.user.isGM,
});
const messageData = {
// flavor: flavorContent,
user: game.user.id,
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
roll: row.roll,
sound: CONFIG.sounds.dice,
content: flavorContent
};
ChatMessage.create(messageData, { rollMode: "gmroll" });
}
/* -------------------------------------------- */
static async tableToChatMessage(table, type, subTypes, typeName = undefined) {
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table.html', {
img: RdDItem.getDefaultImg(subTypes[0]),
typeName: typeName ?? Misc.typeName(type, subTypes[0]),
table,
isGM: game.user.isGM,
});
ChatMessage.create({
user: game.user.id,
whisper: game.user.id,
content: flavorContent
}, { rollMode: "gmroll" });
}
} }

56
module/targets.js Normal file
View File

@@ -0,0 +1,56 @@
import { ENTITE_NONINCARNE } from "./constants.js";
import { DialogSelectTarget } from "./dialog-select-target.js";
export class Targets {
static listTargets() {
return Array.from(game.user.targets);
}
static hasTargets() {
return Targets.listTargets().length > 0;
}
static extractTokenData(target) {
if (!target) {
return undefined
}
return { id: target.id, name: target.document.name, img: target.document.texture.src ?? target.actor.img ?? 'icons/svg/mystery-man.svg' };
}
static isTargetEntite(target) {
return target?.actor.type == 'entite' && target?.actor.system.definition.typeentite == ENTITE_NONINCARNE;
}
static async selectOneToken(onSelectTarget = target => { }) {
const targets = Targets.listTargets();
switch (targets.length) {
case 0: return;
case 1:
onSelectTarget(targets[0]);
return;
default:
{
const tokens = targets.map(it => Targets.extractTokenData(it))
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-select-target.html", {
tokens: tokens
});
new DialogSelectTarget(html, onSelectTarget, targets).render(true);
}
}
}
static getTarget() {
const targets = Targets.listTargets();
switch (targets.length) {
case 1:
return targets[0];
case 0:
ui.notifications.warn("Vous devez choisir une cible à attaquer!");
break;
default:
ui.notifications.warn("Vous devez choisir une cible (et <strong>une seule</strong>) à attaquer!");
return;
}
}
}

View File

@@ -1,20 +1,31 @@
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js"; import { RdDDice } from "./rdd-dice.js";
import { SystemCompendiums } from "./settings/system-compendiums.js"; import { RdDUtility } from "./rdd-utility.js";
import { SystemCompendiums, CompendiumTable, CompendiumTableHelpers } from "./settings/system-compendiums.js";
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class TMRRencontres { export class TMRRencontres {
static init() {
const tmrRencontre = new TMRRencontres();
game.system.rdd.rencontresTMR = tmrRencontre;
}
constructor(){
this.table = new CompendiumTable('rencontres', 'Item', 'rencontre', Misc.ascending(it => it.system.ordreTri));
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/** /**
* Retourne une recontre en fonction de la case et du tirage * Retourne une recontre en fonction de la case et du tirage
* @param {*} terrain * @param {*} terrain
* @param {*} forcedRoll * @param {*} forcedRoll
*/ */
static async rollRencontre(terrain, forcedRoll) { async rollRencontre(terrain, forcedRoll) {
terrain = TMRUtility.findTMRLike(terrain); terrain = TMRUtility.findTMRLike(terrain);
if (terrain == undefined) { if (terrain == undefined) {
return undefined; return undefined;
@@ -24,49 +35,27 @@ export class TMRRencontres {
forcedRoll = undefined; forcedRoll = undefined;
} }
const codeTerrain = Grammar.toLowerCaseNoAccent(terrain) const codeTerrain = Grammar.toLowerCaseNoAccent(terrain)
const table = await TMRRencontres.$buildTableRencontre(codeTerrain);
const [selected, roll] = await TMRRencontres.$selectRencontre(codeTerrain, table, forcedRoll);
const rencontre = await TMRRencontres.createRencontre(selected.rencontre);
TMRRencontres.$chatRolledRencontre(rencontre, terrain, table, roll, true);
return false;
}
/* -------------------------------------------- */
static async $buildTableRencontre(codeTerrain) {
let max = 0;
const items = await SystemCompendiums.getItems('rencontres', 'rencontre');
const filtreMauvaise = codeTerrain == 'mauvaise' ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre; const filtreMauvaise = codeTerrain == 'mauvaise' ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
const rencontres = items.filter(it => it.type == 'rencontre') const frequence = it => it.system.frequence[codeTerrain];
.filter(filtreMauvaise) const row = await this.table.getRandom(frequence, filtreMauvaise, forcedRoll);
.filter(it => it.system.frequence[codeTerrain] > 0) if (row) {
.sort(Misc.ascending(it => it.system.ordreTri)) await CompendiumTableHelpers.tableRowToChatMessage(row);
.map(it => { }
const frequence = it.system.frequence[codeTerrain];
max += frequence; return row?.document;
return { rencontre: it, min: max - frequence + 1, max: max,frequence: frequence }; }
});
return rencontres; async chatTable(terrain) {
const codeTerrain = Grammar.toLowerCaseNoAccent(terrain)
const isMauvaise = codeTerrain == 'mauvaise';
const filtreMauvaise = isMauvaise ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
const frequence = it => it.system.frequence[codeTerrain];
const typeName = isMauvaise ? 'Mauvaises rencontres' : `Rencontres en ${Misc.upperFirst(terrain)}`;
return await this.table.toChatMessage(frequence, filtreMauvaise, typeName);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $selectRencontre(terrain, table, roll = undefined) { async createRencontre(rencontre, tmr = undefined) {
const total = table.map(it => it.frequence).reduce(Misc.sum(), 0);
if (total == 0){
ui.notifications.warn(`Pas de rencontres définies pour ${terrain}`);
return undefined;
}
if (roll != undefined && (roll > total || roll <= 0)) {
ui.notifications.warn(`Jet de rencontre ${roll} en dehors de la table [1..${total}], le jet est relancé`);
roll = undefined;
}
if (!roll) {
roll = await RdDDice.rollTotal(`1d${total}`);
}
return [table.find(it => it.min <= roll && roll <= it.max), roll];
}
/* -------------------------------------------- */
static async createRencontre(rencontre, tmr = undefined) {
return rencontre.clone({ return rencontre.clone({
'system.force': await RdDDice.rollTotal(rencontre.system.formule), 'system.force': await RdDDice.rollTotal(rencontre.system.formule),
'system.coord': tmr?.coord, 'system.coord': tmr?.coord,
@@ -75,7 +64,7 @@ export class TMRRencontres {
}, { save: false }); }, { save: false });
} }
static async calculRencontre(rencontre, tmr = undefined) { async calculRencontre(rencontre, tmr = undefined) {
if (rencontre.system.coord == "") { if (rencontre.system.coord == "") {
rencontre.system.coord = tmr?.coord; rencontre.system.coord = tmr?.coord;
} }
@@ -91,46 +80,53 @@ export class TMRRencontres {
return rencontre; return rencontre;
} }
/* -------------------------------------------- */
static $chatRolledRencontre(rencontre, terrain, table, roll = 0, displayTable=false){
const total = table.map(it => it.frequence).reduce(Misc.sum(), 0);
const namesPercent = displayTable ?
table.map(it => `<br>${it.rencontre.name} : ${it.frequence}${total == 100 ? '%' : ''} (${it.min} - ${it.max})`).reduce((a, b) => a + b, '<hr>')
: '';
const chances = game.user.isGM
? (roll ? `Jet: ${roll} / ${total}` : `Valeurs: [1..${total}]`)
: (roll ? `Jet: ${Math.ceil(roll*100/total)} / 100` : '');
ChatMessage.create({
user: game.user.id,
whisper: [game.user.id],
content: `Compendium: ${SystemCompendiums.getCompendium('rencontres')}
<br>Rencontre en ${terrain}:
${namesPercent}<hr>
<br>${chances}
<br>Rencontre: ${rencontre.name} ${rencontre.system.force} (${rencontre.system.formule})`
});
}
static async getPresentsCite() { async getPresentsCite() {
const rencontres = await SystemCompendiums.getDefaultItems('rencontres'); const rencontres = await SystemCompendiums.getDefaultItems('rencontres');
return rencontres.filter(it => !it.system.mauvaiseRencontre && it.system.presentCite).map(it => return rencontres.filter(it => !it.system.mauvaiseRencontre && it.system.presentCite).map(it =>
it.clone({ 'system.formule': "2d6" }, { save: false })); it.clone({ 'system.formule': "2d6" }, { save: false }));
} }
static async getReveDeDragon(force) { async getReveDeDragon(force) {
const rencontres = await SystemCompendiums.getDefaultItems('rencontres'); const rencontres = await SystemCompendiums.getDefaultItems('rencontres');
const reveDeDragon = rencontres.find(it => Grammar.equalsInsensitive(it.name, 'Rêve de Dragon')); const reveDeDragon = rencontres.find(it => Grammar.equalsInsensitive(it.name, 'Rêve de Dragon'));
return reveDeDragon?.clone({ 'system.force': force }, { save: false }); return reveDeDragon?.clone({ 'system.force': force }, { save: false });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getRencontreAleatoire(tmr, mauvaise) { async getRencontreAleatoire(tmr, mauvaise) {
const codeTerrain = mauvaise ? 'mauvaise' : tmr.type; const codeTerrain = mauvaise ? 'mauvaise' : tmr.type;
const table = await TMRRencontres.$buildTableRencontre(codeTerrain); const filtreMauvaise = codeTerrain == 'mauvaise' ? it => it.system.mauvaiseRencontre : it => !it.system.mauvaiseRencontre;
const [selected, roll] = await TMRRencontres.$selectRencontre(codeTerrain, table); const frequence = it => it.system.frequence[codeTerrain];
const rencontre = await TMRRencontres.createRencontre(selected.rencontre, tmr);
TMRRencontres.$chatRolledRencontre(rencontre, TMRUtility.getTMRType(tmr.coord), table, roll); const row = await this.table.getRandom(frequence, filtreMauvaise);
if (row) {
const rencontre = await this.createRencontre(row.document, tmr);
await this.$chatRolledRencontre(row, rencontre, tmr);
return rencontre; return rencontre;
} }
return undefined;
}
/* -------------------------------------------- */
async $chatRolledRencontre(row, rencontre,tmr) {
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table-roll-rencontre.html',
{
roll: row.roll,
rencontre,
row,
percentages: (row.total == 100) ? '%' : '',
tmr,
isGM: game.user.isGM,
});
const messageData = {
user: game.user.id,
type: CONST.CHAT_MESSAGE_TYPES.ROLL,
roll: row.roll,
sound: CONFIG.sounds.dice,
content: flavorContent
};
ChatMessage.create(messageData, { rollMode: "gmroll" });
}
} }

View File

@@ -3,7 +3,6 @@ import { Grammar } from "../grammar.js";
import { TMRUtility } from "../tmr-utility.js"; import { TMRUtility } from "../tmr-utility.js";
import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js"; import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js";
import { Draconique } from "./draconique.js"; import { Draconique } from "./draconique.js";
import { TMRRencontres } from "../tmr-rencontres.js";
export class PresentCites extends Draconique { export class PresentCites extends Draconique {
@@ -47,7 +46,7 @@ export class PresentCites extends Draconique {
} }
async choisirUnPresent(casetmr, onChoixPresent) { async choisirUnPresent(casetmr, onChoixPresent) {
const presents = await TMRRencontres.getPresentsCite() const presents = await game.system.rdd.rencontresTMR.getPresentsCite()
const buttons = {}; const buttons = {};
presents.forEach(r => buttons['present'+r.id] = { icon: '<i class="fas fa-check"></i>', label: r.name, callback: async () => onChoixPresent(r) }); presents.forEach(r => buttons['present'+r.id] = { icon: '<i class="fas fa-check"></i>', label: r.name, callback: async () => onChoixPresent(r) });
let d = new Dialog({ let d = new Dialog({

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,32 +0,0 @@
{"name":"Arme dhast","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":4,"equipe":false,"dommages":"4","force":"12","resistance":8,"competence":"Arme d'hast","cout":10,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":false,"deuxmains":true,"unemain":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/hast.webp","effects":[],"_id":"U6qli6TPbzj8tUdH"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/baton.webp","effects":[],"_id":"wyiy7aLaP8jnzkFn"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_petit.webp","effects":[],"_id":"eK28jEeQiJdd93L3"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_grand.webp","effects":[],"_id":"7B9sKLf4ipRyyEjF"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/bouclier_moyen.webp","effects":[],"_id":"1O7IJiQSDYxJ5VsD"}
{"name":"Cuir / Metal","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>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.</p>\n<p>&nbsp;</p>","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":"fDwsTMuug0Z5BdaA"}
{"name":"Cuir Epais","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>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.</p>\n<p>&nbsp;</p>","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":"szOThadvQvFcS79R"}
{"name":"Cuir Souple","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>Même épaisseur que nos modernes blousons de cuir. Pourpoint ou cotte de cuir souple + culottes de cuir souple + bottes de cuir souple.</p>\n<p>&nbsp;</p>","quantite":1,"encombrement":0,"equipe":false,"protection":2,"deterioration":0,"malus":0,"cout":6},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_souple.webp","effects":[],"_id":"b0f08L5CDeFIMluC"}
{"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},"flags":{"core":{"sheetClass":""}},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/dague.webp","effects":[],"_id":"CGYOJbaKtYvF2qa9"}
{"name":"Double dragonne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>Apparue vers la fin du Second &Acirc;ge, c&rsquo;&eacute;tait<em> une grande &eacute;p&eacute;e &agrave; deux mains</em>. Encombrante et prohibant le bouclier, c&rsquo;&eacute;tait avant tout une &eacute;p&eacute;e de duel et de frime.</p>","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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/double_dragonne.webp","effects":[],"_id":"6s5QjArwz9w9JIGL"}
{"name":"Drap Matelassé","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>Deux épaisseurs de drap surpiquées, avec rembourrage de laine.</p>\n<p>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 jusquaux genoux, façon Robin des Bois.</p>\n<p>&nbsp;</p>","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":"vQ494sD9FgFI08kZ"}
{"name":"Épée bâtarde","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>Comme son nom l&rsquo;indique, c&rsquo;est une <em>b&acirc;tarde </em>de l'&eacute;p&eacute;e longue et de l'&eacute;p&eacute;e sorde, &agrave; la fois longue et large, pouvant s&rsquo;utiliser &agrave; une ou deux mains.</p>","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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_batarde.webp","effects":[],"_id":"KmfftnkUsPQD6fV0"}
{"name":"Épée cyane","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>Long <em>cimeterre </em>&agrave; l&rsquo;acier bleut&eacute;, exclusivement fabriqu&eacute; par les Cyans ou Hommes bleus.</p>","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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_cyane.webp","effects":[],"_id":"ijCebH1Pr3LmzdOj"}
{"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},"flags":{"core":{"sourceId":"Item.ErwaSLcGryAbYjkm"}},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/demi_dragonne.webp","effects":[],"_id":"IlA16EWR1x5ZBckA"}
{"name":"Épée dragonne","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>C&rsquo;est une &eacute;p&eacute;e <em>longue</em>, plus robuste que l&rsquo;esparlongue, pouvant &eacute;galement frapper de taille.</p>","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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_dragonne.webp","effects":[],"_id":"3Wk5dzp3M7Das6wh"}
{"name":"Épée gnome","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>C&rsquo;est une &eacute;p&eacute;e <em>courte</em>, essentiellement fabriqu&eacute;e et port&eacute;e par les Gnomes au Second &Acirc;ge.</p>","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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.webp","effects":[],"_id":"WurdjqJ8zMiXNdiW"}
{"name":"Épée sorde","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>C&rsquo;est une &eacute;p&eacute;e plus courte que la dragonne, mais plus <em>large</em>. Elle peut s&rsquo;utiliser &agrave; une ou deux mains. Sa grande solidit&eacute; en fait l&rsquo;&eacute;p&eacute;e de pr&eacute;dilection des gardes et des soldats.</p>\n<p>C&rsquo;est probablement &agrave; elle que le <em>Guerrier Sorde</em> doit son nom (&agrave; moins que ce ne soit l&rsquo;inverse).</p>","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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_sord.webp","effects":[],"_id":"cFnFQrQIPgyZRWdo"}
{"name":"Esparlongue","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"<p>C&rsquo;est une &eacute;p&eacute;e semblable &agrave; la <em>rapi&egrave;re</em>, longue et ne frappant uniquement d&rsquo;estoc. Elle doit son nom &agrave; ce qu&rsquo;elle &eacute;tait particuli&egrave;rement en vogue, au Second &Acirc;ge, dans la cit&eacute; d&rsquo;Esparlongue. En ce d&eacute;but du Troisi&egrave;me &Acirc;ge, toutefois, on lui substitue le plus souvent la <strong>demi-dragonne</strong>, &eacute;p&eacute;e tr&egrave;s voisine, ne frappant pareillement que d&rsquo;estoc, mais plus r&eacute;sistante (r&eacute;sistance 10) et moins co&ucirc;teuse (15 sols) ; son bonus aux dommages (+2) est identique.</p>","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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/esparlongue.webp","effects":[],"_id":"t3LZDSaQ6AiloImA"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/fleau_leger.webp","effects":[],"_id":"J4PpWO4OZ6JPaAUB"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/fleau_lourd.webp","effects":[],"_id":"HRLrRhAF4Hkfbqjh"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/gourdin.webp","effects":[],"_id":"PoTI2z0Wr4hxiLpQ"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/grande_hache.webp","effects":[],"_id":"hVgd4APvAW8sbXf0"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/hache_bataille.webp","effects":[],"_id":"9jbjDpbddL2Ep09s"}
{"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":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/systems/foundryvtt-reve-de-dragon/icons/objets/hachette.webp","effects":[],"_id":"TKyv5S3VNaOLOWJw"}
{"name":"Javeline","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"arme","data":{"description":"","quantite":1,"encombrement":1,"equipe":false,"dommages":"1","force":"7","resistance":5,"competence":"Lance","cout":1,"portee_courte":0,"portee_moyenne":0,"portee_extreme":0,"rapide":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/javeline.webp","effects":[],"_id":"Ri5QtS98FTfgHk2N"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/lance.webp","effects":[],"_id":"viHilj5hAHZqWuli"}
{"name":"Mailles de Fer","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>Grand haubert de mailles avec capuche À enfiler sur une cotte de cuir souple ou de drap matelassé) + bottes de cuir / métal.</p>\n<p>&nbsp;</p>","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":"KQZIK8ltQ3sQiDGe"}
{"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":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/systems/foundryvtt-reve-de-dragon/icons/objets/marteau.webp","effects":[],"_id":"i26px61PjvPlOiJW"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/masse_lourde.webp","effects":[],"_id":"7xFe41JZIVNMLv1U"}
{"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},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/massette.webp","effects":[],"_id":"wK5sGduzSvY3XxMF"}
{"name":"Plaques de Fer","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"armure","data":{"description":"<p>L'armure classique du chevalier. Armure complète de plaques (heaume, cuirasse, épaulières, cubitières, ventrière, cuissards, jambières).</p>\n<p>&nbsp;</p>","quantite":1,"encombrement":8,"equipe":false,"protection":6,"deterioration":0,"malus":-6,"cout":100},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.webp","effects":[],"_id":"S3bLtbXe6BzEFCjt"}
{"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":true,"deuxmains":false,"unemain":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/armes_armures/systems/foundryvtt-reve-de-dragon/icons/objets/rasoir.webp","effects":[],"_id":"9UFxKeFJv79QSzhz"}

View File

@@ -1,49 +1,49 @@
{"name":"Moussecaille","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":6,"ingredients":"<ul>\n<li>4 grosses cailles (1 sust chaque)</li>\n<li>3 livres de mousseroles</li>\n<li>4 &eacute;chalotes</li>\n<li>1 racine de r&eacute;f&egrave;ble</li>\n<li>1 schouillat de miel</li>\n<li>10 schouillats de beurre</li>\n<li>2 doigts d&rsquo;huile</li>\n<li>5 schouillats de farine de bl&eacute;di&egrave;ze</li>\n<li>eau</li>\n<li>sel</li>\n<li>4 brins de klampine</li>\n<li>4 brins de luciane</li>\n<li>1 brin de mentharde</li>\n<li>4 brins de p&egrave;pre</li>\n</ul>","duree":"80 minutes","sust":8,"description":"<p>Civet de cailles aux mousseroles.</p>\n<p>La mousserole est un petit champignon rose, tr&egrave;s abondant apr&egrave;s la pluie (commun). Pratiquement, cette recette peut s&rsquo;appliquer &agrave; tout gibier &agrave; plume pr&eacute;par&eacute; aux champignons.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_6.webp","effects":[],"_id":"240HPtZsgZQERFMF"} {"name":"Moussecaille","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.240HPtZsgZQERFMF"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_6.webp","effects":[],"_id":"240HPtZsgZQERFMF","system":{"description":"<p>Civet de cailles aux mousseroles.</p>\n<p>La mousserole est un petit champignon rose, tr&egrave;s abondant apr&egrave;s la pluie (commun). Pratiquement, cette recette peut s&rsquo;appliquer &agrave; tout gibier &agrave; plume pr&eacute;par&eacute; aux champignons.</p>","descriptionmj":"","niveau":6,"ingredients":"<ul>\n<li>4 grosses cailles (1 sust chaque)</li>\n<li>3 livres de mousseroles</li>\n<li>4 &eacute;chalotes</li>\n<li>1 racine de r&eacute;f&egrave;ble</li>\n<li>1 schouillat de miel</li>\n<li>10 schouillats de beurre</li>\n<li>2 doigts d&rsquo;huile</li>\n<li>5 schouillats de farine de bl&eacute;di&egrave;ze</li>\n<li>eau</li>\n<li>sel</li>\n<li>4 brins de klampine</li>\n<li>4 brins de luciane</li>\n<li>1 brin de mentharde</li>\n<li>4 brins de p&egrave;pre</li>\n</ul>","duree":"80 minutes","sust":8,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870029,"modifiedTime":1671048281603,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Panaris et Phlegmon","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":7,"description":"<p>Romance sur la fatalit&eacute; qui s&eacute;pare deux amants et que seule la mort r&eacute;unit.</p>\n<p>&Agrave; la fin, la belle Panaris est transform&eacute;e en carafe et le gentil Phlegmon en bouchon de cristal. L&rsquo;empereur, &agrave; qui &eacute;choit le flacon, les rassemble symboliquement.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_7.webp","effects":[],"_id":"36YGDFJBxekzEvBw"} {"name":"Panaris et Phlegmon","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.36YGDFJBxekzEvBw"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_7.webp","effects":[],"_id":"36YGDFJBxekzEvBw","system":{"description":"<p>Romance sur la fatalit&eacute; qui s&eacute;pare deux amants et que seule la mort r&eacute;unit.</p>\n<p>&Agrave; la fin, la belle Panaris est transform&eacute;e en carafe et le gentil Phlegmon en bouchon de cristal. L&rsquo;empereur, &agrave; qui &eacute;choit le flacon, les rassemble symboliquement.</p>","descriptionmj":"","niveau":7,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870029,"modifiedTime":1671048281603,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La danse des sept rêves","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":6,"description":"<p>V&eacute;ritable ballet, la danse des sept r&ecirc;ves est une chor&eacute;graphie dramatique &eacute;labor&eacute;e.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_8.webp","effects":[],"_id":"4mhiTAEhwDh7S3i0"} {"name":"La danse des sept rêves","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.4mhiTAEhwDh7S3i0"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_8.webp","effects":[],"_id":"4mhiTAEhwDh7S3i0","system":{"description":"<p>V&eacute;ritable ballet, la danse des sept r&ecirc;ves est une chor&eacute;graphie dramatique &eacute;labor&eacute;e.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281604,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Les fléchettes","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"adressehasard","base":-6,"caraccomp":"Lancer","description":"<p>Jeu d&rsquo;adresse consistant &agrave; viser une cible avec des fl&eacute;chettes.</p>\n<p>Pour simuler une partie, faire tirer &agrave; chaque participant 5 jets de Lancer/Jeu &agrave; z&eacute;ro et additionner les points de t&acirc;che obtenus. Le plus grand nombre gagne.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_flechettes.webp","effects":[],"_id":"8jOKQkuS6RJyM3uD"} {"name":"Les fléchettes","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.8jOKQkuS6RJyM3uD"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_flechettes.webp","effects":[],"_id":"8jOKQkuS6RJyM3uD","system":{"description":"<p>Jeu d&rsquo;adresse consistant &agrave; viser une cible avec des fl&eacute;chettes.</p>\n<p>Pour simuler une partie, faire tirer &agrave; chaque participant 5 jets de Lancer/Jeu &agrave; z&eacute;ro et additionner les points de t&acirc;che obtenus. Le plus grand nombre gagne.</p>","descriptionmj":"","type":"adressehasard","base":-6,"caraccomp":"Lancer","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281604,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La peccadille","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":false,"apparence":true,"niveau":2,"description":"<p>La peccadille se danse &agrave; deux, comme la valse ou le tango. Plus lente et moins rythm&eacute;e&nbsp; que les deux premi&egrave;res, elle comporte quatre figures :</p>\n<p>1) les cavaliers se tiennent par les mains</p>\n<p>2) ils se tiennent par la taille</p>\n<p>3) figure libre, improvis&eacute;e par celui ou celle qui a invit&eacute; l&rsquo;autre</p>\n<p>4) les deux visages doivent se rapprocher de fa&ccedil;on &agrave; se toucher par le bout du nez &agrave; l&rsquo;exclusion de toute autre partie du corps.</p>\n<p>Et l&rsquo;on recommence.</p>\n<p>L&rsquo;int&eacute;r&ecirc;t de cette danse r&eacute;side dans sa figure libre, sobre ou os&eacute;e, et sa difficult&eacute; dans le nez &agrave; nez.</p>\n<p>Il arrive lors de cette figure que, emport&eacute;s par le mouvement, les visages se heurtent violemment, ce qui produit toujours une mauvaise impression chez le partenaire.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_2.webp","effects":[],"_id":"8p4pMXbgY4S5fZjJ"} {"name":"La peccadille","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.8p4pMXbgY4S5fZjJ"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_2.webp","effects":[],"_id":"8p4pMXbgY4S5fZjJ","system":{"description":"<p>La peccadille se danse &agrave; deux, comme la valse ou le tango. Plus lente et moins rythm&eacute;e&nbsp; que les deux premi&egrave;res, elle comporte quatre figures :</p>\n<p>1) les cavaliers se tiennent par les mains</p>\n<p>2) ils se tiennent par la taille</p>\n<p>3) figure libre, improvis&eacute;e par celui ou celle qui a invit&eacute; l&rsquo;autre</p>\n<p>4) les deux visages doivent se rapprocher de fa&ccedil;on &agrave; se toucher par le bout du nez &agrave; l&rsquo;exclusion de toute autre partie du corps.</p>\n<p>Et l&rsquo;on recommence.</p>\n<p>L&rsquo;int&eacute;r&ecirc;t de cette danse r&eacute;side dans sa figure libre, sobre ou os&eacute;e, et sa difficult&eacute; dans le nez &agrave; nez.</p>\n<p>Il arrive lors de cette figure que, emport&eacute;s par le mouvement, les visages se heurtent violemment, ce qui produit toujours une mauvaise impression chez le partenaire.</p>","descriptionmj":"","type":"recreative","agilite":false,"apparence":true,"niveau":2,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281604,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Les dragons","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"reflexion","base":-8,"caraccomp":"Intellect","description":"<p>Les dragons sont les &eacute;checs draconics.</p>\n<p>Plus complexes et soumis &agrave; beaucoup plus de variantes que nos &eacute;checs, les dragons se jouent sur un plateau de 7 x 7 cases. Chaque joueur poss&egrave;de 14 pi&egrave;ces : le voyageur, le haut-r&ecirc;vant, la pucelle, le groin, le m&eacute;nestrel, l&rsquo;archer, la maison, et 7 arbres.</p>\n<p>Les arbres sont l&rsquo;&eacute;quivalent des pions et servent &agrave; constituer les for&ecirc;ts. Les joueurs ne jouent pas l&rsquo;un en face de l&rsquo;autre, mais c&ocirc;te &agrave; c&ocirc;te, avec l&rsquo;&eacute;chiquier devant eux. Il y a ainsi le joueur de droite qui plante la for&ecirc;t dite dextriote, et le joueur de gauche qui plante la for&ecirc;t sinistrante. Quelle que soit la variante jou&eacute;e, l&rsquo;&eacute;chiquier commence vide, les joueurs introduisant leurs pi&egrave;ces, arbres ou autres, l&rsquo;un apr&egrave;s l&rsquo;autre.</p>\n<p>Selon les variantes, les pi&egrave;ces ne se d&eacute;placent pas de la m&ecirc;me fa&ccedil;on. Les arbres ne prennent ni ne se d&eacute;placent jamais. Ils servent d&rsquo;obstacle aux lignes de d&eacute;placement des autres pi&egrave;ces. Seuls les haut-r&ecirc;vants peuvent les prendre dans certaines variantes.</p>\n<p>Les maisons, &eacute;galement fixes, ne peuvent &ecirc;tre prises que quand elles sont vides. Selon les variantes, elles peuvent contenir de deux &agrave; quatre autres pi&egrave;ces (qui coexistent sur la m&ecirc;me case), sauf des arbres. Dans la maison les pi&egrave;ces sont prot&eacute;g&eacute;es, on ne peut les prendre. Une variante permet d&rsquo;agrandir la maison en sacrifiant un arbre.</p>\n<p>Selon une autre, les archers peuvent augmenter leur nombre de fl&egrave;ches en sacrifiant &eacute;galement un arbre.</p>\n<p>Dans la variante traditionnelle, la plus ancienne, le but du jeu est d&rsquo;investir la maison adverse. Cela suppose qu&rsquo;elle soit vide. Il faut pr&eacute;alablement &eacute;liminer ou neutraliser les pi&egrave;ces en dehors, jusqu&rsquo;&agrave; obliger les occupants de la maison &agrave; sortir (comme aux &eacute;checs, on ne peut passer son coup, on doit effectuer un mouvement).</p>\n<p>Dans des variantes plus r&eacute;centes, plus faciles, le but est de capturer une certaine pi&egrave;ce adverse, g&eacute;n&eacute;ralement le groin ou la pucelle (qui joue l&rsquo;&eacute;quivalent du roi de nos &eacute;checs). Une variante tr&egrave;s populaire oblige que ce soit le groin qui capture la pucelle.</p>\n<p>La dur&eacute;e d&rsquo;une partie de dragons est en moyenne d&rsquo;une heure.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_calculs.webp","effects":[],"_id":"AVAMD5C2mxuOfwV4"} {"name":"Les dragons","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.AVAMD5C2mxuOfwV4"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_calculs.webp","effects":[],"_id":"AVAMD5C2mxuOfwV4","system":{"description":"<p>Les dragons sont les &eacute;checs draconics.</p>\n<p>Plus complexes et soumis &agrave; beaucoup plus de variantes que nos &eacute;checs, les dragons se jouent sur un plateau de 7 x 7 cases. Chaque joueur poss&egrave;de 14 pi&egrave;ces : le voyageur, le haut-r&ecirc;vant, la pucelle, le groin, le m&eacute;nestrel, l&rsquo;archer, la maison, et 7 arbres.</p>\n<p>Les arbres sont l&rsquo;&eacute;quivalent des pions et servent &agrave; constituer les for&ecirc;ts. Les joueurs ne jouent pas l&rsquo;un en face de l&rsquo;autre, mais c&ocirc;te &agrave; c&ocirc;te, avec l&rsquo;&eacute;chiquier devant eux. Il y a ainsi le joueur de droite qui plante la for&ecirc;t dite dextriote, et le joueur de gauche qui plante la for&ecirc;t sinistrante. Quelle que soit la variante jou&eacute;e, l&rsquo;&eacute;chiquier commence vide, les joueurs introduisant leurs pi&egrave;ces, arbres ou autres, l&rsquo;un apr&egrave;s l&rsquo;autre.</p>\n<p>Selon les variantes, les pi&egrave;ces ne se d&eacute;placent pas de la m&ecirc;me fa&ccedil;on. Les arbres ne prennent ni ne se d&eacute;placent jamais. Ils servent d&rsquo;obstacle aux lignes de d&eacute;placement des autres pi&egrave;ces. Seuls les haut-r&ecirc;vants peuvent les prendre dans certaines variantes.</p>\n<p>Les maisons, &eacute;galement fixes, ne peuvent &ecirc;tre prises que quand elles sont vides. Selon les variantes, elles peuvent contenir de deux &agrave; quatre autres pi&egrave;ces (qui coexistent sur la m&ecirc;me case), sauf des arbres. Dans la maison les pi&egrave;ces sont prot&eacute;g&eacute;es, on ne peut les prendre. Une variante permet d&rsquo;agrandir la maison en sacrifiant un arbre.</p>\n<p>Selon une autre, les archers peuvent augmenter leur nombre de fl&egrave;ches en sacrifiant &eacute;galement un arbre.</p>\n<p>Dans la variante traditionnelle, la plus ancienne, le but du jeu est d&rsquo;investir la maison adverse. Cela suppose qu&rsquo;elle soit vide. Il faut pr&eacute;alablement &eacute;liminer ou neutraliser les pi&egrave;ces en dehors, jusqu&rsquo;&agrave; obliger les occupants de la maison &agrave; sortir (comme aux &eacute;checs, on ne peut passer son coup, on doit effectuer un mouvement).</p>\n<p>Dans des variantes plus r&eacute;centes, plus faciles, le but est de capturer une certaine pi&egrave;ce adverse, g&eacute;n&eacute;ralement le groin ou la pucelle (qui joue l&rsquo;&eacute;quivalent du roi de nos &eacute;checs). Une variante tr&egrave;s populaire oblige que ce soit le groin qui capture la pucelle.</p>\n<p>La dur&eacute;e d&rsquo;une partie de dragons est en moyenne d&rsquo;une heure.</p>","descriptionmj":"","type":"reflexion","base":-8,"caraccomp":"Intellect","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281605,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La mort dAmarak","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":6,"description":"<p>&Eacute;pop&eacute;e &agrave; gros budget et effets sp&eacute;ciaux spectaculaires.</p>\n<p>Amarak, ayant bu une potion de gigantisme, meurt en se cognant la t&ecirc;te dans la lune.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_6.webp","effects":[],"_id":"C5smOdHzrDHlrrZq"} {"name":"La mort dAmarak","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.C5smOdHzrDHlrrZq"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_6.webp","effects":[],"_id":"C5smOdHzrDHlrrZq","system":{"description":"<p>&Eacute;pop&eacute;e &agrave; gros budget et effets sp&eacute;ciaux spectaculaires.</p>\n<p>Amarak, ayant bu une potion de gigantisme, meurt en se cognant la t&ecirc;te dans la lune.</p>","descriptionmj":"","niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281605,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La princesse endormie","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":7,"description":"<p>Ballade sur une princesse qui se pique le doigt et dort tr&egrave;s longtemps suite &agrave; un mal&eacute;fice.</p>\n<p>Les derniers couplets sont malheureusement oubli&eacute;s, de sorte que la chanson ne finit pas.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_7.webp","effects":[],"_id":"CBpwK9udfdzlWbfb"} {"name":"La princesse endormie","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.CBpwK9udfdzlWbfb"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_7.webp","effects":[],"_id":"CBpwK9udfdzlWbfb","system":{"description":"<p>Ballade sur une princesse qui se pique le doigt et dort tr&egrave;s longtemps suite &agrave; un mal&eacute;fice.</p>\n<p>Les derniers couplets sont malheureusement oubli&eacute;s, de sorte que la chanson ne finit pas.</p>","descriptionmj":"","niveau":7,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870030,"modifiedTime":1671048281605,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Le mal rêvé","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":4,"description":"<p>Complainte sur la destin&eacute;e mis&eacute;rable d&rsquo;un homme qui avait les oreilles &agrave; la place des genoux.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_4.webp","effects":[],"_id":"FcTMJE5Wfd02axxd"} {"name":"Le mal rêvé","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.FcTMJE5Wfd02axxd"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_4.webp","effects":[],"_id":"FcTMJE5Wfd02axxd","system":{"description":"<p>Complainte sur la destin&eacute;e mis&eacute;rable d&rsquo;un homme qui avait les oreilles &agrave; la place des genoux.</p>","descriptionmj":"","niveau":4,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870031,"modifiedTime":1671048281605,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La plumette","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"adressehasard","base":-4,"caraccomp":"Dextérité / Volonté","description":"<p>Jeu d&rsquo;adresse et de volont&eacute;, la plumette se joue &agrave; deux, chacun chatouillant le visage de l&rsquo;autre avec une plume. Les visages doivent rester imperturbables.</p>\n<p>Le premier qui trahit un signe quelconque (rire, &eacute;ternuement, grimace) a perdu.</p>\n<p>Pour simuler une partie, utiliser les r&egrave;gles de combat, chacun &agrave; tour de r&ocirc;le attaquant ou tentant de parer l&rsquo;adversaire.</p>\n<p>Pour attaquer, utiliser DEXT&Eacute;RIT&Eacute;/Jeu difficult&eacute; libre et pour parer VOLONT&Eacute;/Jeu &agrave; la difficult&eacute; de l&rsquo;attaque. Le vainqueur est le premier &agrave; r&eacute;ussir une attaque non par&eacute;e.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_plumette.webp","effects":[],"_id":"HyOXCAtpaP7eaHGj"} {"name":"La plumette","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.HyOXCAtpaP7eaHGj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_plumette.webp","effects":[],"_id":"HyOXCAtpaP7eaHGj","system":{"description":"<p>Jeu d&rsquo;adresse et de volont&eacute;, la plumette se joue &agrave; deux, chacun chatouillant le visage de l&rsquo;autre avec une plume. Les visages doivent rester imperturbables.</p>\n<p>Le premier qui trahit un signe quelconque (rire, &eacute;ternuement, grimace) a perdu.</p>\n<p>Pour simuler une partie, utiliser les r&egrave;gles de combat, chacun &agrave; tour de r&ocirc;le attaquant ou tentant de parer l&rsquo;adversaire.</p>\n<p>Pour attaquer, utiliser DEXT&Eacute;RIT&Eacute;/Jeu difficult&eacute; libre et pour parer VOLONT&Eacute;/Jeu &agrave; la difficult&eacute; de l&rsquo;attaque. Le vainqueur est le premier &agrave; r&eacute;ussir une attaque non par&eacute;e.</p>","descriptionmj":"","type":"adressehasard","base":-4,"caraccomp":"Dextérité / Volonté","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870032,"modifiedTime":1671048281605,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La bergamasque","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":false,"apparence":true,"niveau":5,"description":"<p>La bergamasque reprend le principe de la sarabande, mais sur un rythme plus vif et des figures plus compliqu&eacute;es.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_5.webp","effects":[],"_id":"KJ0Ck2G2t4lYIKJH"} {"name":"La bergamasque","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.KJ0Ck2G2t4lYIKJH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_5.webp","effects":[],"_id":"KJ0Ck2G2t4lYIKJH","system":{"description":"<p>La bergamasque reprend le principe de la sarabande, mais sur un rythme plus vif et des figures plus compliqu&eacute;es.</p>","descriptionmj":"","type":"recreative","agilite":false,"apparence":true,"niveau":5,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870032,"modifiedTime":1671048281606,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Les calculs","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"reflexion","base":-6,"caraccomp":"Intellect","description":"<p>Ce jeu se pratique avec des calculs, c&rsquo;est &agrave;-dire des petits cailloux, que l&rsquo;on pose alternativement sur une surface grill&eacute;e.</p>\n<p>La strat&eacute;gie est &agrave; mi-chemin entre le go et le morpion.</p>\n<p>Tr&egrave;s pratiqu&eacute;, ce jeu peut &ecirc;tre facilement improvis&eacute; en tra&ccedil;ant la grille &agrave; la craie sur une table, ou &agrave; l&rsquo;ext&eacute;rieur, sur du sable lisse.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_calculs.webp","effects":[],"_id":"MixMWkfRpEN51QuP"} {"name":"Les calculs","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.MixMWkfRpEN51QuP"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_calculs.webp","effects":[],"_id":"MixMWkfRpEN51QuP","system":{"description":"<p>Ce jeu se pratique avec des calculs, c&rsquo;est &agrave;-dire des petits cailloux, que l&rsquo;on pose alternativement sur une surface grill&eacute;e.</p>\n<p>La strat&eacute;gie est &agrave; mi-chemin entre le go et le morpion.</p>\n<p>Tr&egrave;s pratiqu&eacute;, ce jeu peut &ecirc;tre facilement improvis&eacute; en tra&ccedil;ant la grille &agrave; la craie sur une table, ou &agrave; l&rsquo;ext&eacute;rieur, sur du sable lisse.</p>","descriptionmj":"","type":"reflexion","base":-6,"caraccomp":"Intellect","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870032,"modifiedTime":1671048281606,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La serpentine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":1,"description":"<p>Danse basique, lente ou vive, ondulante et serpentine.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_1.webp","effects":[],"_id":"N7bgcR8OEh6MpfiF"} {"name":"La serpentine","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.N7bgcR8OEh6MpfiF"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_1.webp","effects":[],"_id":"N7bgcR8OEh6MpfiF","system":{"description":"<p>Danse basique, lente ou vive, ondulante et serpentine.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":1,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870032,"modifiedTime":1671048281606,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Rêve de Dragon","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":8,"description":"<p>R&eacute;citatif, dont la moralit&eacute; se r&eacute;sume ainsi : puisque tout n&rsquo;est qu&rsquo;un r&ecirc;ve, allons dormir.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_8.webp","effects":[],"_id":"OTRi9mHhIANUnPA7"} {"name":"Rêve de Dragon","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.OTRi9mHhIANUnPA7"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_8.webp","effects":[],"_id":"OTRi9mHhIANUnPA7","system":{"description":"<p>R&eacute;citatif, dont la moralit&eacute; se r&eacute;sume ainsi : puisque tout n&rsquo;est qu&rsquo;un r&ecirc;ve, allons dormir.</p>","descriptionmj":"","niveau":8,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870033,"modifiedTime":1671048281607,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Choucroume","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":2,"ingredients":"<ul>\n<li>1 livre de chou &eacute;minc&eacute;</li>\n<li>2 doigts d&rsquo;huile</li>\n<li>1 pinte de bi&egrave;re</li>\n<li>sel</li>\n<li>8 brins d&rsquo;aromates (b&eacute;jaune, luciane)</li>\n</ul>\n<p>&nbsp;</p>\n<p>Une variante appel&eacute;e choucroume liquide utilise le double de bi&egrave;re (2 pintes) et se consomme froide.</p>","duree":"30 minutes","sust":8,"description":"<p>Vari&eacute;t&eacute; de bloutade au chou, cuite dans de la bi&egrave;re.</p>\n<p>&Eacute;mincer finement le chou et le faire revenir dans l&rsquo;huile.</p>\n<p>Ajouter la bi&egrave;re, le sel, les aromates, puis cuire sans cesser de touiller comme pour une bloutade ordinaire.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_2.webp","effects":[],"_id":"POuOV6xoPnO0b9OQ"} {"name":"Choucroume","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.POuOV6xoPnO0b9OQ"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_2.webp","effects":[],"_id":"POuOV6xoPnO0b9OQ","system":{"description":"<p>Vari&eacute;t&eacute; de bloutade au chou, cuite dans de la bi&egrave;re.</p>\n<p>&Eacute;mincer finement le chou et le faire revenir dans l&rsquo;huile.</p>\n<p>Ajouter la bi&egrave;re, le sel, les aromates, puis cuire sans cesser de touiller comme pour une bloutade ordinaire.</p>","descriptionmj":"","niveau":2,"ingredients":"<ul>\n<li>1 livre de chou &eacute;minc&eacute;</li>\n<li>2 doigts d&rsquo;huile</li>\n<li>1 pinte de bi&egrave;re</li>\n<li>sel</li>\n<li>8 brins d&rsquo;aromates (b&eacute;jaune, luciane)</li>\n</ul>\n<p>&nbsp;</p>\n<p>Une variante appel&eacute;e choucroume liquide utilise le double de bi&egrave;re (2 pintes) et se consomme froide.</p>","duree":"30 minutes","sust":8,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870033,"modifiedTime":1671048281607,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La turlutaine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":false,"apparence":true,"niveau":3,"description":"<p>Sarabande simplifi&eacute;e dans&eacute;e par les villageois, moins lente et moins guind&eacute;e que cette derni&egrave;re.</p>\n<p>On danse tant&ocirc;t en groupe, tant&ocirc;t par couples, avec changements de partenaire.</p>\n<p>Au moment de la s&eacute;paration pour reformer le groupe, les partenaires s&rsquo;envoient des baisers du bout des doigts.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_3.webp","effects":[],"_id":"Q5Lx4WWKWGFjF9cX"} {"name":"La turlutaine","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.Q5Lx4WWKWGFjF9cX"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_3.webp","effects":[],"_id":"Q5Lx4WWKWGFjF9cX","system":{"description":"<p>Sarabande simplifi&eacute;e dans&eacute;e par les villageois, moins lente et moins guind&eacute;e que cette derni&egrave;re.</p>\n<p>On danse tant&ocirc;t en groupe, tant&ocirc;t par couples, avec changements de partenaire.</p>\n<p>Au moment de la s&eacute;paration pour reformer le groupe, les partenaires s&rsquo;envoient des baisers du bout des doigts.</p>","descriptionmj":"","type":"recreative","agilite":false,"apparence":true,"niveau":3,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870033,"modifiedTime":1671048281607,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Le bourrichon","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":true,"apparence":true,"niveau":0,"description":"<p>Le bourrichon est une sorte de farandole joyeuse et rythm&eacute;e o&ugrave; un grand nombre de danseurs &eacute;voluent en se tenant par la main. Les figures sont libres, l&rsquo;essentiel &eacute;tant de garder le rythme.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_0.webp","effects":[],"_id":"QvMNog5MF3vDIBGR"} {"name":"Le bourrichon","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.QvMNog5MF3vDIBGR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_0.webp","effects":[],"_id":"QvMNog5MF3vDIBGR","system":{"description":"<p>Le bourrichon est une sorte de farandole joyeuse et rythm&eacute;e o&ugrave; un grand nombre de danseurs &eacute;voluent en se tenant par la main. Les figures sont libres, l&rsquo;essentiel &eacute;tant de garder le rythme.</p>","descriptionmj":"","type":"recreative","agilite":true,"apparence":true,"niveau":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870033,"modifiedTime":1671048281607,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Grabuge","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":3,"ingredients":"<ul>\n<li>1 livre de tomari</li>\n<li>1 livre de poisson (mer ou eau douce)</li>\n<li>2 poireaux</li>\n<li>6 oignons</li>\n<li>1 laitue</li>\n<li>2 schouillats de beurre</li>\n<li>2 doigts d&rsquo;huile</li>\n<li>1 doigt de vinaigre</li>\n<li>eau</li>\n<li>sel</li>\n<li>6 brins de luciane</li>\n<li>6 brins de klampine</li>\n<li>8 brins de pif-paf</li>\n</ul>","duree":"60 minutes","sust":12,"description":"<p>Plat de tomari, de plures et de poisson mijot&eacute; au pif-paf.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_3.webp","effects":[],"_id":"RvsPbA1ehQgRvGu6"} {"name":"Grabuge","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.RvsPbA1ehQgRvGu6"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_3.webp","effects":[],"_id":"RvsPbA1ehQgRvGu6","system":{"description":"<p>Plat de tomari, de plures et de poisson mijot&eacute; au pif-paf.</p>","descriptionmj":"","niveau":3,"ingredients":"<ul>\n<li>1 livre de tomari</li>\n<li>1 livre de poisson (mer ou eau douce)</li>\n<li>2 poireaux</li>\n<li>6 oignons</li>\n<li>1 laitue</li>\n<li>2 schouillats de beurre</li>\n<li>2 doigts d&rsquo;huile</li>\n<li>1 doigt de vinaigre</li>\n<li>eau</li>\n<li>sel</li>\n<li>6 brins de luciane</li>\n<li>6 brins de klampine</li>\n<li>8 brins de pif-paf</li>\n</ul>","duree":"60 minutes","sust":12,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870033,"modifiedTime":1671048281608,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La danse du feu","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":5,"description":"<p>La danse du feu se danse usuellement de nuit et pr&egrave;s d&rsquo;un feu.</p>\n<p>Lente, aux mouvements plus sugg&eacute;r&eacute;s que marqu&eacute;s, elle est imitative des flammes, comme si le danseur avait le feu pour partenaire.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_5.webp","effects":[],"_id":"UBVYoQmilTmkqppd"} {"name":"La danse du feu","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.UBVYoQmilTmkqppd"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_5.webp","effects":[],"_id":"UBVYoQmilTmkqppd","system":{"description":"<p>La danse du feu se danse usuellement de nuit et pr&egrave;s d&rsquo;un feu.</p>\n<p>Lente, aux mouvements plus sugg&eacute;r&eacute;s que marqu&eacute;s, elle est imitative des flammes, comme si le danseur avait le feu pour partenaire.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":5,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281608,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La danse du voile","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":6,"description":"<p>De caract&egrave;re libre, tant&ocirc;t alti&egrave;re comme la souveraine ou d&eacute;hanch&eacute;e comme la callipyge, cette danse utilise un voile comme accessoire (pi&egrave;ce de tissu, ch&acirc;le, &eacute;charpe, etc.).</p>\n<p>Son int&eacute;r&ecirc;t r&eacute;side dans les mouvements du voile avec lesquels s&rsquo;harmonisent ceux de la danseuse.</p>\n<p>Peu pratiqu&eacute;e par les hommes.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_6.webp","effects":[],"_id":"Ui1bMMBBdxMb2AZ2"} {"name":"La danse du voile","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.Ui1bMMBBdxMb2AZ2"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_6.webp","effects":[],"_id":"Ui1bMMBBdxMb2AZ2","system":{"description":"<p>De caract&egrave;re libre, tant&ocirc;t alti&egrave;re comme la souveraine ou d&eacute;hanch&eacute;e comme la callipyge, cette danse utilise un voile comme accessoire (pi&egrave;ce de tissu, ch&acirc;le, &eacute;charpe, etc.).</p>\n<p>Son int&eacute;r&ecirc;t r&eacute;side dans les mouvements du voile avec lesquels s&rsquo;harmonisent ceux de la danseuse.</p>\n<p>Peu pratiqu&eacute;e par les hommes.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281608,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Fleur de haut-rêve","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":1,"description":"<p>Romance &agrave; l&rsquo;eau de rose sur les malheurs d&rsquo;une jeune haut-r&ecirc;vante.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"Y5rAtXL0WxOqqbZs"} {"name":"Fleur de haut-rêve","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.Y5rAtXL0WxOqqbZs"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"Y5rAtXL0WxOqqbZs","system":{"description":"<p>Romance &agrave; l&rsquo;eau de rose sur les malheurs d&rsquo;une jeune haut-r&ecirc;vante.</p>","descriptionmj":"","niveau":1,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La souveraine","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":4,"description":"<p>Danse tr&egrave;s lente, sobre, hi&eacute;ratique, plus caract&eacute;ris&eacute;e par ses poses que par ses mouvements.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_4.webp","effects":[],"_id":"Y791UctCHALnBgjO"} {"name":"La souveraine","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.Y791UctCHALnBgjO"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_4.webp","effects":[],"_id":"Y791UctCHALnBgjO","system":{"description":"<p>Danse tr&egrave;s lente, sobre, hi&eacute;ratique, plus caract&eacute;ris&eacute;e par ses poses que par ses mouvements.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":4,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Bras de fer","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"adressehasard","base":-4,"caraccomp":"Force","description":"<p>Pour attaquer, utiliser Force/Jeu difficult&eacute; libre.&nbsp; Pour parer, l'opposant joue pareillement&nbsp; Force/Jeu &agrave; la difficult&eacute; de l&rsquo;attaque.</p>\n<p>Le vainqueur est le premier &agrave; r&eacute;ussir une attaque non par&eacute;e.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_brasdefer.webp","effects":[],"_id":"ZJvL0e5hjuws7mIH"} {"name":"Bras de fer","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.ZJvL0e5hjuws7mIH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_brasdefer.webp","effects":[],"_id":"ZJvL0e5hjuws7mIH","system":{"description":"<p>Pour attaquer, utiliser Force/Jeu difficult&eacute; libre.&nbsp; Pour parer, l'opposant joue pareillement&nbsp; Force/Jeu &agrave; la difficult&eacute; de l&rsquo;attaque.</p>\n<p>Le vainqueur est le premier &agrave; r&eacute;ussir une attaque non par&eacute;e.</p>","descriptionmj":"","type":"adressehasard","base":-4,"caraccomp":"Force","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La chèvre rose","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":3,"description":"<p>Ballade comique sur une ch&egrave;vre de la couleur en question, qui s&rsquo;av&egrave;re finalement &ecirc;tre une princesse m&eacute;tamorphos&eacute;e par un mal&eacute;fice.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_3.webp","effects":[],"_id":"aB78Io55m2kXDjwQ"} {"name":"La chèvre rose","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.aB78Io55m2kXDjwQ"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_3.webp","effects":[],"_id":"aB78Io55m2kXDjwQ","system":{"description":"<p>Ballade comique sur une ch&egrave;vre de la couleur en question, qui s&rsquo;av&egrave;re finalement &ecirc;tre une princesse m&eacute;tamorphos&eacute;e par un mal&eacute;fice.</p>","descriptionmj":"","niveau":3,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870034,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Tripotée","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":2,"ingredients":"<ul>\n<li>1/2 livre de cosses</li>\n<li>1/2 livre de porte-p&eacute;pins</li>\n<li>1/2 livre de racines</li>\n<li>eau</li>\n<li>5 schouillats de farine de bl&eacute;di&egrave;ze</li>\n<li>3 schouillats de farine de bloute</li>\n<li>4 brins de b&eacute;jaune</li>\n<li>2 brins de muscaline</li>\n<li>2 brins de p&egrave;pre</li>\n</ul>","duree":"40 minutes","sust":6,"description":"<p>Soupe v&eacute;g&eacute;tarienne comprenant des l&eacute;gumes de chacune des trois sortes. Selon les l&eacute;gumes utilis&eacute;s, la tripot&eacute;e peut avoir de multiples variantes, la plus courante &eacute;tant pois-quaroce-turneps.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_2.webp","effects":[],"_id":"aWfeLfT1kM2cCrNn"} {"name":"Tripotée","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.aWfeLfT1kM2cCrNn"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_2.webp","effects":[],"_id":"aWfeLfT1kM2cCrNn","system":{"description":"<p>Soupe v&eacute;g&eacute;tarienne comprenant des l&eacute;gumes de chacune des trois sortes. Selon les l&eacute;gumes utilis&eacute;s, la tripot&eacute;e peut avoir de multiples variantes, la plus courante &eacute;tant pois-quaroce-turneps.</p>","descriptionmj":"","niveau":2,"ingredients":"<ul>\n<li>1/2 livre de cosses</li>\n<li>1/2 livre de porte-p&eacute;pins</li>\n<li>1/2 livre de racines</li>\n<li>eau</li>\n<li>5 schouillats de farine de bl&eacute;di&egrave;ze</li>\n<li>3 schouillats de farine de bloute</li>\n<li>4 brins de b&eacute;jaune</li>\n<li>2 brins de muscaline</li>\n<li>2 brins de p&egrave;pre</li>\n</ul>","duree":"40 minutes","sust":6,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870035,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Tiens, vlà les Groins !","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":0,"description":"<p>Chanson de marche peu rafin&eacute;e, comme en t&eacute;moigne le refrain :</p>\n<blockquote>\n<p>&laquo; Tiens, v&rsquo;l&agrave; les Groins !</p>\n<p>&Ccedil;a y&rsquo;en a eux qui faire du foin !</p>\n<p>Quand y&rsquo;en a pr&egrave;s, y&rsquo;en a pas loin !</p>\n<p>Tiens, v&rsquo;l&agrave; les Groins ! &raquo;</p>\n</blockquote>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"dwSY0ImswRHUSuRQ"} {"name":"Tiens, vlà les Groins !","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.dwSY0ImswRHUSuRQ"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"dwSY0ImswRHUSuRQ","system":{"description":"<p>Chanson de marche peu rafin&eacute;e, comme en t&eacute;moigne le refrain :</p>\n<blockquote>\n<p>&laquo; Tiens, v&rsquo;l&agrave; les Groins !</p>\n<p>&Ccedil;a y&rsquo;en a eux qui faire du foin !</p>\n<p>Quand y&rsquo;en a pr&egrave;s, y&rsquo;en a pas loin !</p>\n<p>Tiens, v&rsquo;l&agrave; les Groins ! &raquo;</p>\n</blockquote>","descriptionmj":"","niveau":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870035,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La volée","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":true,"apparence":true,"niveau":6,"description":"<p>Danse villageoise, la vol&eacute;e est une farandole rapide incluant des sauts et des figures quasi acrobatiques, ainsi que des moments rapproch&eacute;s &agrave; deux (comme la peccadille). Elle est &eacute;videmment r&eacute;serv&eacute;e aux bons danseurs, et particuli&egrave;rement ext&eacute;nuante.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_6.webp","effects":[],"_id":"ehAslJ16qKJDrTqt"} {"name":"La volée","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.ehAslJ16qKJDrTqt"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_6.webp","effects":[],"_id":"ehAslJ16qKJDrTqt","system":{"description":"<p>Danse villageoise, la vol&eacute;e est une farandole rapide incluant des sauts et des figures quasi acrobatiques, ainsi que des moments rapproch&eacute;s &agrave; deux (comme la peccadille). Elle est &eacute;videmment r&eacute;serv&eacute;e aux bons danseurs, et particuli&egrave;rement ext&eacute;nuante.</p>","descriptionmj":"","type":"recreative","agilite":true,"apparence":true,"niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870035,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"jOL4buV3m3nHr8v7","name":"Le doublon","type":"jeu","img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_doublon.webp","data":{"type":"de","base":0,"caraccomp":"Chance","reference":"","description":"<p>Jeu de pur hasard consistant &agrave; obtenir un double avec deux d&eacute;s.</p>\n<p>Si plusieurs joueurs y parviennent, le plus haut gagne ; si aucun n&rsquo;y parvient, le coup est nul et les mises restent au pot.</p>\n<p>Pour simuler une partie de doublon, faire simplement tirer des jets de CHANCE &agrave; z&eacute;ro (ajust&eacute;s astrologiquement), mais sans comp&eacute;tence, pas m&ecirc;me Jeu, et comparer les r&eacute;sultats (&eacute;chec, r&eacute;ussite normale, significative, etc.) : le meilleur gagne. &Agrave; &eacute;galit&eacute; de r&eacute;ussites, le coup est nul.</p>"},"effects":[],"folder":null,"sort":0,"permission":{"default":0,"rYShh2P1DNavdoBD":3},"flags":{}} {"_id":"jOL4buV3m3nHr8v7","name":"Le doublon","type":"jeu","img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_doublon.webp","effects":[],"folder":null,"sort":0,"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.jOL4buV3m3nHr8v7"}},"system":{"description":"<p>Jeu de pur hasard consistant &agrave; obtenir un double avec deux d&eacute;s.</p>\n<p>Si plusieurs joueurs y parviennent, le plus haut gagne ; si aucun n&rsquo;y parvient, le coup est nul et les mises restent au pot.</p>\n<p>Pour simuler une partie de doublon, faire simplement tirer des jets de CHANCE &agrave; z&eacute;ro (ajust&eacute;s astrologiquement), mais sans comp&eacute;tence, pas m&ecirc;me Jeu, et comparer les r&eacute;sultats (&eacute;chec, r&eacute;ussite normale, significative, etc.) : le meilleur gagne. &Agrave; &eacute;galit&eacute; de r&eacute;ussites, le coup est nul.</p>","descriptionmj":"","type":"de","base":0,"caraccomp":"Chance","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870036,"modifiedTime":1671048281609,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Le rossignol dOstarlath","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":8,"description":"<p>Romance o&ugrave; les paroles, peu importantes, sont essentiellement un exercice de vocalises.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_8.webp","effects":[],"_id":"jUsy5PTDwBgDrRnq"} {"name":"Le rossignol dOstarlath","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.jUsy5PTDwBgDrRnq"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_8.webp","effects":[],"_id":"jUsy5PTDwBgDrRnq","system":{"description":"<p>Romance o&ugrave; les paroles, peu importantes, sont essentiellement un exercice de vocalises.</p>","descriptionmj":"","niveau":8,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870037,"modifiedTime":1671048281610,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Le roi des ours","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":3,"description":"<p>Sanglante &eacute;pop&eacute;e sur un th&egrave;me identique* : mal&eacute;fice, m&eacute;tamorphose et superbe vengeance finale.</p>\n<p>&nbsp;</p>\n<p><em>*voir \"La ch&egrave;vre rose\"</em></p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_3.webp","effects":[],"_id":"jUxckTsggDZBgn2W"} {"name":"Le roi des ours","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.jUxckTsggDZBgn2W"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_3.webp","effects":[],"_id":"jUxckTsggDZBgn2W","system":{"description":"<p>Sanglante &eacute;pop&eacute;e sur un th&egrave;me identique* : mal&eacute;fice, m&eacute;tamorphose et superbe vengeance finale.</p>\n<p>&nbsp;</p>\n<p><em>*voir \"La ch&egrave;vre rose\"</em></p>","descriptionmj":"","niveau":3,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870037,"modifiedTime":1671048281610,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La route est longue","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":0,"description":"<p>Chanson de marche aux couplets r&eacute;p&eacute;titifs.</p>\n<blockquote>\n<p>&laquo; Une lieue sans cheval, &ccedil;a use, &ccedil;a use</p>\n<p>Une lieue sans cheval, &ccedil;a use les sandales !&raquo;</p>\n</blockquote>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"jyPBU95uPhIhsdpa"} {"name":"La route est longue","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.jyPBU95uPhIhsdpa"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"jyPBU95uPhIhsdpa","system":{"description":"<p>Chanson de marche aux couplets r&eacute;p&eacute;titifs.</p>\n<blockquote>\n<p>&laquo; Une lieue sans cheval, &ccedil;a use, &ccedil;a use</p>\n<p>Une lieue sans cheval, &ccedil;a use les sandales !&raquo;</p>\n</blockquote>","descriptionmj":"","niveau":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870037,"modifiedTime":1671048281610,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La danse du couteau","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":6,"description":"<p>Plus masculine que f&eacute;minine, cette danse utilise un couteau (dague) comme accessoire.</p>\n<p>Elle est imitative d&rsquo;un combat.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_6.webp","effects":[],"_id":"k9EELSV0DrurUt1e"} {"name":"La danse du couteau","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.k9EELSV0DrurUt1e"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_6.webp","effects":[],"_id":"k9EELSV0DrurUt1e","system":{"description":"<p>Plus masculine que f&eacute;minine, cette danse utilise un couteau (dague) comme accessoire.</p>\n<p>Elle est imitative d&rsquo;un combat.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870037,"modifiedTime":1671048281610,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Lamour est morte","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":5,"description":"<p>Romance sentimentale d&rsquo;une tristesse &agrave; faire pleurer les cailloux.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_5.webp","effects":[],"_id":"kCU7A8fMczERjizY"} {"name":"Lamour est morte","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.kCU7A8fMczERjizY"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_5.webp","effects":[],"_id":"kCU7A8fMczERjizY","system":{"description":"<p>Romance sentimentale d&rsquo;une tristesse &agrave; faire pleurer les cailloux.</p>","descriptionmj":"","niveau":5,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870037,"modifiedTime":1671048281610,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Amandjara","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":2,"description":"<p>S&eacute;r&eacute;nade sur la l&eacute;gendaire cit&eacute; d&rsquo;Amandjara,</p>\n<p>&laquo; Perle du d&eacute;sert bleu, sur qui la lune fait les doux yeux ... &raquo;</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_2.webp","effects":[],"_id":"kiIlPL5XANy5OgYn"} {"name":"Amandjara","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.kiIlPL5XANy5OgYn"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_2.webp","effects":[],"_id":"kiIlPL5XANy5OgYn","system":{"description":"<p>S&eacute;r&eacute;nade sur la l&eacute;gendaire cit&eacute; d&rsquo;Amandjara,</p>\n<p>&laquo; Perle du d&eacute;sert bleu, sur qui la lune fait les doux yeux ... &raquo;</p>","descriptionmj":"","niveau":2,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870038,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Bloutade","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":1,"ingredients":"<ul>\n<li>1 livre de farine de bloute*</li>\n<li>1/2 livre de viande de porc ou de padongre coup&eacute;e en petits morceaux</li>\n<li>2 doigts d&rsquo;huile</li>\n<li>eau,</li>\n<li>sel</li>\n<li>8 brins d&rsquo;aromates (b&eacute;jaune, luciane)</li>\n</ul>","duree":"30 minutes","sust":8,"description":"<p>Pur&eacute;e de farine de bloute.</p>\n<p>&nbsp;</p>\n<p><strong>Bloute</strong></p>\n<p>Avec le tomari ou le bl&eacute;di&egrave;ze, la bloute est &agrave; la base de l&rsquo;alimentation dans un grand nombre d&rsquo;endroits. C&rsquo;est un tubercule de forme et de couleur voisins de notre manioc, &agrave; la chair g&eacute;latineuse et fade. Totalement immangeables telles quelles, les bloutes sont mises &agrave; s&eacute;cher sur des claies, puis broy&eacute;es en farine. Ce n&rsquo;est qu&rsquo;ainsi qu&rsquo;on peut les consommer. La farine de bloute entre dans la confection des brouets et des rago&ucirc;ts, notamment de la bloutade. Ainsi cuite, elle ressemble &agrave; du tapioca.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_1.webp","effects":[],"_id":"lv6AiGYIjtqHhn7u"} {"name":"Bloutade","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.lv6AiGYIjtqHhn7u"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_1.webp","effects":[],"_id":"lv6AiGYIjtqHhn7u","system":{"description":"<p>Pur&eacute;e de farine de bloute.</p>\n<p>&nbsp;</p>\n<p><strong>Bloute</strong></p>\n<p>Avec le tomari ou le bl&eacute;di&egrave;ze, la bloute est &agrave; la base de l&rsquo;alimentation dans un grand nombre d&rsquo;endroits. C&rsquo;est un tubercule de forme et de couleur voisins de notre manioc, &agrave; la chair g&eacute;latineuse et fade. Totalement immangeables telles quelles, les bloutes sont mises &agrave; s&eacute;cher sur des claies, puis broy&eacute;es en farine. Ce n&rsquo;est qu&rsquo;ainsi qu&rsquo;on peut les consommer. La farine de bloute entre dans la confection des brouets et des rago&ucirc;ts, notamment de la bloutade. Ainsi cuite, elle ressemble &agrave; du tapioca.</p>","descriptionmj":"","niveau":1,"ingredients":"<ul>\n<li>1 livre de farine de bloute*</li>\n<li>1/2 livre de viande de porc ou de padongre coup&eacute;e en petits morceaux</li>\n<li>2 doigts d&rsquo;huile</li>\n<li>eau,</li>\n<li>sel</li>\n<li>8 brins d&rsquo;aromates (b&eacute;jaune, luciane)</li>\n</ul>","duree":"30 minutes","sust":8,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870038,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Le tisonnier","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"carte","base":-4,"caraccomp":"Chance / Empathie","description":"<p>On commence par se mettre d&rsquo;accord sur la valeur hi&eacute;rarchique des symboles et des combinaisons possibles, puis le jeu consiste, &agrave; chaque distribution de cartes, &agrave; miser selon un syst&egrave;me de surench&egrave;res jusqu&rsquo;&agrave; ce que les cartes soient d&eacute;voil&eacute;es.</p>\n<p>La combinaison la plus forte emporte alors les mises.</p>\n<p>Le jeu demande de la chance, sans laquelle il est difficile de gagner &agrave; long terme, mais tout autant de l&rsquo;empathie pour bluffer lors des surench&egrave;res.</p>\n<p>Pour simuler une partie, jouer un jet de CHANCE &agrave; z&eacute;ro (ajust&eacute; astrologiquement), suivi d&rsquo;un jet d&rsquo;EMPATHIE/Jeu &agrave; z&eacute;ro, et additionner les points de t&acirc;che obtenus par les deux jets. Le vainqueur est celui qui en totalise le plus.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_tisonnier.webp","effects":[],"_id":"mRzHzrubRkyqHUTC"} {"name":"Le tisonnier","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.mRzHzrubRkyqHUTC"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_tisonnier.webp","effects":[],"_id":"mRzHzrubRkyqHUTC","system":{"description":"<p>On commence par se mettre d&rsquo;accord sur la valeur hi&eacute;rarchique des symboles et des combinaisons possibles, puis le jeu consiste, &agrave; chaque distribution de cartes, &agrave; miser selon un syst&egrave;me de surench&egrave;res jusqu&rsquo;&agrave; ce que les cartes soient d&eacute;voil&eacute;es.</p>\n<p>La combinaison la plus forte emporte alors les mises.</p>\n<p>Le jeu demande de la chance, sans laquelle il est difficile de gagner &agrave; long terme, mais tout autant de l&rsquo;empathie pour bluffer lors des surench&egrave;res.</p>\n<p>Pour simuler une partie, jouer un jet de CHANCE &agrave; z&eacute;ro (ajust&eacute; astrologiquement), suivi d&rsquo;un jet d&rsquo;EMPATHIE/Jeu &agrave; z&eacute;ro, et additionner les points de t&acirc;che obtenus par les deux jets. Le vainqueur est celui qui en totalise le plus.</p>","descriptionmj":"","type":"carte","base":-4,"caraccomp":"Chance / Empathie","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870038,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Plume de zyglute","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":4,"description":"<p>S&eacute;r&eacute;nade.</p>\n<p>Belle musique, mais paroles d&rsquo;une rare stupidit&eacute; :</p>\n<blockquote>\n<p>&laquo; Coin-coin, glou-glou, c&rsquo;est qui ? c&rsquo;est vous ? &raquo;</p>\n</blockquote>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_4.webp","effects":[],"_id":"nCFFhbL54WXU0FFi"} {"name":"Plume de zyglute","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.nCFFhbL54WXU0FFi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_4.webp","effects":[],"_id":"nCFFhbL54WXU0FFi","system":{"description":"<p>S&eacute;r&eacute;nade.</p>\n<p>Belle musique, mais paroles d&rsquo;une rare stupidit&eacute; :</p>\n<blockquote>\n<p>&laquo; Coin-coin, glou-glou, c&rsquo;est qui ? c&rsquo;est vous ? &raquo;</p>\n</blockquote>","descriptionmj":"","niveau":4,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870038,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Lauberge noire","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":5,"description":"<p>Complainte macabre sur un aubergiste qui assassine ses clients avec la r&acirc;pe &agrave; fromage.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_5.webp","effects":[],"_id":"srNKj5s0TOw7VDQ4"} {"name":"Lauberge noire","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.srNKj5s0TOw7VDQ4"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_5.webp","effects":[],"_id":"srNKj5s0TOw7VDQ4","system":{"description":"<p>Complainte macabre sur un aubergiste qui assassine ses clients avec la r&acirc;pe &agrave; fromage.</p>","descriptionmj":"","niveau":5,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870038,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Ma chope est vide !","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":0,"description":"<p>Chanson &agrave; boire peu raffin&eacute;e.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"uGVOeSq2ZKMG8VjU"} {"name":"Ma chope est vide !","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.uGVOeSq2ZKMG8VjU"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp","effects":[],"_id":"uGVOeSq2ZKMG8VjU","system":{"description":"<p>Chanson &agrave; boire peu raffin&eacute;e.</p>","descriptionmj":"","niveau":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870039,"modifiedTime":1671048281611,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La callipyge","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"soliste","agilite":false,"apparence":true,"niveau":2,"description":"<p>Comme la serpentine, avec des effets plus marqu&eacute;s, essentiellement bas&eacute;e sur les mouvements du bassin. La callipyge n&rsquo;est g&eacute;n&eacute;ralement dans&eacute;e que par les femmes.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_2.webp","effects":[],"_id":"uf7a9D5RYw7gOi36"} {"name":"La callipyge","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.uf7a9D5RYw7gOi36"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_sol_2.webp","effects":[],"_id":"uf7a9D5RYw7gOi36","system":{"description":"<p>Comme la serpentine, avec des effets plus marqu&eacute;s, essentiellement bas&eacute;e sur les mouvements du bassin. La callipyge n&rsquo;est g&eacute;n&eacute;ralement dans&eacute;e que par les femmes.</p>","descriptionmj":"","type":"soliste","agilite":false,"apparence":true,"niveau":2,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870039,"modifiedTime":1671048281612,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La gambade","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":true,"apparence":true,"niveau":1,"description":"<p>Gigue endiabl&eacute;e, proche du bourrichon, mais avec des figures un peu moins sommaires.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_1.webp","effects":[],"_id":"uxdljYU7TlC2F6oA"} {"name":"La gambade","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.uxdljYU7TlC2F6oA"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_1.webp","effects":[],"_id":"uxdljYU7TlC2F6oA","system":{"description":"<p>Gigue endiabl&eacute;e, proche du bourrichon, mais avec des figures un peu moins sommaires.</p>","descriptionmj":"","type":"recreative","agilite":true,"apparence":true,"niveau":1,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870039,"modifiedTime":1671048281612,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Trompe de padongre à la mentharde","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"recettecuisine","data":{"niveau":4,"ingredients":"<ul>\n<li>1 belle trompe de padongre (10 sust)</li>\n<li>25 schouillats de miel</li>\n<li>1 livre de beurre</li>\n<li>1 pinte de lait</li>\n<li>20 brins de mentharde</li>\n<li>sel</li>\n</ul>","duree":"90 minutes","sust":12,"description":"<p>Enduite de miel, de beurre et entour&eacute;e de feuilles de mentharde fra&icirc;ches, la trompe de padongre doit &ecirc;tre cuite au four et arros&eacute;e r&eacute;guli&egrave;rement de lait. Toute la difficult&eacute; r&eacute;side dans la cuisson.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_4.webp","effects":[],"_id":"uzSivEs6SFEGVoI0"} {"name":"Trompe de padongre à la mentharde","type":"recettecuisine","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.uzSivEs6SFEGVoI0"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_4.webp","effects":[],"_id":"uzSivEs6SFEGVoI0","system":{"description":"<p>Enduite de miel, de beurre et entour&eacute;e de feuilles de mentharde fra&icirc;ches, la trompe de padongre doit &ecirc;tre cuite au four et arros&eacute;e r&eacute;guli&egrave;rement de lait. Toute la difficult&eacute; r&eacute;side dans la cuisson.</p>","descriptionmj":"","niveau":4,"ingredients":"<ul>\n<li>1 belle trompe de padongre (10 sust)</li>\n<li>25 schouillats de miel</li>\n<li>1 livre de beurre</li>\n<li>1 pinte de lait</li>\n<li>20 brins de mentharde</li>\n<li>sel</li>\n</ul>","duree":"90 minutes","sust":12,"exotisme":0,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870039,"modifiedTime":1671048281613,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La triplette","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"de","base":0,"caraccomp":"Chance","description":"<p>Autre jeu de hasard, la triplette est un jeu de d&eacute;s de combinaisons se jouant avec trois d&eacute;s (sorte de 421).</p>\n<p>Pour simuler une partie de triplette, d&eacute;terminer l&rsquo;ordre dans lequel jouent les participants. Le premier &agrave; jouer peut tenter de un &agrave; trois jets de CHANCE &agrave; z&eacute;ro (ajust&eacute;s astrologiquement comme pour le doublon), et additionner les points de t&acirc;che obtenus.</p>\n<p>Attention aux &eacute;checs qui donnent des points n&eacute;gatifs ! Il peut &ecirc;tre plus judicieux de se contenter d&rsquo;un seul jet bien r&eacute;ussi.</p>\n<p>Les joueurs suivants, en effet, pourront &agrave; leur tour tenter le m&ecirc;me nombre de jets de CHANCE ou moins, mais pas davantage. Le plus grand nombre de points gagne finalement.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_doublon.webp","effects":[],"_id":"vYPjOjd3vSAvjL76"} {"name":"La triplette","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.vYPjOjd3vSAvjL76"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_doublon.webp","effects":[],"_id":"vYPjOjd3vSAvjL76","system":{"description":"<p>Autre jeu de hasard, la triplette est un jeu de d&eacute;s de combinaisons se jouant avec trois d&eacute;s (sorte de 421).</p>\n<p>Pour simuler une partie de triplette, d&eacute;terminer l&rsquo;ordre dans lequel jouent les participants. Le premier &agrave; jouer peut tenter de un &agrave; trois jets de CHANCE &agrave; z&eacute;ro (ajust&eacute;s astrologiquement comme pour le doublon), et additionner les points de t&acirc;che obtenus.</p>\n<p>Attention aux &eacute;checs qui donnent des points n&eacute;gatifs ! Il peut &ecirc;tre plus judicieux de se contenter d&rsquo;un seul jet bien r&eacute;ussi.</p>\n<p>Les joueurs suivants, en effet, pourront &agrave; leur tour tenter le m&ecirc;me nombre de jets de CHANCE ou moins, mais pas davantage. Le plus grand nombre de points gagne finalement.</p>","descriptionmj":"","type":"de","base":0,"caraccomp":"Chance","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870040,"modifiedTime":1671048281613,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Le voyageur","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":1,"description":"<p>Ballade sur les tribulations d&rsquo;un voyageur.</p>\n<p>Interminable, cette chanson poss&egrave;de plus de cent couplets.</p>\n<p>&nbsp;</p>\n<p><em>D&eacute;terminer en tirant 1d100 le nombre de couplets connus.</em></p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"vlqX5BC9recz2kM2"} {"name":"Le voyageur","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.vlqX5BC9recz2kM2"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"vlqX5BC9recz2kM2","system":{"description":"<p>Ballade sur les tribulations d&rsquo;un voyageur.</p>\n<p>Interminable, cette chanson poss&egrave;de plus de cent couplets.</p>\n<p>&nbsp;</p>\n<p><em>D&eacute;terminer en tirant 1d100 le nombre de couplets connus.</em></p>","descriptionmj":"","niveau":1,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870040,"modifiedTime":1671048281613,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La pétasse","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"jeu","data":{"type":"adressehasard","base":-6,"caraccomp":"Lancer","description":"<p>Jeu d&rsquo;adresse combinant boules et quilles.</p>\n<p>Chaque joueur dispose de plusieurs quilles, appel&eacute;es p&eacute;tasses, et de boules de bois, appel&eacute;es tronchets. Le jeu conna&icirc;t de nombreuses variantes, mais le principe g&eacute;n&eacute;ral est le m&ecirc;me : culbuter les p&eacute;tasses des adversaires en &eacute;vitant de se faire troncher les siennes.</p>\n<p>Pour simuler une partie, faire tirer &agrave; chaque participant 5 jets de Lancer/Jeu &agrave; z&eacute;ro et additionner les points de t&acirc;che obtenus. Le plus grand nombre gagne.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_petasse.webp","effects":[],"_id":"vo8GoXIBNWp1GY12"} {"name":"La pétasse","type":"jeu","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.vo8GoXIBNWp1GY12"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/jeux_petasse.webp","effects":[],"_id":"vo8GoXIBNWp1GY12","system":{"description":"<p>Jeu d&rsquo;adresse combinant boules et quilles.</p>\n<p>Chaque joueur dispose de plusieurs quilles, appel&eacute;es p&eacute;tasses, et de boules de bois, appel&eacute;es tronchets. Le jeu conna&icirc;t de nombreuses variantes, mais le principe g&eacute;n&eacute;ral est le m&ecirc;me : culbuter les p&eacute;tasses des adversaires en &eacute;vitant de se faire troncher les siennes.</p>\n<p>Pour simuler une partie, faire tirer &agrave; chaque participant 5 jets de Lancer/Jeu &agrave; z&eacute;ro et additionner les points de t&acirc;che obtenus. Le plus grand nombre gagne.</p>","descriptionmj":"","type":"adressehasard","base":-6,"caraccomp":"Lancer","reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870040,"modifiedTime":1671048281613,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"La sarabande","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"danse","data":{"type":"recreative","agilite":false,"apparence":true,"niveau":4,"description":"<p>Peu pratiqu&eacute;e dans les villages, la sarabande est une danse de cour, lente et solennelle, alternant groupe et couples, comme la turlutaine dont elle est une version &laquo;s&eacute;rieuse&raquo;.</p>\n<p>Les changements de partenaire s&rsquo;accompagnent de profondes r&eacute;v&eacute;rences.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_4.webp","effects":[],"_id":"wf1jpIZmrB5LfK93"} {"name":"La sarabande","type":"danse","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.wf1jpIZmrB5LfK93"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/danse_4.webp","effects":[],"_id":"wf1jpIZmrB5LfK93","system":{"description":"<p>Peu pratiqu&eacute;e dans les villages, la sarabande est une danse de cour, lente et solennelle, alternant groupe et couples, comme la turlutaine dont elle est une version &laquo;s&eacute;rieuse&raquo;.</p>\n<p>Les changements de partenaire s&rsquo;accompagnent de profondes r&eacute;v&eacute;rences.</p>","descriptionmj":"","type":"recreative","agilite":false,"apparence":true,"niveau":4,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870042,"modifiedTime":1671048281613,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Le retour du baron gris","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":2,"description":"<p>&Eacute;pop&eacute;e pleine de cavalcades, de trahisons, de batailles et de cervelles &eacute;clat&eacute;es.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_2.webp","effects":[],"_id":"xjITZoom3Azu9NQa"} {"name":"Le retour du baron gris","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.xjITZoom3Azu9NQa"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_2.webp","effects":[],"_id":"xjITZoom3Azu9NQa","system":{"description":"<p>&Eacute;pop&eacute;e pleine de cavalcades, de trahisons, de batailles et de cervelles &eacute;clat&eacute;es.</p>","descriptionmj":"","niveau":2,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870042,"modifiedTime":1671048281614,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Lheure de la Lyre","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":1,"description":"<p>Berceuse sur le th&egrave;me de la nuit qui descend.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"yLcvnrbqIKS4ezj7"} {"name":"Lheure de la Lyre","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.yLcvnrbqIKS4ezj7"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_1.webp","effects":[],"_id":"yLcvnrbqIKS4ezj7","system":{"description":"<p>Berceuse sur le th&egrave;me de la nuit qui descend.</p>","descriptionmj":"","niveau":1,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870043,"modifiedTime":1671048281614,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Le cavalier de sombre neige","permission":{"default":0,"rYShh2P1DNavdoBD":3},"type":"chant","data":{"niveau":6,"description":"<p>&Eacute;pop&eacute;e pleine de suspense et de terreur, o&ugrave; le soleil est rouge, la lune violette et la neige noire.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_6.webp","effects":[],"_id":"zRQ5WnPI483CKm9Q"} {"name":"Le cavalier de sombre neige","type":"chant","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.arts-et-divertissements.zRQ5WnPI483CKm9Q"}},"img":"systems/foundryvtt-reve-de-dragon/icons/arts/chant_6.webp","effects":[],"_id":"zRQ5WnPI483CKm9Q","system":{"description":"<p>&Eacute;pop&eacute;e pleine de suspense et de terreur, o&ugrave; le soleil est rouge, la lune violette et la neige noire.</p>","descriptionmj":"","niveau":6,"reference":""},"ownership":{"default":0,"rYShh2P1DNavdoBD":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047870043,"modifiedTime":1671048281614,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}

File diff suppressed because one or more lines are too long

View File

@@ -1,29 +1,29 @@
{"_id":"0zRL8bOpCXNQnIR4","name":"Ruade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.0zRL8bOpCXNQnIR4"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":4,"description":null,"descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"0zRL8bOpCXNQnIR4","name":"Ruade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.0zRL8bOpCXNQnIR4"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[],"system":{"description":null,"descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":4,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702692,"modifiedTime":1671048288982,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"4GmpkphbsmQjvVVK","name":"Escalade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.4GmpkphbsmQjvVVK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_escalade.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"4GmpkphbsmQjvVVK","name":"Escalade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.4GmpkphbsmQjvVVK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_escalade.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702692,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"6DK46pyO0hzEuuUg","name":"Morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.6DK46pyO0hzEuuUg"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"generale","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"6DK46pyO0hzEuuUg","name":"Morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.6DK46pyO0hzEuuUg"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"generale","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702692,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"categorie_parade":"","niveau":2,"default_diffLibre":0,"carac_value":14,"iscombat":true,"isparade":false,"ispossession":true,"dommages":0,"description":"<p>L'entit&eacute; tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie":"melee"},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624948267,"modifiedTime":1663625011162,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"9u16zxXRurCtxuOX","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}} {"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"description":"<p>L'entit&eacute; tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie_parade":"","niveau":2,"default_diffLibre":0,"categorie":"draconic","carac_value":14,"iscombat":true,"isnaturelle":true,"ispossession":true,"dommages":0,"isparade":false},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624976822,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"9u16zxXRurCtxuOX","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"_id":"BjqRrGtHtTzuNpZB","name":"Griffes et Crocs","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011172,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"BjqRrGtHtTzuNpZB","name":"Griffes et Crocs","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702692,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"CYpxxf1uTa78NWR9","name":"Esquive","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.CYpxxf1uTa78NWR9"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702692,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"CYpxxf1uTa78NWR9","name":"Esquive","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.CYpxxf1uTa78NWR9"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702692,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"JTuBQCPdumw3DfxH","name":"Crête","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.JTuBQCPdumw3DfxH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-crete.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":3,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"JTuBQCPdumw3DfxH","name":"Crête","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.JTuBQCPdumw3DfxH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-crete.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":3,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"Kt7WlB5Ui97X211z","name":"Vol","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Kt7WlB5Ui97X211z"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-vol.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"Kt7WlB5Ui97X211z","name":"Vol","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Kt7WlB5Ui97X211z"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-vol.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288983,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"LWQHz5ymNBzh6ZEr","name":"Cornes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.LWQHz5ymNBzh6ZEr"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-corne.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"LWQHz5ymNBzh6ZEr","name":"Cornes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.LWQHz5ymNBzh6ZEr"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-corne.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"NctG7suzvGE7ZZzj","name":"Bras-bouches","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.NctG7suzvGE7ZZzj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-brasbouche.webp","effects":[],"system":{"categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"NctG7suzvGE7ZZzj","name":"Bras-bouches","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.NctG7suzvGE7ZZzj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-brasbouche.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"OzHBowOMADRwcVXR","name":"Pierre Tenue","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.OzHBowOMADRwcVXR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierretenue.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"OzHBowOMADRwcVXR","name":"Pierre Tenue","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.OzHBowOMADRwcVXR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierretenue.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":false,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"PCwbR6lghjydTj93","name":"Grande morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.PCwbR6lghjydTj93"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"PCwbR6lghjydTj93","name":"Grande morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.PCwbR6lghjydTj93"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"PrVuVpwuYaZtwRUi","name":"Piétinement","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.PrVuVpwuYaZtwRUi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":4,"description":null,"descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702693,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"PrVuVpwuYaZtwRUi","name":"Piétinement","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.PrVuVpwuYaZtwRUi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pietinement.webp","effects":[],"system":{"description":null,"descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":4,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702693,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"RAnasKnoA3OQgwfv","name":"Pinces","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.RAnasKnoA3OQgwfv"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pinces.webp","effects":[],"system":{"categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":3,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"RAnasKnoA3OQgwfv","name":"Pinces","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.RAnasKnoA3OQgwfv"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pinces.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":3,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"XgfRxSj8Ty1d3JFM","name":"Mandibules","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.XgfRxSj8Ty1d3JFM"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-mandibules.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","carac-value":null,"categorie":"generale","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"XgfRxSj8Ty1d3JFM","name":"Mandibules","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.XgfRxSj8Ty1d3JFM"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-mandibules.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"generale","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false,"carac-value":null},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"Zpl2Bi451vB3r91W","name":"Coup de pied","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Zpl2Bi451vB3r91W"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-coup_de_pied.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":3,"description":null,"descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"Zpl2Bi451vB3r91W","name":"Coup de pied","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.Zpl2Bi451vB3r91W"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-coup_de_pied.webp","effects":[],"system":{"description":null,"descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":3,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"categorie_parade":"","niveau":2,"default_diffLibre":0,"carac_value":14,"iscombat":true,"isparade":false,"ispossession":true,"dommages":0,"description":"<p>L'entit&eacute; tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie":"draconic"},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624976822,"modifiedTime":1663625011162,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"duVgxI3Cdko0KzAj","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}} {"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"categorie_parade":"","niveau":2,"default_diffLibre":0,"carac_value":14,"iscombat":true,"isparade":false,"ispossession":true,"dommages":0,"description":"<p>L'entit&eacute; tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie":"draconic"},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624976822,"modifiedTime":1663625011162,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"_id":"duVgxI3Cdko0KzAj","folder":null,"sort":0,"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3}}
{"_id":"efl1HdDSKpBfImQ1","name":"Pierre Lancée","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.efl1HdDSKpBfImQ1"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierrelancee.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"lancer","isnaturelle":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"efl1HdDSKpBfImQ1","name":"Pierre Lancée","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.efl1HdDSKpBfImQ1"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-pierrelancee.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"lancer","carac_value":0,"iscombat":true,"isnaturelle":false,"ispossession":false,"dommages":1,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"h9ASt4vrvEgxfj7j","name":"Tronçonneuse","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.h9ASt4vrvEgxfj7j"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-tronconneuse.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":10,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"h9ASt4vrvEgxfj7j","name":"Tronçonneuse","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.h9ASt4vrvEgxfj7j"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-tronconneuse.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":10,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"jhua9kkCs55OV7Yl","name":"Grandes griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.jhua9kkCs55OV7Yl"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"jhua9kkCs55OV7Yl","name":"Grandes griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.jhua9kkCs55OV7Yl"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"lzEdMrKXbOYrWG5S","name":"Vigilance","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.lzEdMrKXbOYrWG5S"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"lzEdMrKXbOYrWG5S","name":"Vigilance","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.lzEdMrKXbOYrWG5S"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"ndNshntOYb1JFNqi","name":"Serres","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.ndNshntOYb1JFNqi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-serres.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":2,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702694,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"ndNshntOYb1JFNqi","name":"Serres","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.ndNshntOYb1JFNqi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-serres.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702694,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"os88Rsp7mBkahqmh","name":"Bec","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.os88Rsp7mBkahqmh"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-beak.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"os88Rsp7mBkahqmh","name":"Bec","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.os88Rsp7mBkahqmh"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-beak.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"qilRzXpVaGceNmQp","name":"Dague","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.qilRzXpVaGceNmQp"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dague.webp","effects":[],"system":{"categorie_parade":"dagues","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"qilRzXpVaGceNmQp","name":"Dague","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.qilRzXpVaGceNmQp"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dague.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"dagues","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":false,"ispossession":false,"dommages":1,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"qrd9AoZzFgyzFBxz","name":"Griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.qrd9AoZzFgyzFBxz"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":true,"isparade":true,"ispossession":false,"dommages":1,"description":"","descriptionmj":"","categorie":"melee","isnaturelle":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011173,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"qrd9AoZzFgyzFBxz","name":"Griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.qrd9AoZzFgyzFBxz"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"categorie":"melee","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"isparade":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288984,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"sUdXhpuVVOAlcVpo","name":"Pickpocket","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.sUdXhpuVVOAlcVpo"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_pickpocket.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"sUdXhpuVVOAlcVpo","name":"Pickpocket","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.sUdXhpuVVOAlcVpo"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_pickpocket.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288985,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"shsUV8UpU18c0RJK","name":"Course","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.shsUV8UpU18c0RJK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"shsUV8UpU18c0RJK","name":"Course","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.shsUV8UpU18c0RJK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288985,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"yBUVTjTXYfwvzusb","name":"Saut","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yBUVTjTXYfwvzusb"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":"","categorie":"generale"},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"yBUVTjTXYfwvzusb","name":"Saut","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yBUVTjTXYfwvzusb"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"generale","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288985,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"yDHZfK4RmwQW4YaW","name":"Discrétion","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yDHZfK4RmwQW4YaW"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.webp","effects":[],"system":{"categorie_parade":"","niveau":0,"default_diffLibre":0,"carac_value":0,"iscombat":false,"isparade":false,"ispossession":false,"dommages":0,"description":"","descriptionmj":""},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.16","coreVersion":"10.285","createdTime":1663624702695,"modifiedTime":1663625011174,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}} {"_id":"yDHZfK4RmwQW4YaW","name":"Discrétion","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.yDHZfK4RmwQW4YaW"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624702695,"modifiedTime":1671048288985,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}

View File

@@ -1,15 +1,15 @@
{"_id":"0Ms9iKxqigNNpZEx","name":"Esquive","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":false,"dommages":0,"description":"","categorie_parade":"","isparade":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","effects":[]} {"_id":"0Ms9iKxqigNNpZEx","name":"Esquive","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.0Ms9iKxqigNNpZEx"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895714,"modifiedTime":1671048307066,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"18wcei5hlEInsBFO","name":"Attaque","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":0,"description":"","carac-value":null,"categorie_parade":"","isparade":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[]} {"_id":"18wcei5hlEInsBFO","name":"Attaque","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.18wcei5hlEInsBFO"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":0,"carac-value":null,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895715,"modifiedTime":1671048307066,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"3Crwg8cx2JOb697T","name":"Parade","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":false,"dommages":0,"description":"","carac-value":null,"categorie_parade":"","isparade":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","effects":[]} {"_id":"3Crwg8cx2JOb697T","name":"Parade","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.3Crwg8cx2JOb697T"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":false,"isnaturelle":true,"ispossession":false,"dommages":0,"carac-value":null,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895715,"modifiedTime":1671048307066,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"6eWCVDYLXXO1Z48D","name":"Grandes griffes","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"categorie_parade":"sans-armes","niveau":0,"carac_value":0,"iscombat":true,"isparade":false,"dommages":2,"description":""},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[]} {"_id":"6eWCVDYLXXO1Z48D","name":"Grandes griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895715,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"9Y83OsQgeyR5oCdH","name":"Griffes","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","carac-value":null,"categorie_parade":"sans-armes","isparade":false},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[]} {"_id":"9Y83OsQgeyR5oCdH","name":"Griffes","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.BjqRrGtHtTzuNpZB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-griffes.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"carac-value":null,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895715,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"D9cBJ3EJPYLnABiJ","name":"Tentacules","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"categorie_parade":"boucliers","niveau":0,"carac_value":0,"iscombat":true,"isparade":true,"dommages":2,"description":"<p>Attaque ou parade avec un tentacule.</p>"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-tentacule.webp","effects":[]} {"_id":"D9cBJ3EJPYLnABiJ","name":"Tentacules","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.D9cBJ3EJPYLnABiJ"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-tentacule.webp","effects":[],"system":{"description":"<p>Attaque ou parade avec un tentacule.</p>","descriptionmj":"","categorie_parade":"boucliers","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":true},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"QGULMUoC9JXFze0r","name":"Bouclier Lourd","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":0,"description":"","carac-value":null,"categorie_parade":"boucliers","isparade":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_bouclier.webp","effects":[]} {"_id":"QGULMUoC9JXFze0r","name":"Bouclier Lourd","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.QGULMUoC9JXFze0r"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_bouclier.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"boucliers","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":0,"carac-value":null,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"WsYnwR8GcOxfuCI0","name":"Bras-Galet","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","carac-value":null,"categorie_parade":"","isparade":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","effects":[]} {"_id":"WsYnwR8GcOxfuCI0","name":"Bras-Galet","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.WsYnwR8GcOxfuCI0"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"carac-value":null,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"c0I93Q53i4ZmxpyT","name":"Corps à Corps","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":0,"description":"","categorie_parade":"sans-armes","isparade":true},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp","effects":[]} {"_id":"c0I93Q53i4ZmxpyT","name":"Corps à Corps","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"sans-armes","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"d5SZ09sFaG3cL2Rg","name":"Bec","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":0,"description":"","categorie_parade":"","isparade":false},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.os88Rsp7mBkahqmh"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-beak.webp","effects":[]} {"_id":"d5SZ09sFaG3cL2Rg","name":"Bec","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.os88Rsp7mBkahqmh"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-beak.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":0,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"db8E8HwROw1ZcwRR","name":"Crocs","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","carac-value":null,"categorie_parade":"","isparade":false},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.NctG7suzvGE7ZZzj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-brasbouche.webp","effects":[]} {"_id":"db8E8HwROw1ZcwRR","name":"Crocs","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-creatures.NctG7suzvGE7ZZzj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-brasbouche.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"carac-value":null,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895716,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"gPOQd9NI7AFH0whX","name":"Epée Bâtarde","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":4,"description":"","carac-value":null,"categorie_parade":"epees-lourdes","isparade":true},"flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-humanoides.YTKld5ggDsHqwYoR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_epee_1_main.webp","effects":[]} {"_id":"gPOQd9NI7AFH0whX","name":"Epée Bâtarde","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-humanoides.YTKld5ggDsHqwYoR"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_epee_1_main.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"epees-lourdes","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":4,"carac-value":null,"isparade":true},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895717,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"j1xHCzfIeYKgXxoH","name":"Morsure","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competencecreature","data":{"niveau":0,"carac_value":0,"iscombat":true,"dommages":1,"description":"","categorie_parade":"","isparade":false},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[]} {"_id":"j1xHCzfIeYKgXxoH","name":"Morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.j1xHCzfIeYKgXxoH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":1,"isparade":false},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895717,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"_id":"lDZ3qUPKN35ob5TH","name":"Grande morsure","permission":{"default":0,"Q2G6GTdrotKzYGUC":3},"type":"competencecreature","data":{"categorie_parade":"","niveau":0,"carac_value":0,"iscombat":true,"isparade":false,"dommages":2,"description":""},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[]} {"_id":"lDZ3qUPKN35ob5TH","name":"Grande morsure","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.lDZ3qUPKN35ob5TH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/compcreature-morsure.webp","effects":[],"system":{"description":"","descriptionmj":"","categorie_parade":"","niveau":0,"default_diffLibre":0,"categorie":"","carac_value":0,"iscombat":true,"isnaturelle":true,"ispossession":false,"dommages":2,"isparade":false},"ownership":{"default":0,"Q2G6GTdrotKzYGUC":3},"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047895717,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"categorie_parade":"","niveau":2,"default_diffLibre":-4,"categorie":"melee","carac_value":14,"iscombat":true,"isnaturelle":true,"ispossession":true,"dommages":0,"description":"<p>L'entit&eacute; tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","isparade":false},"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.0.22","coreVersion":"10.286","createdTime":1663624976822,"modifiedTime":1664918524164,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"folder":null,"sort":0,"_id":"wDHR5UHWq568lfGa"} {"name":"Possession","type":"competencecreature","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences-entites.c0I93Q53i4ZmxpyT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp","effects":[],"system":{"description":"<p>L'entit&eacute; tente de prendre possession du corps de sa victime.</p>","descriptionmj":"","categorie_parade":"","niveau":2,"default_diffLibre":-4,"categorie":"melee","carac_value":14,"iscombat":true,"isnaturelle":true,"ispossession":true,"dommages":0,"isparade":false},"ownership":{"default":0,"Hp9ImM4o9YRTSdfu":3},"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1663624976822,"modifiedTime":1671048307067,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"},"folder":null,"sort":0,"_id":"wDHR5UHWq568lfGa"}

View File

@@ -1,67 +1,67 @@
{"name":"Comédie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Lart de paraître sur une scène : jouer un rôle, déclamer des vers, mimer, conter. Peut aussi servir à simuler, mystifier.</p>\n<p>&nbsp;</p>","defaut_carac":"apparence"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp","_id":"2JLK5e97WbTM5WxX"} {"name":"Comédie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.2JLK5e97WbTM5WxX"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp","_id":"2JLK5e97WbTM5WxX","system":{"description":"<p>Lart de paraître sur une scène : jouer un rôle, déclamer des vers, mimer, conter. Peut aussi servir à simuler, mystifier.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"apparence","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890257,"modifiedTime":1671048297532,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Jeu","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"specialisee","xp":0,"description":"<p>Jeux de tripot, manipuler les dés. Connaître les jeux et les meilleures stratégies, déceler un tricheur et tricher soi-même.</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_jeu.webp","_id":"3VSMRwMYpOi83wgE"} {"name":"Jeu","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.3VSMRwMYpOi83wgE"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_jeu.webp","_id":"3VSMRwMYpOi83wgE","system":{"description":"<p>Jeux de tripot, manipuler les dés. Connaître les jeux et les meilleures stratégies, déceler un tricheur et tricher soi-même.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"specialisee","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890257,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Cuisine","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-4,"base":-4,"categorie":"generale","xp":0,"description":"<p>Identifier les saveurs culinaires, les épices et les aromates. Exécuter, inventer une recette. Faire griller un gibier sur un feu de&nbsp;camp nest généralement pas de la cuisine,&nbsp;mais de la simple survie.</p>\n<p>&nbsp;</p>","defaut_carac":"odoratgout"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_cuisine.webp","_id":"3qRzl3nhLZNsoDsI"} {"name":"Cuisine","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.3qRzl3nhLZNsoDsI"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_cuisine.webp","_id":"3qRzl3nhLZNsoDsI","system":{"description":"<p>Identifier les saveurs culinaires, les épices et les aromates. Exécuter, inventer une recette. Faire griller un gibier sur un feu de&nbsp;camp nest généralement pas de la cuisine,&nbsp;mais de la simple survie.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-4,"default_diffLibre":0,"base":-4,"categorie":"generale","xp":0,"defaut_carac":"odoratgout","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890258,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Survie en Sous-Sol","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_sous_sol.webp","_id":"6pXxEdeo7xcDvgx0"} {"name":"Survie en Sous-Sol","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.6pXxEdeo7xcDvgx0"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_sous_sol.webp","_id":"6pXxEdeo7xcDvgx0","system":{"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890258,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Corps à corps","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Groupées en une seule jusquau niveau zéro, ces compétences sont les principes de base du combat de mêlée. Corps à&nbsp;corps permet de se battre sans armes ; Es-quive permet desquiver toutes les sortes&nbsp;de coup ; Dague de mêlée permet lutilisation de la dague au contact.</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp","_id":"8Uj41cL5Qlxxy675"} {"name":"Corps à corps","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.8Uj41cL5Qlxxy675"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp","_id":"8Uj41cL5Qlxxy675","system":{"description":"<p>Groupées en une seule jusquau niveau zéro, ces compétences sont les principes de base du combat de mêlée. Corps à&nbsp;corps permet de se battre sans armes ; Es-quive permet desquiver toutes les sortes&nbsp;de coup ; Dague de mêlée permet lutilisation de la dague au contact.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890258,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Discrétion","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-4,"base":-4,"categorie":"generale","xp":0,"description":"<p>Se déplacer en silence, sans se faire remarquer, passer inaperçu, se fondre dans</p>\n<p>lanonymat, se cacher.</p>\n<p>&nbsp;</p>","defaut_carac":"agilite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.webp","_id":"94P55yZfeipCGbsr"} {"name":"Discrétion","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.94P55yZfeipCGbsr"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_discretion.webp","_id":"94P55yZfeipCGbsr","system":{"description":"<p>Se déplacer en silence, sans se faire remarquer, passer inaperçu, se fondre dans</p>\n<p>lanonymat, se cacher.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-4,"default_diffLibre":0,"base":-4,"categorie":"generale","xp":0,"defaut_carac":"agilite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890258,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Saut","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-4,"base":-4,"categorie":"generale","xp":0,"description":"<p>Sauter par-dessus un obstacle ou sauter en contrebas ; rattraper une chute en la transformant en saut.</p>\n<p>&nbsp;</p>","defaut_carac":"agilite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","_id":"9ICvksiNG6Bhm8CE"} {"name":"Saut","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.9ICvksiNG6Bhm8CE"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_saut.webp","_id":"9ICvksiNG6Bhm8CE","system":{"description":"<p>Sauter par-dessus un obstacle ou sauter en contrebas ; rattraper une chute en la transformant en saut.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-4,"default_diffLibre":0,"base":-4,"categorie":"generale","xp":0,"defaut_carac":"agilite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890259,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Navigation","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"specialisee","xp":0,"description":"<p>Connaissance des manœuvres à accomplir sur un voilier, connaissance de la mer, de ses courants (voir Navigation, p325).</p>\n<p>&nbsp;</p>","defaut_carac":"vue"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_navigation.webp","_id":"AXeWswf2Dth9ysvy"} {"name":"Navigation","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.AXeWswf2Dth9ysvy"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_navigation.webp","_id":"AXeWswf2Dth9ysvy","system":{"description":"<p>Connaissance des manœuvres à accomplir sur un voilier, connaissance de la mer, de ses courants (voir Navigation, p325).</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"specialisee","xp":0,"defaut_carac":"vue","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890259,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Séduction","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-4,"base":-4,"categorie":"generale","xp":0,"description":"<p>Lart dêtre galant, de paraître attirant. Permet les conquêtes amoureuses.</p>\n<p>&nbsp;</p>","defaut_carac":"apparence"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_seduction.webp","_id":"AbM6lJ7DI2UAWLxj"} {"name":"Séduction","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.AbM6lJ7DI2UAWLxj"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_seduction.webp","_id":"AbM6lJ7DI2UAWLxj","system":{"description":"<p>Lart dêtre galant, de paraître attirant. Permet les conquêtes amoureuses.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-4,"default_diffLibre":0,"base":-4,"categorie":"generale","xp":0,"defaut_carac":"apparence","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890260,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Masse à 2 mains","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Ces compétences permettent lutilisation des masses, gourdins, bâtons, pour attaquer, voire parer.</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_masse_2_mains.webp","_id":"BMAloiSbDKOu3b4C"} {"name":"Masse à 2 mains","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.BMAloiSbDKOu3b4C"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_masse_2_mains.webp","_id":"BMAloiSbDKOu3b4C","system":{"description":"<p>Ces compétences permettent lutilisation des masses, gourdins, bâtons, pour attaquer, voire parer.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890260,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Chirurgie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"specialisee","xp":0,"description":"<p>Lart de soigner les blessures, panser, recoudre ; savoir se servir dun rasoir. Chirurgie&nbsp;est utilisée pour accomplir premiers soins et soins complets sur toutes les blessures, et&nbsp;par extension, pour tous les actes de secourisme et de réanimation.</p>\n<p>&nbsp;</p>","defaut_carac":"dexterite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_chirurgie.webp","_id":"BlG2YPATIbnY3m9P"} {"name":"Chirurgie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.BlG2YPATIbnY3m9P"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_chirurgie.webp","_id":"BlG2YPATIbnY3m9P","system":{"description":"<p>Lart de soigner les blessures, panser, recoudre ; savoir se servir dun rasoir. Chirurgie&nbsp;est utilisée pour accomplir premiers soins et soins complets sur toutes les blessures, et&nbsp;par extension, pour tous les actes de secourisme et de réanimation.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"specialisee","xp":0,"defaut_carac":"dexterite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890260,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Survie en Montagne","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_montagne.webp","_id":"BzqBOeqS6HvJhqey"} {"name":"Survie en Montagne","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.BzqBOeqS6HvJhqey"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_montagne.webp","_id":"BzqBOeqS6HvJhqey","system":{"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890260,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Métallurgie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"specialisee","xp":0,"description":"<p>Cest au sens large le travail du métal, et principalement du fer. Battre le fer, forger, tremper, limer, poncer, riveter. Évaluer la qualité, la solidité, dun objet de fer, une arme par exemple.</p>\n<p>&nbsp;</p>","defaut_carac":"force"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_metallurgie.webp","_id":"CHyk96ypxMrg8VXh"} {"name":"Métallurgie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.CHyk96ypxMrg8VXh"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_metallurgie.webp","_id":"CHyk96ypxMrg8VXh","system":{"description":"<p>Cest au sens large le travail du métal, et principalement du fer. Battre le fer, forger, tremper, limer, poncer, riveter. Évaluer la qualité, la solidité, dun objet de fer, une arme par exemple.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"specialisee","xp":0,"defaut_carac":"force","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890260,"modifiedTime":1671048297533,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Equitation","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Monter à cheval, et, dune manière générale, connaissance des chevaux. Peut sappliquer aux autres montures de Rêve de&nbsp;Dragon : aligates, zyglutes, etc.</p>\n<p>&nbsp;</p>","defaut_carac":"agilite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_equitation.webp","_id":"F5iQNrZSeJsfyTnV"} {"name":"Equitation","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.F5iQNrZSeJsfyTnV"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_equitation.webp","_id":"F5iQNrZSeJsfyTnV","system":{"description":"<p>Monter à cheval, et, dune manière générale, connaissance des chevaux. Peut sappliquer aux autres montures de Rêve de&nbsp;Dragon : aligates, zyglutes, etc.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"agilite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890260,"modifiedTime":1671048297534,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Hache à 2 mains","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Ces deux compétences permettent lutilisation des hachettes, cognées et haches de bataille, pour attaquer.</p>\n<p>&nbsp;</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hache_a_2_mains.webp","_id":"F97wHYDsQ5UyvJnb"} {"name":"Hache à 2 mains","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.F97wHYDsQ5UyvJnb"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hache_a_2_mains.webp","_id":"F97wHYDsQ5UyvJnb","system":{"description":"<p>Ces deux compétences permettent lutilisation des hachettes, cognées et haches de bataille, pour attaquer.</p>\n<p>&nbsp;</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890260,"modifiedTime":1671048297534,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Charpenterie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Cest au sens large le travail du bois, charpenterie, menuiserie, ébénisterie. Évaluer&nbsp;la qualité, solidité, dune structure de bois.</p>\n<p>&nbsp;</p>","defaut_carac":"dexterite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_charpenterie.webp","_id":"FqLWG6xjISKMLPiX"} {"name":"Charpenterie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.FqLWG6xjISKMLPiX"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_charpenterie.webp","_id":"FqLWG6xjISKMLPiX","system":{"description":"<p>Cest au sens large le travail du bois, charpenterie, menuiserie, ébénisterie. Évaluer&nbsp;la qualité, solidité, dune structure de bois.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"dexterite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890260,"modifiedTime":1671048297534,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Astrologie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"connaissance","xp":0,"description":"<p>Connaissance des étoiles et de leur signification symbolique. Calculer les nombres astraux gouvernant la chance de chaque&nbsp;individu. Sorienter aux étoiles (voir Astrologie, p155).</p>\n<p>&nbsp;</p>","defaut_carac":"vue"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_astrologie.webp","_id":"GIIQm22Q4bBsmxpE"} {"name":"Astrologie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.GIIQm22Q4bBsmxpE"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_astrologie.webp","_id":"GIIQm22Q4bBsmxpE","system":{"description":"<p>Connaissance des étoiles et de leur signification symbolique. Calculer les nombres astraux gouvernant la chance de chaque&nbsp;individu. Sorienter aux étoiles (voir Astrologie, p155).</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"connaissance","xp":0,"defaut_carac":"vue","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890260,"modifiedTime":1671048297534,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Course","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-4,"base":-4,"categorie":"generale","xp":0,"description":"<p>Sprinter le plus vite possible, ou courir sur de longues distances en m&eacute;nageant son souffle.</p>\n<p>&nbsp;</p>","defaut_carac":"agilite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","_id":"Jz4AZdDlSjsyoUsm"} {"name":"Course","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.Jz4AZdDlSjsyoUsm"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_course.webp","_id":"Jz4AZdDlSjsyoUsm","system":{"description":"<p>Sprinter le plus vite possible, ou courir sur de longues distances en m&eacute;nageant son souffle.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-4,"default_diffLibre":0,"base":-4,"categorie":"generale","xp":0,"defaut_carac":"agilite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890261,"modifiedTime":1671048297534,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Chant","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-4,"base":-4,"categorie":"generale","xp":0,"description":"<p>Savoir chanter juste, se souvenir de mélodies, improviser.</p>\n<p>&nbsp;</p>","defaut_carac":"ouie"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_chant.webp","_id":"LE4nA119la5cd0bC"} {"name":"Chant","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.LE4nA119la5cd0bC"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_chant.webp","_id":"LE4nA119la5cd0bC","system":{"description":"<p>Savoir chanter juste, se souvenir de mélodies, improviser.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-4,"default_diffLibre":0,"base":-4,"categorie":"generale","xp":0,"defaut_carac":"ouie","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890261,"modifiedTime":1671048297534,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Danse","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-4,"base":-4,"categorie":"generale","xp":0,"description":"<p>Être capable de danser en mesure, de danser harmonieusement avec une personne</p>\n<p>ou un groupe, de charmer un public par&nbsp;une exhibition.</p>\n<p>&nbsp;</p>","defaut_carac":"agilite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_danse.webp","_id":"LhP3Y0qCBHNp2atl"} {"name":"Danse","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.LhP3Y0qCBHNp2atl"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_danse.webp","_id":"LhP3Y0qCBHNp2atl","system":{"description":"<p>Être capable de danser en mesure, de danser harmonieusement avec une personne</p>\n<p>ou un groupe, de charmer un public par&nbsp;une exhibition.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-4,"default_diffLibre":0,"base":-4,"categorie":"generale","xp":0,"defaut_carac":"agilite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890261,"modifiedTime":1671048297534,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Epée à 2 mains","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Ces compétences permettent lutilisation des sept types dépées de Rêve de Dragon pour attaquer ou parer.</p>\n<p>&nbsp;</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_epee_2_mains.webp","_id":"MLIEbxSJHkY1m3No"} {"name":"Epée à 2 mains","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.MLIEbxSJHkY1m3No"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_epee_2_mains.webp","_id":"MLIEbxSJHkY1m3No","system":{"description":"<p>Ces compétences permettent lutilisation des sept types dépées de Rêve de Dragon pour attaquer ou parer.</p>\n<p>&nbsp;</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890261,"modifiedTime":1671048297534,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Dessin","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-4,"base":-4,"categorie":"generale","xp":0,"description":"<p>Avoir le sens des proportions. Savoir dessiner, faire le portrait de quelquun, mais</p>\n<p>également savoir faire un schéma, une carte, un plan, aux proportions exactes.</p>\n<p>&nbsp;</p>","defaut_carac":"tir"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dessin.webp","_id":"OVcZE4kfiPYEOzgm"} {"name":"Dessin","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.OVcZE4kfiPYEOzgm"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dessin.webp","_id":"OVcZE4kfiPYEOzgm","system":{"description":"<p>Avoir le sens des proportions. Savoir dessiner, faire le portrait de quelquun, mais</p>\n<p>également savoir faire un schéma, une carte, un plan, aux proportions exactes.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-4,"default_diffLibre":0,"base":-4,"categorie":"generale","xp":0,"defaut_carac":"tir","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890261,"modifiedTime":1671048297534,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Orfèvrerie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"specialisee","xp":0,"description":"<p>Travail et connaissance des métaux précieux : or, argent, cuivre, étain, et par extension des pierres et perles précieuses.&nbsp;Évaluer la taille et la pureté dune gemme,&nbsp;le prix dun bijou.</p>\n<p>&nbsp;</p>","defaut_carac":"dexterite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_orfevrerie.webp","_id":"PMOjO2CdedH1UTyi"} {"name":"Orfèvrerie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.PMOjO2CdedH1UTyi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_orfevrerie.webp","_id":"PMOjO2CdedH1UTyi","system":{"description":"<p>Travail et connaissance des métaux précieux : or, argent, cuivre, étain, et par extension des pierres et perles précieuses.&nbsp;Évaluer la taille et la pureté dune gemme,&nbsp;le prix dun bijou.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"specialisee","xp":0,"defaut_carac":"dexterite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890261,"modifiedTime":1671048297535,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Serrurerie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"specialisee","xp":0,"description":"<p>Compréhension des mécaniques et mécanismes, et plus particulièrement des serrures. Comprendre un mécanisme, le faire fonctionner, le réparer, le désarmer, le crocheter.</p>\n<p>&nbsp;</p>","defaut_carac":"dexterite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_serrurerie.webp","_id":"PMnsXDyeB8w8ZG2k"} {"name":"Serrurerie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.PMnsXDyeB8w8ZG2k"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_serrurerie.webp","_id":"PMnsXDyeB8w8ZG2k","system":{"description":"<p>Compréhension des mécaniques et mécanismes, et plus particulièrement des serrures. Comprendre un mécanisme, le faire fonctionner, le réparer, le désarmer, le crocheter.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"specialisee","xp":0,"defaut_carac":"dexterite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890261,"modifiedTime":1671048297535,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Survie en Forêt","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_foret.webp","_id":"PbvubzCxnOSnWLpG"} {"name":"Survie en Forêt","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.PbvubzCxnOSnWLpG"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_foret.webp","_id":"PbvubzCxnOSnWLpG","system":{"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890261,"modifiedTime":1671048297535,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Botanique","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"connaissance","xp":0,"description":"<p>Identification des espèces végétales et de leurs propriétés. Permet de savoir si une plante connue pousse dans un milieu donné. Recherche de cette plante.</p>\n<p>&nbsp;</p>","defaut_carac":"vue"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_botanique.webp","_id":"PmwXYvmutlyQEonB"} {"name":"Botanique","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.PmwXYvmutlyQEonB"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_botanique.webp","_id":"PmwXYvmutlyQEonB","system":{"description":"<p>Identification des espèces végétales et de leurs propriétés. Permet de savoir si une plante connue pousse dans un milieu donné. Recherche de cette plante.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"connaissance","xp":0,"defaut_carac":"vue","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890262,"modifiedTime":1671048297536,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Bouclier","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Utilisation de toutes les sortes de bouclierpour parer.</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_bouclier.webp","_id":"SJE3ghtswQwP1dIy"} {"name":"Bouclier","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.SJE3ghtswQwP1dIy"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_bouclier.webp","_id":"SJE3ghtswQwP1dIy","system":{"description":"<p>Utilisation de toutes les sortes de bouclierpour parer.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890262,"modifiedTime":1671048297536,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Alchimie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"connaissance","xp":0,"description":"<p>Connaissance des recettes et préparations alchimiques. Identification, élaboration, des solutions diverses, breuvages, poudres, onguents, crèmes, etc. (voir Principes dalchimie, p357).</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_alchimie.webp","_id":"TAKRb9CdMUhs9dd4"} {"name":"Alchimie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.TAKRb9CdMUhs9dd4"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_alchimie.webp","_id":"TAKRb9CdMUhs9dd4","system":{"description":"<p>Connaissance des recettes et préparations alchimiques. Identification, élaboration, des solutions diverses, breuvages, poudres, onguents, crèmes, etc. (voir Principes dalchimie, p357).</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"connaissance","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890262,"modifiedTime":1671048297536,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Vigilance","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-4,"base":-4,"categorie":"generale","xp":0,"description":"<p>Le talent dêtre toujours sur ses gardes, prêt à déceler la moindre anomalie, de</p>\n<p>bruit, dodeur, de mouvement, etc. Permet de ne pas être surpris en combat, par</p>\n<p>exemple. Indispensable pour monter sérieusement la garde.</p>\n<p>&nbsp;</p>","defaut_carac":"volonte"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","_id":"VyAJK54OPjiRt8oH"} {"name":"Vigilance","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.VyAJK54OPjiRt8oH"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_vigilance.webp","_id":"VyAJK54OPjiRt8oH","system":{"description":"<p>Le talent dêtre toujours sur ses gardes, prêt à déceler la moindre anomalie, de</p>\n<p>bruit, dodeur, de mouvement, etc. Permet de ne pas être surpris en combat, par</p>\n<p>exemple. Indispensable pour monter sérieusement la garde.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-4,"default_diffLibre":0,"base":-4,"categorie":"generale","xp":0,"defaut_carac":"volonte","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890262,"modifiedTime":1671048297536,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Médecine","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"connaissance","xp":0,"description":"<p>Diagnostic et soin des maladies. Connaissance des remèdes.</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_medecine.webp","_id":"XK2TlYnhR8FlDaEi"} {"name":"Médecine","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.XK2TlYnhR8FlDaEi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_medecine.webp","_id":"XK2TlYnhR8FlDaEi","system":{"description":"<p>Diagnostic et soin des maladies. Connaissance des remèdes.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"connaissance","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890263,"modifiedTime":1671048297538,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Maroquinerie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"specialisee","xp":0,"description":"<p>Travail du cuir et de la peau. Dépecer correctement un animal en vue de conserver la peau, préparation au tannage, tannage. Évaluer la qualité, la solidité, dun travail de cuir.</p>\n<p>&nbsp;</p>","defaut_carac":"dexterite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_maroquinerie.webp","_id":"XYMQBxFKSs2nPW0J"} {"name":"Maroquinerie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.XYMQBxFKSs2nPW0J"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_maroquinerie.webp","_id":"XYMQBxFKSs2nPW0J","system":{"description":"<p>Travail du cuir et de la peau. Dépecer correctement un animal en vue de conserver la peau, préparation au tannage, tannage. Évaluer la qualité, la solidité, dun travail de cuir.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"specialisee","xp":0,"defaut_carac":"dexterite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890263,"modifiedTime":1671048297538,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Dague","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Pour utiliser les Dagues et les Couteaux en combat</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dague.webp","_id":"XZNm5W8nTe8aCG61"} {"name":"Dague","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.XZNm5W8nTe8aCG61"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dague.webp","_id":"XZNm5W8nTe8aCG61","system":{"description":"<p>Pour utiliser les Dagues et les Couteaux en combat</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890263,"modifiedTime":1671048297538,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Survie en Marais","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_marais.webp","_id":"azn3Sm7XYKP78huL"} {"name":"Survie en Marais","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.azn3Sm7XYKP78huL"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_marais.webp","_id":"azn3Sm7XYKP78huL","system":{"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890263,"modifiedTime":1671048297538,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Voie d'Hypnos","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"draconic","xp":0,"description":"<p>Magie dillusion, suggestion, invocation.</p>\n<p>&nbsp;</p>","defaut_carac":"reve"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","_id":"bt2cR4aE6lIOeg4F"} {"name":"Voie d'Hypnos","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.bt2cR4aE6lIOeg4F"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hypnos.webp","_id":"bt2cR4aE6lIOeg4F","system":{"description":"<p>Magie dillusion, suggestion, invocation.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"draconic","xp":0,"defaut_carac":"reve","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890263,"modifiedTime":1671048297538,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Zoologie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"connaissance","xp":0,"description":"<p>Connaissance des espèces animales, de leurs mœurs, leur des habitat.</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_zoologie.webp","_id":"c5wursWW03ckpyqn"} {"name":"Zoologie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.c5wursWW03ckpyqn"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_zoologie.webp","_id":"c5wursWW03ckpyqn","system":{"description":"<p>Connaissance des espèces animales, de leurs mœurs, leur des habitat.</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"connaissance","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890263,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Masse à 1 main","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Ces compétences permettent lutilisation des masses, gourdins, bâtons, pour attaquer, voire parer.</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_masse_1_main.webp","_id":"cMHm3gQr9rUp4iPK"} {"name":"Masse à 1 main","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.cMHm3gQr9rUp4iPK"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_masse_1_main.webp","_id":"cMHm3gQr9rUp4iPK","system":{"description":"<p>Ces compétences permettent lutilisation des masses, gourdins, bâtons, pour attaquer, voire parer.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890263,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Voie de Thanatos","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"draconic","xp":0,"description":"<p>Magie noire des forces du cauchemar.</p>\n<p>&nbsp;</p>","defaut_carac":"reve"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","_id":"dPlTQzvU3CEg5qKc"} {"name":"Voie de Thanatos","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.dPlTQzvU3CEg5qKc"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_thanatos.webp","_id":"dPlTQzvU3CEg5qKc","system":{"description":"<p>Magie noire des forces du cauchemar.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"draconic","xp":0,"defaut_carac":"reve","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890263,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Pickpocket","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Art extrêmement dangereux du vol à la tire.</p>","defaut_carac":"dexterite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_pickpocket.webp","_id":"dT5cvI7q1HcrLaT1"} {"name":"Pickpocket","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.dT5cvI7q1HcrLaT1"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_pickpocket.webp","_id":"dT5cvI7q1HcrLaT1","system":{"description":"<p>Art extrêmement dangereux du vol à la tire.</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"dexterite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890263,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Maçonnerie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Cest au sens large le travail de la pierre. Évaluer la qualité, la solidité dune struc-</p>\n<p>ture maçonnée.</p>\n<p>&nbsp;</p>","defaut_carac":"vue"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_maconnerie.webp","_id":"dwGVDTUJYP9FcmWM"} {"name":"Maçonnerie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.dwGVDTUJYP9FcmWM"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_maconnerie.webp","_id":"dwGVDTUJYP9FcmWM","system":{"description":"<p>Cest au sens large le travail de la pierre. Évaluer la qualité, la solidité dune struc-</p>\n<p>ture maçonnée.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"vue","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890264,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Epée à 1 main","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Groupées en une seule jusquau niveau zéro, ces compétences sont les principes de base du combat de mêlée. Corps à&nbsp;corps permet de se battre sans armes ; Es-quive permet desquiver toutes les sortes&nbsp;de coup ; Dague de mêlée permet lutilisation de la dague au contact.</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_epee_1_main.webp","_id":"fPhPcCP3sbS6mfbS"} {"name":"Epée à 1 main","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.fPhPcCP3sbS6mfbS"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_epee_1_main.webp","_id":"fPhPcCP3sbS6mfbS","system":{"description":"<p>Groupées en une seule jusquau niveau zéro, ces compétences sont les principes de base du combat de mêlée. Corps à&nbsp;corps permet de se battre sans armes ; Es-quive permet desquiver toutes les sortes&nbsp;de coup ; Dague de mêlée permet lutilisation de la dague au contact.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890264,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Escalade","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-4,"base":-4,"categorie":"generale","xp":0,"description":"<p>Escalader des obstacles, grimper à la corde, à un arbre, le long dune paroi.</p>\n<p>&nbsp;</p>","defaut_carac":"force"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_escalade.webp","_id":"gECPPcn6j3B3sWTS"} {"name":"Escalade","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.gECPPcn6j3B3sWTS"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_escalade.webp","_id":"gECPPcn6j3B3sWTS","system":{"description":"<p>Escalader des obstacles, grimper à la corde, à un arbre, le long dune paroi.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-4,"default_diffLibre":0,"base":-4,"categorie":"generale","xp":0,"defaut_carac":"force","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890264,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Légendes","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"connaissance","xp":0,"description":"<p>Connaissance des légendes et des faits du passé. Légendes tient lieu dhistoire.</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_legendes.webp","_id":"i3wMVkXObzlDVZTG"} {"name":"Légendes","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.i3wMVkXObzlDVZTG"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_legendes.webp","_id":"i3wMVkXObzlDVZTG","system":{"description":"<p>Connaissance des légendes et des faits du passé. Légendes tient lieu dhistoire.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"connaissance","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890264,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Fronde","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"tir","xp":0,"description":"<p>Utilisation de la fronde giratoire.</p>\n<p>&nbsp;</p>","defaut_carac":"tir"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_fronde.webp","_id":"iNXKIfaETtgSGA0S"} {"name":"Fronde","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.iNXKIfaETtgSGA0S"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_fronde.webp","_id":"iNXKIfaETtgSGA0S","system":{"description":"<p>Utilisation de la fronde giratoire.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"tir","xp":0,"defaut_carac":"tir","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890264,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Arbalète","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"tir","xp":0,"description":"<p>Utilisation de tous les types darbalètes.</p>","defaut_carac":"tir"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_arbalete.webp","_id":"lt9VC7PkX4Faiduq"} {"name":"Arbalète","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.lt9VC7PkX4Faiduq"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_arbalete.webp","_id":"lt9VC7PkX4Faiduq","system":{"description":"<p>Utilisation de tous les types darbalètes.</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"tir","xp":0,"defaut_carac":"tir","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890264,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Javelot","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"lancer","xp":0,"description":"<p>Utilisation de la lance courte ou de la javeline en lancer.</p>\n<p>&nbsp;</p>","defaut_carac":"lancer"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_javelot.webp","_id":"neuzZG2C5C0IJ1yk"} {"name":"Javelot","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.neuzZG2C5C0IJ1yk"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_javelot.webp","_id":"neuzZG2C5C0IJ1yk","system":{"description":"<p>Utilisation de la lance courte ou de la javeline en lancer.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"lancer","xp":0,"defaut_carac":"lancer","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890264,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Voie d'Oniros","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"draconic","xp":0,"description":"<p>Magie sappliquant au monde inanimé.</p>\n<p>&nbsp;</p>","defaut_carac":"reve"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp","_id":"nnR2UHelUaF8dxYn"} {"name":"Voie d'Oniros","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.nnR2UHelUaF8dxYn"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp","_id":"nnR2UHelUaF8dxYn","system":{"description":"<p>Magie sappliquant au monde inanimé.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"draconic","xp":0,"defaut_carac":"reve","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890265,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Esquive","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Groupées en une seule jusquau niveau zéro, ces compétences sont les principes de base du combat de mêlée. Corps à&nbsp;corps permet de se battre sans armes ; Es-quive permet desquiver toutes les sortes&nbsp;de coup ; Dague de mêlée permet lutilisation de la dague au contact.</p>\n<p>&nbsp;</p>","defaut_carac":"derobee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","_id":"oFje22fZF1FaCQhN"} {"name":"Esquive","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.oFje22fZF1FaCQhN"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp","_id":"oFje22fZF1FaCQhN","system":{"description":"<p>Groupées en une seule jusquau niveau zéro, ces compétences sont les principes de base du combat de mêlée. Corps à&nbsp;corps permet de se battre sans armes ; Es-quive permet desquiver toutes les sortes&nbsp;de coup ; Dague de mêlée permet lutilisation de la dague au contact.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"derobee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890265,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Survie en Cité","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Se sentir à son aise dans un milieu urbain, dans une foule. Savoir sorienter intuitivement dans le dédale dune cité inconnue, et en déceler les dangers : coupeurs de bourse, escrocs, tout autant que patrouilles de gardes. Savoir à qui sadresser.</p>\n<p>&nbsp;</p>","defaut_carac":"derobee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_cite.webp","_id":"oHnSnCw1RAW5t15S"} {"name":"Survie en Cité","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.oHnSnCw1RAW5t15S"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_cite.webp","_id":"oHnSnCw1RAW5t15S","system":{"description":"<p>Se sentir à son aise dans un milieu urbain, dans une foule. Savoir sorienter intuitivement dans le dédale dune cité inconnue, et en déceler les dangers : coupeurs de bourse, escrocs, tout autant que patrouilles de gardes. Savoir à qui sadresser.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"derobee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890265,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Jonglerie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"specialisee","xp":0,"description":"<p>Balles, quilles, couteaux, torches enflammées : lart traditionnel du jongleur.</p>\n<p>&nbsp;</p>","defaut_carac":"dexterite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_jonglerie.webp","_id":"owCW3nZDvlJy1kCT"} {"name":"Jonglerie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.owCW3nZDvlJy1kCT"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_jonglerie.webp","_id":"owCW3nZDvlJy1kCT","system":{"description":"<p>Balles, quilles, couteaux, torches enflammées : lart traditionnel du jongleur.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"specialisee","xp":0,"defaut_carac":"dexterite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890265,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Natation","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"specialisee","xp":0,"description":"<p>Nager, plonger.</p>\n<p>&nbsp;</p>","defaut_carac":"force"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_natation.webp","_id":"qBUtHhyjvrg1c34I"} {"name":"Natation","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.qBUtHhyjvrg1c34I"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_natation.webp","_id":"qBUtHhyjvrg1c34I","system":{"description":"<p>Nager, plonger.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"specialisee","xp":0,"defaut_carac":"force","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890265,"modifiedTime":1671048297539,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Ecriture","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"connaissance","xp":0,"description":"<p>Lire et &eacute;crire. Savoir composer un texte, un po&egrave;me. Connaissance g&eacute;n&eacute;rale des langues anciennes.</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp","_id":"qmIpUeedvjC8nGF1"} {"name":"Ecriture","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.qmIpUeedvjC8nGF1"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp","_id":"qmIpUeedvjC8nGF1","system":{"description":"<p>Lire et &eacute;crire. Savoir composer un texte, un po&egrave;me. Connaissance g&eacute;n&eacute;rale des langues anciennes.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"connaissance","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297540,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Fléau","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Utilisation de tous les types de fléaux, pour attaquer.</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_fleau.webp","_id":"r79VAGS1fRUm4oAd"} {"name":"Fléau","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.r79VAGS1fRUm4oAd"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_fleau.webp","_id":"r79VAGS1fRUm4oAd","system":{"description":"<p>Utilisation de tous les types de fléaux, pour attaquer.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297540,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Armes d'hast","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Utilisation de toutes les piques, vouges, hallebardes, toujours maniées à deux mains, pour attaquer.</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_armes_hast.webp","_id":"rwsHwIDszSIPBkrO"} {"name":"Armes d'hast","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.rwsHwIDszSIPBkrO"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_armes_hast.webp","_id":"rwsHwIDszSIPBkrO","system":{"description":"<p>Utilisation de toutes les piques, vouges, hallebardes, toujours maniées à deux mains, pour attaquer.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297540,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Arc","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"tir","xp":0,"description":"<p>Utilisation de tous les types darcs.</p>\n<p>&nbsp;</p>","defaut_carac":"tir"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_arc.webp","_id":"tVbFkKSN4n0RSrFU"} {"name":"Arc","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.tVbFkKSN4n0RSrFU"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_arc.webp","_id":"tVbFkKSN4n0RSrFU","system":{"description":"<p>Utilisation de tous les types darcs.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"tir","xp":0,"defaut_carac":"tir","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297540,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Dague de jet","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"lancer","xp":0,"description":"<p>Utilisation de la dague en lancer.</p>","defaut_carac":"lancer"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dague_jet.webp","_id":"thJy5AN0qePmfpJu"} {"name":"Dague de jet","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.thJy5AN0qePmfpJu"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_dague_jet.webp","_id":"thJy5AN0qePmfpJu","system":{"description":"<p>Utilisation de la dague en lancer.</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"lancer","xp":0,"defaut_carac":"lancer","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297540,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Bricolage","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-4,"base":-4,"categorie":"generale","xp":0,"description":"<p>Lart dêtre inventif avec ses doigts, pour de&nbsp;petits aménagements ou réparations. Ne&nbsp;peut en aucun cas se substituer aux compétences dartisanat, Charpenterie, Maçonnerie, etc. Bricolage est utilisé quand lusage&nbsp;de ces compétences nest pas pertinent.</p>\n<p>&nbsp;</p>","defaut_carac":"dexterite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_bricolage.webp","_id":"tvIGIPaEJZBaySil"} {"name":"Bricolage","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.tvIGIPaEJZBaySil"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_bricolage.webp","_id":"tvIGIPaEJZBaySil","system":{"description":"<p>Lart dêtre inventif avec ses doigts, pour de&nbsp;petits aménagements ou réparations. Ne&nbsp;peut en aucun cas se substituer aux compétences dartisanat, Charpenterie, Maçonnerie, etc. Bricolage est utilisé quand lusage&nbsp;de ces compétences nest pas pertinent.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-4,"default_diffLibre":0,"base":-4,"categorie":"generale","xp":0,"defaut_carac":"dexterite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297540,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Voie de Narcos","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"draconic","xp":0,"description":"<p>Magie denchantement.</p>","defaut_carac":"reve"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","_id":"u1Peok1EYkBcVsmN"} {"name":"Voie de Narcos","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.u1Peok1EYkBcVsmN"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_narcos.webp","_id":"u1Peok1EYkBcVsmN","system":{"description":"<p>Magie denchantement.</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"draconic","xp":0,"defaut_carac":"reve","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297540,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Survie en Glaces","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_glace.webp","_id":"uGPqmorAYxv1jboC"} {"name":"Survie en Glaces","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.uGPqmorAYxv1jboC"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_glace.webp","_id":"uGPqmorAYxv1jboC","system":{"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297540,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Survie en Extérieur","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Se sentir à son aise dans la nature, hors de toute civilisation, sorienter. Construireun abri, allumer un feu en mauvaisesconditions, trouver de leau, pêcher, savoirExemplaire pour dépecer un gibier et laccommoder sur un feu de braise. Quand un milieu particulier devient déterminant, utiliser à la place une des 6 survies spécifiques.</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_exterieur.webp","_id":"ue5iDSm2f4efQDWO"} {"name":"Survie en Extérieur","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.ue5iDSm2f4efQDWO"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_exterieur.webp","_id":"ue5iDSm2f4efQDWO","system":{"description":"<p>Se sentir à son aise dans la nature, hors de toute civilisation, sorienter. Construireun abri, allumer un feu en mauvaisesconditions, trouver de leau, pêcher, savoirExemplaire pour dépecer un gibier et laccommoder sur un feu de braise. Quand un milieu particulier devient déterminant, utiliser à la place une des 6 survies spécifiques.</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297540,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Survie en Désert","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_desert.webp","_id":"vDOAyWc2YnuhNnFF"} {"name":"Survie en Désert","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.vDOAyWc2YnuhNnFF"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_survie_desert.webp","_id":"vDOAyWc2YnuhNnFF","system":{"description":"<p>Par exemple pister un gibier en forêt demande lusage de Survie en forêt, trouver une grotte pour sabriter en montagne demande Survie en montagne. Survie en extérieur tient lieu de survie spécifique pour les plaines et collines non boisées.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297540,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Fouet","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"lancer","xp":0,"description":"<p>Utilisation du fouet.</p>","defaut_carac":"lancer"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_fouet.webp","_id":"vIQVQxUeiw36hztI"} {"name":"Fouet","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.vIQVQxUeiw36hztI"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_fouet.webp","_id":"vIQVQxUeiw36hztI","system":{"description":"<p>Utilisation du fouet.</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"lancer","xp":0,"defaut_carac":"lancer","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297541,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Travestissement","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Lart de se déguiser, de se grimer, de se rendre méconnaissable.</p>\n<p>&nbsp;</p>","defaut_carac":"apparence"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_travestissement.webp","_id":"w9QubIHdWEUorges"} {"name":"Travestissement","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.w9QubIHdWEUorges"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_travestissement.webp","_id":"w9QubIHdWEUorges","system":{"description":"<p>Lart de se déguiser, de se grimer, de se rendre méconnaissable.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"apparence","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890266,"modifiedTime":1671048297541,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Hache à 1 main","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Ces deux compétences permettent lutilisation des hachettes, cognées et haches de bataille, pour attaquer.</p>\n<p>&nbsp;</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hache_a_1_main.webp","_id":"wEfuLImdNX4BSXVi"} {"name":"Hache à 1 main","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.wEfuLImdNX4BSXVi"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_hache_a_1_main.webp","_id":"wEfuLImdNX4BSXVi","system":{"description":"<p>Ces deux compétences permettent lutilisation des hachettes, cognées et haches de bataille, pour attaquer.</p>\n<p>&nbsp;</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890267,"modifiedTime":1671048297541,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Musique","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Solfège et règles musicales, jeu dun instrument. Musique donne droit à la connaissance dun instrument de musique, un seul, à spécifier.</p>\n<p>&nbsp;</p>","defaut_carac":"ouie"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_musique.webp","_id":"wefdYe0kvWKioPmk"} {"name":"Musique","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.wefdYe0kvWKioPmk"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_musique.webp","_id":"wefdYe0kvWKioPmk","system":{"description":"<p>Solfège et règles musicales, jeu dun instrument. Musique donne droit à la connaissance dun instrument de musique, un seul, à spécifier.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"ouie","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890267,"modifiedTime":1671048297541,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Commerce","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-8,"base":-8,"categorie":"particuliere","xp":0,"description":"<p>Évaluer le prix dune marchandise, la valeur dune monnaie locale. Savoir</p>\n<p>jusquoù lon peut marchander (lequel&nbsp;marchandage doit être fait en jeu de rôle</p>\n<p>par le joueur lui-même).</p>\n<p>&nbsp;</p>","defaut_carac":"intellect"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp","_id":"zO7Av9hJ2vdJiPgI"} {"name":"Commerce","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.zO7Av9hJ2vdJiPgI"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp","_id":"zO7Av9hJ2vdJiPgI","system":{"description":"<p>Évaluer le prix dune marchandise, la valeur dune monnaie locale. Savoir</p>\n<p>jusquoù lon peut marchander (lequel&nbsp;marchandage doit être fait en jeu de rôle</p>\n<p>par le joueur lui-même).</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-8,"default_diffLibre":0,"base":-8,"categorie":"particuliere","xp":0,"defaut_carac":"intellect","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890267,"modifiedTime":1671048297541,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Lance","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-6,"base":-6,"categorie":"melee","xp":0,"description":"<p>Utilisation en mêlée de la lance courte et de la javeline, pour attaquer, voire parer. La lance nest toujours quà une main.</p>\n<p>&nbsp;</p>","defaut_carac":"melee"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_lance.webp","_id":"zPTXua2Kq6TeBTTZ"} {"name":"Lance","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.zPTXua2Kq6TeBTTZ"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_lance.webp","_id":"zPTXua2Kq6TeBTTZ","system":{"description":"<p>Utilisation en mêlée de la lance courte et de la javeline, pour attaquer, voire parer. La lance nest toujours quà une main.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-6,"default_diffLibre":0,"base":-6,"categorie":"melee","xp":0,"defaut_carac":"melee","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890267,"modifiedTime":1671048297541,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}
{"name":"Acrobatie","permission":{"default":0,"Q4cUvqxCxMoTJXDL":3},"type":"competence","data":{"niveau":-11,"base":-11,"categorie":"specialisee","xp":0,"description":"<p>Pirouettes, sauts périlleux, art du funambule, et dune manière générale, toutes les performances dagilité spécialisées.</p>\n<p>&nbsp;</p>","defaut_carac":"agilite"},"flags":{},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_acrobatie.webp","_id":"zyNYa3hYtrOcF2jA"} {"name":"Acrobatie","type":"competence","flags":{"core":{"sourceId":"Compendium.foundryvtt-reve-de-dragon.competences.zyNYa3hYtrOcF2jA"}},"img":"systems/foundryvtt-reve-de-dragon/icons/competence_acrobatie.webp","_id":"zyNYa3hYtrOcF2jA","system":{"description":"<p>Pirouettes, sauts périlleux, art du funambule, et dune manière générale, toutes les performances dagilité spécialisées.</p>\n<p>&nbsp;</p>","descriptionmj":"","niveau":-11,"default_diffLibre":0,"base":-11,"categorie":"specialisee","xp":0,"defaut_carac":"agilite","niveau_archetype":0,"xp_sort":0},"ownership":{"default":0,"Q4cUvqxCxMoTJXDL":3},"effects":[],"folder":null,"sort":0,"_stats":{"systemId":"foundryvtt-reve-de-dragon","systemVersion":"10.3.13","coreVersion":"10.291","createdTime":1671047890267,"modifiedTime":1671048297541,"lastModifiedBy":"Hp9ImM4o9YRTSdfu"}}

Some files were not shown because too many files have changed in this diff Show More