forked from public/foundryvtt-reve-de-dragon
Compare commits
156 Commits
foundryvtt
...
foundryvtt
Author | SHA1 | Date | |
---|---|---|---|
6de34178b3 | |||
0c90fba346 | |||
f43b7ac651 | |||
ac436bbb25 | |||
9093eadb23 | |||
5821fc611f | |||
381242c8d0 | |||
3ca33e85b7 | |||
01399e922a | |||
c6afb8d445 | |||
4d68318d85 | |||
7811eae728 | |||
2e74ccd1fe | |||
f98ece4ffd | |||
ed068a8ddd | |||
c938778267 | |||
9056514951 | |||
1047720c24 | |||
43bcf1c336 | |||
14d4638e56 | |||
c761aeceb3 | |||
1759e6d1c3 | |||
ecb47addba | |||
b18f93fbfb | |||
19bfee7ea5 | |||
93e44bb982 | |||
12df910b3a | |||
2a3989ac2e | |||
ab884713f6 | |||
940237852b | |||
78ee23da96 | |||
862a267683 | |||
2373acc295 | |||
249d171511 | |||
018b6a32dd | |||
44ec511aa6 | |||
ff44de3b3c | |||
8101b905d8 | |||
27dd89024e | |||
69a653d1e5 | |||
bea4124388 | |||
e5bb2e9afc | |||
1d3ae9bb1a | |||
d4be2957a3 | |||
6c9d03be92 | |||
5a50917730 | |||
d285e866be | |||
ece9ab6f64 | |||
038e922f0f | |||
728c5f2f8e | |||
e6592f8333 | |||
42567e7ca0 | |||
9d1fe6d8fd | |||
f5bd0f32f4 | |||
fad29f9652 | |||
9d51631d5c | |||
d1b73e7658 | |||
54158ee10d | |||
e089bdf9c8 | |||
41ab593059 | |||
42ad4c5b26 | |||
85f8a716d4 | |||
47f305d865 | |||
407b4f82d9 | |||
c950f568fd | |||
0ed90f6177 | |||
b74fc27079 | |||
a65d4511c5 | |||
e61417c44e | |||
8ca725bd38 | |||
441a5965c7 | |||
f08c8f93da | |||
d28362bf14 | |||
e506382d18 | |||
c1cecc76b3 | |||
f2a3e1db45 | |||
b69359a47d | |||
fe6c2e2ff2 | |||
9bd13a6021 | |||
a29630f9a2 | |||
c7fd9f7596 | |||
7b18fd25c3 | |||
5c256e2c49 | |||
1c475348d5 | |||
de5d32f88f | |||
76a02d60ca | |||
724c556b9e | |||
7dfba94a11 | |||
928c7bbcfe | |||
222a06a978 | |||
b4edaf8584 | |||
3c062afd56 | |||
6de4fff403 | |||
3543f081b2 | |||
56f14e12a2 | |||
e226af5ac5 | |||
d8be37a2ec | |||
ba2d9de7b6 | |||
6b8fb3267a | |||
05d6f64a31 | |||
c0570e58b4 | |||
8389d578bc | |||
f05ef79b97 | |||
d2a8bfae4f | |||
d54834fa71 | |||
c898bf5212 | |||
a118dc7334 | |||
46401e5d63 | |||
7eb1d9f838 | |||
1d8f4ebb88 | |||
145a92f462 | |||
5148d02314 | |||
000c89b11a | |||
5d4a18aac5 | |||
34b5df637f | |||
22572ca98c | |||
a6a1c1009e | |||
288cf9162c | |||
4b1381e535 | |||
78336a3f45 | |||
3001ae44de | |||
a43ceb3188 | |||
9e95a44efd | |||
179ea0c85b | |||
3821b5bea1 | |||
2739c650d9 | |||
b101d58bee | |||
0e3d721fc7 | |||
e1e45a83be | |||
3b14e54829 | |||
615a3f1315 | |||
ca72d088cc | |||
ac89b948ca | |||
f22c4d2ec8 | |||
ffd80394d3 | |||
0959d1b18e | |||
24e58abfcc | |||
7d292c009d | |||
4bf075786c | |||
a2a04ade4c | |||
2db6895c76 | |||
e46f35ef92 | |||
9e050d3e12 | |||
81492f2857 | |||
959e751e48 | |||
b6a124b57d | |||
db2ca945a8 | |||
667d764db1 | |||
4273f5f48f | |||
6c4a8eb70f | |||
eb029e8d66 | |||
9ee14b3b56 | |||
3203fae111 | |||
755301275b | |||
f6d5dc9d7c | |||
5e9b47af1f |
4
.gitignore
vendored
4
.gitignore
vendored
@@ -8,3 +8,7 @@ todo.md
|
|||||||
/jsconfig.json
|
/jsconfig.json
|
||||||
/package.json
|
/package.json
|
||||||
/package-lock.json
|
/package-lock.json
|
||||||
|
/packs/*/
|
||||||
|
/packs/*/CURRENT
|
||||||
|
/packs/*/LOG
|
||||||
|
/packs/*/LOCK
|
||||||
|
378
changelog.md
378
changelog.md
@@ -1,266 +1,164 @@
|
|||||||
---
|
|
||||||
|
|
||||||
# v11.0
|
# v11.0
|
||||||
|
## v11.1.5 - Werther de Zloth l'Onirique
|
||||||
|
- Fixes:
|
||||||
|
- la demande de défense ne marchait plus
|
||||||
|
- la tête réserve extensible crée bien une case de réserve extensible (à modifier)
|
||||||
|
- le souffle trou noir ajoute bien une case de trou noir
|
||||||
|
- la queue urgence draconique ne se transforme plus en idée fixe s'il y a des sorts en réserve
|
||||||
|
- l'ajout d'une nouvelle queue ne supprime plus l'insomnie
|
||||||
|
- Amélioration des jets de vie
|
||||||
|
- un 1 sur le jet de vie est une réussite même si le personnage est dans le coma
|
||||||
|
- le temps avant le prochain jet est calculé et affiché
|
||||||
|
- un 20 sur le jet de vie signifie la mort immédiate
|
||||||
|
- si on dépasse le S.Const, le personnage est bien indiqué comme mort
|
||||||
|
- pas de jets de vie pour les morts
|
||||||
|
|
||||||
# v10.7 - L'os de Semolosse
|
## v11.1.4 - Werther de Zloth l'Onirique
|
||||||
|
- Ajout du facteur de significative à côté du pourcentage dans le résultat des jets de dés pour rappeler que le pourcentage n'est pas diviasé
|
||||||
|
- Fix: dans les TMRs, les tooltips affichent bien les informations de tous les effets sur la case
|
||||||
|
- Fix: la fatigue et l'éthylisme sont de nouveau pris en compte dans le calcul de l'éthylisme
|
||||||
|
- Fix: Le MJ peut correctement masquer les points de tâche requis
|
||||||
|
- Fix: le jet d'appréciation n'utilise pas la compétence
|
||||||
|
- Fix: la qualité négative n'est pas exotique, elle est juste mauvaise: on n'utilise pas la cuisine pour se retenir de jeter l'assiette
|
||||||
|
- Esthétique: ne pas afficher "+0" pour les ajustements de jets/encaissement
|
||||||
|
|
||||||
## v10.7.14 - l'expérience de Semolosse
|
## v11.1.2 - Les vertèbres de Werther de Zloth
|
||||||
- Affichage des personnages accordés sur les fiches des entités
|
- Fix: les jets d'encaissement fonctionnent de nouveau normalement
|
||||||
- Refonte du journal d'expérience
|
- Macro "Mon personnage" permettant au joueur d'accéder à sa feuille de personnage depuis la barre de macros
|
||||||
- disponible pour les personnages des joueurs
|
|
||||||
- explication "comptable" des changements (dépense ou ajout, changements de niveaux, ...)
|
|
||||||
- tri alphabétique des différentes listes (sorts, recettes, oeuvres, ...)
|
|
||||||
|
|
||||||
## v10.7.13 - l'armure de Semolosse
|
## v11.1.1 - Les fumebols de Werther de Zloth
|
||||||
- Fix: en cas d'armure variable, la détérioration diminue le dé d'armure
|
- Fix: on peut de nouveau afficher les vues détaillées
|
||||||
|
- Fix: on peut ouvrir les sacs et contenants portés par les véhicules et créatures
|
||||||
|
- Fix: cuisiner du gibier prend maintenant bien les proportaions en compte
|
||||||
|
|
||||||
## v10.7.12
|
## v11.1.0 - Les choix de Werther de Zloth
|
||||||
- Fix: si le MJ gère les changements de jours, l'option "sieste" de la fenêtre de repos est prise par défaut si chateau dormant n'est pas passé
|
- Les options suivantes peuvent être désactivées:
|
||||||
|
- La transformation de stress à Château Dormant
|
||||||
|
- La récuperation de chance à Château Dormant
|
||||||
|
- La récupération d'éthylisme
|
||||||
|
- La récupération de rêve (y compris fleurs de rêve et Rêves de Dragon: la rencontre a lieu, mais ne donne pas de rêve)
|
||||||
|
- Le jet de moral de Château Dormant
|
||||||
|
- Séparation des véhicules dans leur propre acteur
|
||||||
|
- Séparation des entités dans leur propre acteur
|
||||||
|
- Séparation des créatures dans leur propre acteur
|
||||||
|
- La fenêtre de signes draconiques ne sélectionne plus tout les haut-rêvants par défaut
|
||||||
|
- Un nouveau personnage a automatiquement son token relié
|
||||||
|
- corrections de bugs
|
||||||
|
- si on n'utilise pas les règles de fatigues, un reflet de rêve pouvait garder le Haut-rêvant dans les TMRs pour toujours
|
||||||
|
- certaines macros ne marchaient pas pour les créatures/entités/véhicules/commerces
|
||||||
|
- en cas de charge, les particulières sont toujours en force (p125)
|
||||||
|
|
||||||
## v10.7.11 - Le Pugilat de Semolosse
|
## v11.0.28 - les fractures de Khrachtchoum
|
||||||
- Fix sur la projection au sol.
|
- La gravité de la blessure est affichée dans le résumé de l'encaissement
|
||||||
|
- Lors du changement d'acteur pendant le round
|
||||||
|
- le message annonçant le joueur dont c'est le tour ne contient plus d'informations de santé
|
||||||
|
- un message avec les informations de santé est envoyé au Gardienn et au propriétaire du token.acteur
|
||||||
|
- le jet de vie est bien fait par le token si besoin
|
||||||
|
- seul les propriétaires peuvent faire les jets de vie
|
||||||
|
- Amélioration de la fenêtre de jets
|
||||||
|
- le type de dégâts pour les attaques est toujours affiché
|
||||||
|
- le moral est indiqué avant l'icone d'appel au moral
|
||||||
|
|
||||||
## v10.7.10 - Le Pugilat de Semolosse
|
## v11.0.27 - Khrachtchoum le méticuleux
|
||||||
- Gestion de l'empoignade
|
- le tooltip dans les TMR reste visible si on ne bouge pas la souris
|
||||||
- Corrections sur l'initiative
|
- le surencombrement n'affecte QUE les actions physiques
|
||||||
- Correction sur l'equipement des vêtements et bijoux
|
- on peut de nouveau fabriquer une potion depuis la fenêtre d'édition de l'herbe
|
||||||
|
- si les TMR sont minimisées alors qu'une action est requise, elles sont bien réaffichées lorsque l'action est faite
|
||||||
|
|
||||||
## v10.7.9 - Le Pugilat de Semolosse
|
## v11.0.26 - le crépuscule de Khrachtchoum
|
||||||
|
- gestion correcte des TMRs
|
||||||
|
- les TMRs ne sont jamais minimisées (par le système) quand le haut-rêvant est en demi-rêve
|
||||||
|
- lorsqu'une fenêtre liée aux demi-rêve est affichée, cliquer sur les TMRs n'a pas d'effet
|
||||||
|
- les lancers de sorts et lectures de signes sont affichées en premier plan
|
||||||
|
- Les effets qui ouvrent une fenêtre sont bien affichés en premier plan
|
||||||
|
- en cas de rencontre suivie de maîtrises/conquêtes, les fenêtres s'enchaînent
|
||||||
|
- Le drag&drop vers la barre de macro est corrigé
|
||||||
|
- pour les créatures, possibilités d'avoir les attaques ou autres compétences
|
||||||
|
- pour les personnages, les macros sont créées:
|
||||||
|
- pour les compétences
|
||||||
|
- pour le corps à corps, trois macros sont créées: compétence, pugilat, empoignade
|
||||||
|
- pour les armes
|
||||||
|
- deux macros sont créées pour les armes à 1/2 mains
|
||||||
|
- deux macros sont créées pour les armes de mélée et lancer
|
||||||
|
- 4 macros si votre arbalête se lance, tire, et se manie à 1 ou 2 mains...
|
||||||
|
- les jets de compétences d'attaque des créatures fonctionnent de nouveau
|
||||||
|
|
||||||
- Gestion assistée de l'empoignade
|
## v11.0.25 - la vision du rêve de Khrachtchoum
|
||||||
1. On selectionne sa cible (ie le token qui va être empoigné)
|
- Les TMRs restent affichées tant que le Haut-rêvant est en demi-rêve
|
||||||
2. On lance une attaque avec l'"arme" _Empoignade_
|
|
||||||
3. A ce stade, si la victime a une arme, on rappelle le point de règle d'engagement
|
|
||||||
(page 134), et un bouton permet de confirmer l'empoignade
|
|
||||||
4. L'empoigneur fait son jet
|
|
||||||
5. Si réussite, l'empoigné peut se défendre, avec gestion du premier round d'engagement
|
|
||||||
(ie Esquive autorisée ou pas)
|
|
||||||
- 4 bis. et 5 bis. L'empoigné, à son tour, peut tenter de se libérer, toujours en cliquant sur l'action "Empoignade"
|
|
||||||
6. Selon le résultat, incrément/décrément des points d'emp
|
|
||||||
7. Retour en 4., ou si 2 points d'Emp, alors 8.
|
|
||||||
8. Affichage des options disponibles pour l'empoigneur : perte d'endurance, projection au
|
|
||||||
sol ou entrainer au sol. Ces 3 options sont gérées automatiquement ensuite, selon le
|
|
||||||
bouton cliqué par l'empoigneur.
|
|
||||||
|
|
||||||
Les empoignades sont des "items" supprimées à la fin d'un combat, qui peuvent aussi être
|
## v11.0.24 - les couleurs de Khrachtchoum
|
||||||
gérés par le MJ au cas ou. Hors combat, penser à les supprimer (ou commencer et
|
- nouvelle carte des TMRs
|
||||||
arrêter un combat).
|
|
||||||
|
|
||||||
## v10.7.7 - Les bobos de Sémolosse
|
## v11.0.23 - la lumière de Khrachtchoum
|
||||||
- Mise à jour du texte de l'heure pour les joueurs
|
- ajustement automatique de la luminosité selon l'heure pour les scènes:
|
||||||
- L'horloge n'empêche plus de sélectionner les tokens dessous
|
- avec une vision des tokens (sinon: ce n'est pas une scène de carte pour tokens)
|
||||||
- _Lecture & Détection d'Aura_ sous Hypnos sont des rituels
|
- avec illumination globale (correspondant à une illumination extérieure)
|
||||||
- _Lire les étoiles_ pour les joueurs de nouveau fonctionnel
|
- quand lampe "allumée" dans la fenêtre du calendrier
|
||||||
- Ajout de logs pour comprendre un cas d'échec des achatVente
|
|
||||||
|
|
||||||
## v10.7.6 - L'origine des maux de Sémolosse
|
## v11.0.22 - les automatismes de Khrachtchoum le Problémeux
|
||||||
- Calendrier
|
- Macro pour attaquer avec les compétences de créatures
|
||||||
- fix du ré-affichage de l'horloge qui ne marchait pas pour les joueurs
|
|
||||||
- l'horloge ne se ferme plus sur Escape
|
|
||||||
- amélioration d'affichage
|
|
||||||
- couleurs jour/nuit plus marquées
|
|
||||||
- Divers
|
|
||||||
- correction de l'affichage de quantités diminuées d'herbes dans les contenants ouvert
|
|
||||||
- ajout d'un bouton pour diminuer les quantités dans l'équipement (si quantité > 1)
|
|
||||||
- ajout de la signature de l'acteur sur les blessures qu'il a causées
|
|
||||||
|
|
||||||
- Magie
|
## v11.0.20
|
||||||
- correction des bonus de cases pour les sorts en Fleuve
|
- Macro pour attaquer avec les armes des personnages
|
||||||
|
|
||||||
## v10.7.5 - La montre-gousset de Sémolosse
|
## v11.0.17
|
||||||
- Amélioration de la fenêtre calendrier
|
- Fix: les actions de commerce ne s'appliquait pas bien aux personnages des tokens non liés
|
||||||
* plus compacte
|
|
||||||
* horloge analogique (optionnelle)
|
|
||||||
* minimizable (juste la barre de titre)
|
|
||||||
* normalement compatible pop-out
|
|
||||||
|
|
||||||
## v10.7.4 - Les ligatures de Sémolosse
|
## v11.0.15 - L'apprentissage de Khrachtchoum
|
||||||
- Corrections diverses
|
- Fix: l'expérience ne s'appliquait plus sur certaines réussites particulières (régression depuis la 11.0.7)
|
||||||
- Correction des boutons pour déclencher un sort en réserve avec réserve en sécurité ou réserve extensible
|
|
||||||
- le lien pour les jets de vie suite à une blessure critique est remplacé par un bouton
|
|
||||||
- déplacement des tâches et boutons de chirurgie dans l'onglet savoirs et tâches
|
|
||||||
- correction de l'affichage des bonus de cases des sorts
|
|
||||||
- corrections des queues non-refoulables dans le compendium
|
|
||||||
|
|
||||||
## v10.7.3 - Les tisanes de Sémolosse
|
## v11.0.14 - Les pincettes de Khrachtchoum le Problémeux
|
||||||
- Soins
|
- Correction du calcul de la place restante lors de l'ajout dans un conteneur
|
||||||
- on peut de nouveau boire une potion de soins enchantée
|
|
||||||
- les potions non enchantées donnent de nouveau un bonus au prochain jet de récupération
|
|
||||||
- Une fois les soins complets faits, le bonus aux soins complets fournis par les premiers soins est masqué
|
|
||||||
|
|
||||||
- Horloge
|
## v11.0.13 - La multiplication de l'eau de Khrachtchoum le Problémeux
|
||||||
- A l'heure de Couronne pile, les aiguilles des heures et des minutes pointent sur couronne (comme une montre) au lieu d'avoir l'aiguille des heures 15° à gauche
|
- Correction de la vente depuis un commerce ayant des quantités illimitées
|
||||||
|
|
||||||
## v10.7.2 - les maux de dents de Semolosse
|
## v11.0.12 - Les poids de la mesure de Khrachtchoum le Problémeux
|
||||||
- correction des récupérations de blessures
|
- Correction des malus de surencombrement
|
||||||
- la fin de château dormant se passe normalement
|
- Le malus armure est correctement affiché dans l'onglet des caractéristiques
|
||||||
|
- Correction d'orthographe et amélioration des messages des oeuvres d'art
|
||||||
|
|
||||||
## v10.7.1 - L'os de Semolosse
|
## v11.0.11 - Les bleus de Khrachtchoum le Problémeux
|
||||||
- Fix rapide sur les jets de carac qui n'étaient plus possibles
|
- si le gardien configure le sommeil, les joueurs sont notifiés que chateau dormant vient de passer
|
||||||
|
- possibilité de créer des armes et des compétences de créatures non-mortelles.
|
||||||
|
|
||||||
## v10.7.0 - L'os de Semolosse
|
## v11.0.10 - Les Songes de Khrachtchoum le Problémeux
|
||||||
- gestion des blessures en items
|
- on peut de nouveau se déplacer dans les TMRs d'un clic sur la case à atteindre
|
||||||
- soins du token ciblé par menu contextuel (comme le combat)
|
- Lire un livre depuis l'inventaire permet de nouveau de faire un jet de la tâche
|
||||||
- automatisation des soins et de l'affichage de l'avancement des soins
|
créée au lieu de créer toujours une nouvelle tâche
|
||||||
- support des changements d'opérants
|
- La sélection des TMR pour la création de signes draconiques ne cause plus d'erreurs
|
||||||
|
- la récupération d'endurance en cas d'insomnie est limitée à la moitié
|
||||||
|
- le résultat du sommeil lors d'un rêve de dragon à la première heure s'affiche normalement
|
||||||
|
- lorsque le gardien gère la durée des nuits, en cas de rêve de dragon,
|
||||||
|
les heures dormies sont déduites des heures restant à dormir
|
||||||
|
|
||||||
---
|
## v11.0.9 - Les Souvenirs de Khrachtchoum le Problémeux
|
||||||
# v10.6 - Les recherches de Pralinor le Goûteux
|
- mode de saisie de l'archétype en vue détaillée
|
||||||
|
- création une nouvelle incarnation depuis l'archétype
|
||||||
|
- réorganisation de la fenêtre de sélection des règles optionnelles
|
||||||
|
- correction de l'affichage du type dans les fenêtres d'objets
|
||||||
|
|
||||||
## v10.6.25 - Fix sur l'astrologie
|
## v11.0.8 - la poigne de Sémolosse
|
||||||
|
- lien vers le changelog
|
||||||
|
- organisation des compendiums du système
|
||||||
|
- correction de l'empoignade
|
||||||
|
- les items d'empoignade sont ajoutés par le MJ quand nécessaire
|
||||||
|
- seul le joueur propriétaire du personnage peut effectuer ses choix et actions d'empoignade
|
||||||
|
- les caractéristiques du défenseur sont utilisées pour la défense
|
||||||
|
- la difficulté d'attaque est imposée au défenseur
|
||||||
|
- les attaques particulières sont en finesse (p133)
|
||||||
|
- on peut entraîner au sol dès 2 points d'empoignade
|
||||||
|
- les actions liée à l'immobilisation sont proposées en fin de round
|
||||||
|
|
||||||
## v10.6.22 - le nuage de lait dans le thé de Pralinor
|
# v11.0.7
|
||||||
- Amélioration de l'affichage de l'horloge
|
|
||||||
- Fix: affichage des points de guérison dans les potions
|
|
||||||
|
|
||||||
## v10.6.21 - La théière de Pralinor
|
- les créatures ont maintenant le droit d'avoir des compétences de tir, lancer, mêlée, armes naturelles, parade.
|
||||||
- Astrologie
|
- les créatures armées utilisent la bonne phase d'initiative
|
||||||
- le thème astral est directement dans la fenêtre d'astrologie
|
- correction des possessions
|
||||||
- la roue des heures sert d'horloge
|
- la difficulté de la défense est imposée par l'attaque
|
||||||
- sélectionner un personnage ajuste le thème astral pour son heure de naissance
|
- une attaque particulière de possession est en finesse
|
||||||
- sélectionner le nombre astral d'un jour ajuste le thème astral
|
- le rêve actuel des personnages est bien utilisé
|
||||||
|
- correction des achats par le MJ sans acteur sélectionné
|
||||||
|
|
||||||
- Fix: les PNJs peuvent de nouveau dormir
|
Cf branche v10 pour l'historique des versions 10
|
||||||
|
|
||||||
## v10.6.20 - Les Oracles de Pralinor: vous mangerez à Couronne
|
|
||||||
- Ajout de la fenêtre pour effectuer un thème astral
|
|
||||||
|
|
||||||
## v10.6.19 - La cerise de Pralinor
|
|
||||||
- les joueurs peuvent chercher dans les commerces avec un droit limité/observateur
|
|
||||||
- simplifications des fins de tours et nombre d'utilisations
|
|
||||||
- ajout du _Haubert d'Oniros_ dans le compendium de sorts
|
|
||||||
|
|
||||||
## v10.6.17 - Les désordres de Pralinor
|
|
||||||
- le contenu des casseroles et autres contenants est maintenant trié dans l'ordre alphabétique
|
|
||||||
- les objets dupliqués du compendium d'équipement sont de nouveaux uniques
|
|
||||||
|
|
||||||
## v0.6.16 - Le pardon de Pralinor
|
|
||||||
- Ajout d'un commerce _Liste d'équipement_ dans les archétypes de PNJs
|
|
||||||
- Séparations d'équipements groupés et corrections de quelques objets & herbes
|
|
||||||
- On peut éditer les armes stockées dans un commerce
|
|
||||||
|
|
||||||
## v10.6.15 - les digestifs de Pralinor
|
|
||||||
- amélioration des messages de sommeil (nombre d'heure dormies, uniquement les
|
|
||||||
récupérations de rêve en dessous du seuil, affichage de la récupération d'endurance
|
|
||||||
qui avait disparu, meilleur message sur le jet de moral)
|
|
||||||
- les insomnies ne durent bien que 12h draconique à partir du prochain
|
|
||||||
Chateau Dormant (elles pouvaient durer 3 nuits suite à une erreur).
|
|
||||||
- la recherche dans l'équipement affiche correctement les conteneurs dans lesquels les
|
|
||||||
objets trouvés sont rangés
|
|
||||||
|
|
||||||
## v10.6.14 - la digestion de Pralinor
|
|
||||||
- Chateau dormant
|
|
||||||
- la situation du jet de moral peut être choisie lorsque l'on dort
|
|
||||||
- les queues de dragon "insomnie" empêchent de dormir, et de rêver
|
|
||||||
- ajout d'une option pour meilleure gestion de Chateau Dormant par le MJ
|
|
||||||
- avec cette option, à la fin Chateau Dormant, une fenêtre permet au gardien de
|
|
||||||
positionner pour chaque joueur:
|
|
||||||
- le stress de la journée
|
|
||||||
- les heures de sommeil
|
|
||||||
- la situation du jet de moral (neutre/heureux/malheureux)
|
|
||||||
|
|
||||||
- l'affichage des heures Chateau Dormant et Poisson Acrobate est correct
|
|
||||||
- le jet de moral en situation neutre fait maintenant retourner le moral vers 0, et
|
|
||||||
n'affecte plus un moral à 0.
|
|
||||||
## v10.6.13 - la cave de Pralinor
|
|
||||||
- on peut maintenant chercher dans l'inventaire des commerces
|
|
||||||
- l'inventaire est correctement affiché en entier après suppression de la recherche
|
|
||||||
- le message de chateau dormant reflète correctement un jet de moral neutre qui passe le moral de 0 à +1
|
|
||||||
|
|
||||||
## v10.6.12 - l'index de Pralinor
|
|
||||||
- On peut désormais chercher dans l'inventaire comme dans les compétences
|
|
||||||
|
|
||||||
## v10.6.11 - l'empoisonnement de Pralinor
|
|
||||||
- La récupération est bloquée par les maladies. Pas de récupération de vie ou de blessures possibles sous l'effet d'un poison ou d'une maladie
|
|
||||||
- ajout d'un "poison" pour bloquer la récupération sous Griffe Morbide de Thanatos.
|
|
||||||
Ajout du lien vers l'objet du compendium dans la description MJ,, qui pourra donc
|
|
||||||
ajouter ce "poison" à la victime pour empêcher ses guérisons de vie ou blessure.
|
|
||||||
|
|
||||||
## v10.6.10
|
|
||||||
- Correction de l'édition des description
|
|
||||||
- Amélioration des descriptions d'alchimie:
|
|
||||||
- difficulté calculée automatiquement
|
|
||||||
- Température pour les couleurs
|
|
||||||
- La sustentation n'est plus concaténée dans certains cas (ce qui donnait 2+2=22)
|
|
||||||
|
|
||||||
## v10.6.8 : les bon mots de Pralinor
|
|
||||||
- Dans la fenêtre de _recherche et tirages_, possibilité de chercher sur le nom des objets en plus des autres critères
|
|
||||||
|
|
||||||
## v10.6.7 : les grumelés de Pralinor
|
|
||||||
- les objets peuvent être utilisés depuis la fenêtre d'un conteneur
|
|
||||||
- dans les fenêtres de contenants, le contenu est correctement indenté
|
|
||||||
- la présentation du contenu d'un sac est améliorée
|
|
||||||
- le bouton Nouvel Objet n'est affiché que si on est propriétaire de l'acteur
|
|
||||||
- la fenêtre de vente permet de nouveau de choisir les quantités à vendre
|
|
||||||
|
|
||||||
## v10.6.6
|
|
||||||
- Corrections d'armes rudimentaires
|
|
||||||
- Inversion: Taille puis poids
|
|
||||||
- Suppression d'une ligne de caractéristique vide (causée par la beauté)
|
|
||||||
- Les messages liés aux compétences troncs deviennent des notifications
|
|
||||||
## v10.6.5
|
|
||||||
- Le +dom est de nouveau affiché
|
|
||||||
- L'édition de caractéristiques des créatures fonctionne de nouveau
|
|
||||||
|
|
||||||
## v10.6.4 - La sénilité de Pralinor
|
|
||||||
- Fenêtre _Recherches et tirages_
|
|
||||||
- les résultats de recherches sur plusieurs compendiums sont triés
|
|
||||||
- lors de recherches avec un ou des milieux sélectionnés:
|
|
||||||
- le filtre sur la rareté utilise la rareté dans ces milieux
|
|
||||||
- les tirages se basent sur la fréquence la plus élevées dans ces milieux
|
|
||||||
- les filtres par utilisation prennent les potions en compte
|
|
||||||
- les remèdes ont une catégorie de potion 'Remède' (et correspondent à une utilisation médicale)
|
|
||||||
- ajout d'un filtre d'utilisation 'cuisine'
|
|
||||||
|
|
||||||
|
|
||||||
# Divers
|
|
||||||
- fix du cas où la transformation de 0 points de stress était concaténé, (passage de 29 à 290 avec 0 points transformés)
|
|
||||||
- suppression du compendium de taches courantes, désormais inutile
|
|
||||||
|
|
||||||
## v10.6.3 - le baba-brandevin de Pralinor
|
|
||||||
- les tâches de Soins sont maintenant déplacées à côté des blessures
|
|
||||||
- on peut créer les tâches de soins directement avec un bouton par gravité.
|
|
||||||
|
|
||||||
- le round n'est plus bloqué si un acteur est sonné
|
|
||||||
- un rare cas d'initiative négative pouvait empêcher de faire une initiative (à cause de l'état général)
|
|
||||||
- dans une circonstance inconnue, une rencontre pouvait disparaître lors de la maîtrise. Ajout d'un message pour essayer d'obtenir des détails sur ce cas, et ajout d'une sécurité pour retrouver la rencontre (qui est conservée par la fenêtre de choix d'action).
|
|
||||||
- les objets temporels (queues, souffles, poisons, maladies...) créés avant la gestion temporelle ne pouvaient pas être édités.
|
|
||||||
- les particulières sur les jets de résistance de rêve actuel ne rapportent qu'un point d'expérience (p191)
|
|
||||||
- pour lutter contre l'alcoolisme, les jets d'éthylisme sont considérés comme des jets de résistance, et n'apportent qu'un point d'expérience.
|
|
||||||
## v10.6.2 - Le méli-mélo de Pralinor
|
|
||||||
- Fenêtre _Recherches et tirages_
|
|
||||||
- support de la recherche dans les compendiums choisis
|
|
||||||
- suppression des commandes `/table milieu` et `/tirer milieu` (remplacées par la fenêtre de recherche)
|
|
||||||
- ajout de fréquences à tous les équipements
|
|
||||||
## v10.6.1 - Les recherches de Pralinor
|
|
||||||
- Fenêtre _Recherches et tirages_
|
|
||||||
- Amélioration des filtres de cuisine/utilisation
|
|
||||||
- Ajout de catégories pour les poisons, urtiquants, ...
|
|
||||||
- Bouton "Effacer les filtres" plus clair
|
|
||||||
- Drag&drop depuis la recherche
|
|
||||||
- Reprise du compendium
|
|
||||||
- pour les plantes vénéneuses
|
|
||||||
- pour les plantes venimeuses
|
|
||||||
- ajout de sust pour les champignons et autres plantes comestibles
|
|
||||||
|
|
||||||
- Affichage de l'image du token pour les commerces non liés
|
|
||||||
- Les pièces d'or sont appelées 'Dragon'
|
|
||||||
|
|
||||||
## v10.6.0 - Les recherches de Pralinor le Goûteux
|
|
||||||
- Fenêtre _Recherches et tirages_
|
|
||||||
- ajout de la fenêtre _Recherches et tirages_ avec filtres paramétrables
|
|
||||||
- ouverture de la fenêtre: commande `/tirage` ou macro disponible dans les macros du système
|
|
||||||
- support des équipements, faune & flore (depuis les compendiums configurés par défaut)
|
|
||||||
- nombreux choix à activer
|
|
||||||
- possibilité de montrer les objets correspondant à la sélection
|
|
||||||
- possibilité de faire un tirage parmi ces objets (en prenant en compte la fréquence)
|
|
||||||
|
|
||||||
- Plantes & pèche
|
|
||||||
- séparation des ingrédients et plantes comestibles
|
|
||||||
- retour des poissons dans les compendiums
|
|
||||||
- ajout d'un lien depuis les plantes toxiques/dangereuses vers la maladie/poison correspondante
|
|
||||||
|
|
||||||
- On peut de nouveau ouvrir les conteneurs dans une fenêtre séparée
|
|
||||||
- Les jets de volontés d'éthylisme calculent correctement la difficulté liée au moral (ie: 0 au lieu de -22)
|
|
||||||
- si le journal de chronologie est supprimée, on peut en choisir un autre
|
|
||||||
- la taille du calendrier est ajustée pour éviter une présentation bancale quand le nom du mois est court
|
|
||||||
|
BIN
icons/voyageurs/personnage.webp
Normal file
BIN
icons/voyageurs/personnage.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.1 KiB |
@@ -7,33 +7,30 @@ import { Misc } from "./misc.js";
|
|||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
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 { ReglesOptionnelles } from "./settings/regles-optionnelles.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 { MAINS_DIRECTRICES } from "./actor.js";
|
import { MAINS_DIRECTRICES } from "./actor.js";
|
||||||
import { RdDBaseActorSheet } from "./actor/base-actor-sheet.js";
|
import { RdDBaseActorReveSheet } from "./actor/base-actor-reve-sheet.js";
|
||||||
import { RdDItem } from "./item.js";
|
import { RdDItem } from "./item.js";
|
||||||
import { RdDItemBlessure } from "./item/blessure.js";
|
import { RdDItemBlessure } from "./item/blessure.js";
|
||||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||||
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/**
|
/**
|
||||||
* Extend the basic ActorSheet with some very simple modifications
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
* @extends {ActorSheet}
|
* @extends {ActorSheet}
|
||||||
*/
|
*/
|
||||||
export class RdDActorSheet extends RdDBaseActorSheet {
|
export class RdDActorSheet extends RdDBaseActorReveSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
RdDUtility.initAfficheContenu();
|
return mergeObject(RdDBaseActorReveSheet.defaultOptions, {
|
||||||
return mergeObject(super.defaultOptions, {
|
|
||||||
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: 550,
|
width: 550,
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
|
||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
|
|
||||||
showCompNiveauBase: false,
|
showCompNiveauBase: false,
|
||||||
vueDetaillee: false
|
vueArchetype: false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -55,7 +52,8 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
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),
|
||||||
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
|
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
|
||||||
surEncombrementMessage: this.actor.getMessageSurEncombrement(),
|
surEncombrementMessage: this.actor.isSurenc() ? "Sur-Encombrement!" : "",
|
||||||
|
malusArmure: this.actor.getMalusArmure()
|
||||||
})
|
})
|
||||||
|
|
||||||
this.timerRecherche = undefined;
|
this.timerRecherche = undefined;
|
||||||
@@ -79,9 +77,12 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// toujours avoir une liste d'armes (pour mettre esquive et corps à corps)
|
// toujours avoir une liste d'armes (pour mettre esquive et corps à corps)
|
||||||
formData.combat = duplicate(formData.armes ?? []);
|
const actor = this.actor;
|
||||||
|
formData.combat = duplicate(formData.armes);
|
||||||
RdDItemArme.computeNiveauArmes(formData.combat, formData.competences);
|
RdDItemArme.computeNiveauArmes(formData.combat, formData.competences);
|
||||||
RdDItemArme.ajoutCorpsACorps(formData.combat, formData.competences, formData.system.carac);
|
formData.combat.push(RdDItemArme.mainsNues(actor));
|
||||||
|
formData.combat.push(RdDItemArme.empoignade(actor));
|
||||||
|
|
||||||
formData.esquives = this.actor.getCompetences("Esquive");
|
formData.esquives = this.actor.getCompetences("Esquive");
|
||||||
formData.combat = RdDCombatManager.listActionsArmes(formData.combat, formData.competences, formData.system.carac);
|
formData.combat = RdDCombatManager.listActionsArmes(formData.combat, formData.competences, formData.system.carac);
|
||||||
formData.empoignades = this.actor.getEmpoignades();
|
formData.empoignades = this.actor.getEmpoignades();
|
||||||
@@ -110,20 +111,28 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */ /** @override */
|
/* -------------------------------------------- */
|
||||||
|
/** @override */
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
|
||||||
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.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;
|
||||||
|
|
||||||
this.html.find('.item-action').click(async event => {
|
this.html.find('.sheet-possession-attack').click(async event => {
|
||||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
const poss = RdDSheetUtility.getItem(event, this.actor)
|
||||||
item?.actionPrincipale(this.actor, async () => this.render())
|
this.actor.conjurerPossession(poss)
|
||||||
});
|
})
|
||||||
|
|
||||||
|
this.html.find('.subacteur-label a').click(async event => {
|
||||||
|
let actorId = RdDSheetUtility.getEventItemData(event, 'actor-id');
|
||||||
|
let actor = game.actors.get(actorId);
|
||||||
|
if (actor) {
|
||||||
|
actor.sheet.render(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
this.html.find('.subacteur-delete').click(async event => {
|
this.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");
|
||||||
@@ -153,18 +162,6 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
this.actor.updateCompteurValue("experience", parseInt(event.target.value));
|
this.actor.updateCompteurValue("experience", parseInt(event.target.value));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.encaisser-direct').click(async event => {
|
|
||||||
this.actor.encaisser();
|
|
||||||
})
|
|
||||||
this.html.find('.sheet-possession-attack').click(async event => {
|
|
||||||
const poss = RdDSheetUtility.getItem(event, this.actor)
|
|
||||||
this.actor.conjurerPossession(poss)
|
|
||||||
})
|
|
||||||
this.html.find('.remise-a-neuf').click(async event => {
|
|
||||||
if (game.user.isGM) {
|
|
||||||
this.actor.remiseANeuf();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.html.find('.creer-tache').click(async event => {
|
this.html.find('.creer-tache').click(async event => {
|
||||||
this.createEmptyTache();
|
this.createEmptyTache();
|
||||||
});
|
});
|
||||||
@@ -174,9 +171,7 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
this.html.find('.creer-blessure-legere').click(async event => RdDItemBlessure.createBlessure(this.actor, 2));
|
this.html.find('.creer-blessure-legere').click(async event => RdDItemBlessure.createBlessure(this.actor, 2));
|
||||||
this.html.find('.creer-blessure-grave').click(async event => RdDItemBlessure.createBlessure(this.actor, 4));
|
this.html.find('.creer-blessure-grave').click(async event => RdDItemBlessure.createBlessure(this.actor, 4));
|
||||||
this.html.find('.creer-blessure-critique').click(async event => RdDItemBlessure.createBlessure(this.actor, 6));
|
this.html.find('.creer-blessure-critique').click(async event => RdDItemBlessure.createBlessure(this.actor, 6));
|
||||||
this.html.find('.creer-une-oeuvre').click(async event => {
|
this.html.find('.creer-une-oeuvre').click(async event => this.selectTypeOeuvreToCreate());
|
||||||
this.selectTypeOeuvreToCreate();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.html.find('.blessure-premierssoins-done').change(async event => {
|
this.html.find('.blessure-premierssoins-done').change(async event => {
|
||||||
const blessure = this.getBlessure(event);
|
const blessure = this.getBlessure(event);
|
||||||
@@ -201,11 +196,6 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Roll Carac
|
// Roll Carac
|
||||||
this.html.find('.carac-label a').click(async event => {
|
|
||||||
let caracName = event.currentTarget.attributes.name.value;
|
|
||||||
this.actor.rollCarac(caracName.toLowerCase());
|
|
||||||
});
|
|
||||||
|
|
||||||
this.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');
|
||||||
});
|
});
|
||||||
@@ -214,14 +204,10 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
this.actor.rollAppelChance();
|
this.actor.rollAppelChance();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Roll Skill
|
||||||
this.html.find('[name="jet-astrologie"]').click(async event => {
|
this.html.find('[name="jet-astrologie"]').click(async event => {
|
||||||
this.actor.astrologieNombresAstraux();
|
this.actor.astrologieNombresAstraux();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Roll Skill
|
|
||||||
this.html.find('a.competence-label').click(async event => {
|
|
||||||
this.actor.rollCompetence(RdDSheetUtility.getItemId(event));
|
|
||||||
});
|
|
||||||
this.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));
|
||||||
});
|
});
|
||||||
@@ -246,13 +232,6 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
this.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));
|
||||||
});
|
});
|
||||||
this.html.find('.subacteur-label a').click(async event => {
|
|
||||||
let actorId = RdDSheetUtility.getEventItemData(event, 'actor-id');
|
|
||||||
let actor = game.actors.get(actorId);
|
|
||||||
if (actor) {
|
|
||||||
actor.sheet.render(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Boutons spéciaux MJs
|
// Boutons spéciaux MJs
|
||||||
this.html.find('.forcer-tmr-aleatoire').click(async event => {
|
this.html.find('.forcer-tmr-aleatoire').click(async event => {
|
||||||
@@ -287,35 +266,12 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
ui.notifications.info("Impossible de lancer l'initiative sans être dans un combat.");
|
ui.notifications.info("Impossible de lancer l'initiative sans être dans un combat.");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
// Display TMR, visualisation
|
// Display TMR
|
||||||
this.html.find('.visu-tmr').click(async event => {
|
this.html.find('.visu-tmr').click(async event => { this.actor.displayTMR("visu") })
|
||||||
this.actor.displayTMR("visu");
|
this.html.find('.monte-tmr').click(async event => { this.actor.displayTMR("normal") })
|
||||||
});
|
this.html.find('.monte-tmr-rapide').click(async event => { this.actor.displayTMR("rapide") })
|
||||||
|
|
||||||
// Display TMR, normal
|
this.html.find('.repos').click(async event => { await this.actor.repos() })
|
||||||
this.html.find('.monte-tmr').click(async event => {
|
|
||||||
this.actor.displayTMR("normal");
|
|
||||||
});
|
|
||||||
|
|
||||||
// Display TMR, fast
|
|
||||||
this.html.find('.monte-tmr-rapide').click(async event => {
|
|
||||||
this.actor.displayTMR("rapide");
|
|
||||||
});
|
|
||||||
|
|
||||||
this.html.find('.repos').click(async event => {
|
|
||||||
await this.actor.repos();
|
|
||||||
});
|
|
||||||
this.html.find('.delete-active-effect').click(async event => {
|
|
||||||
if (game.user.isGM) {
|
|
||||||
let effect = this.html.find(event.currentTarget).parents(".active-effect").data('effect');
|
|
||||||
this.actor.removeEffect(effect);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.html.find('.enlever-tous-effets').click(async event => {
|
|
||||||
if (game.user.isGM) {
|
|
||||||
await this.actor.removeEffects();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
this.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);
|
||||||
@@ -329,47 +285,39 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
|
|
||||||
if (this.options.vueDetaillee) {
|
if (this.options.vueDetaillee) {
|
||||||
// On carac change
|
// On carac change
|
||||||
this.html.find('.carac-value').change(async event => {
|
|
||||||
let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", "");
|
|
||||||
this.actor.updateCarac(caracName, parseInt(event.target.value));
|
|
||||||
});
|
|
||||||
this.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
|
|
||||||
this.html.find('.competence-value').change(async event => {
|
|
||||||
let compName = event.currentTarget.attributes.compname.value;
|
|
||||||
//console.log("Competence changed :", compName);
|
|
||||||
this.actor.updateCompetence(compName, parseInt(event.target.value));
|
|
||||||
});
|
|
||||||
// On competence xp change
|
// On competence xp change
|
||||||
this.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
|
|
||||||
this.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));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.html.find('.toggle-archetype').click(async event => {
|
||||||
|
this.options.vueArchetype = !this.options.vueArchetype;
|
||||||
|
this.render(true);
|
||||||
|
});
|
||||||
// On competence archetype change
|
// On competence archetype change
|
||||||
this.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));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
this.html.find('.nouvelle-incarnation').click(async event => {
|
||||||
|
this.actor.nouvelleIncarnation();
|
||||||
|
});
|
||||||
|
|
||||||
this.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);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.vue-detaillee').click(async event => {
|
|
||||||
this.options.vueDetaillee = !this.options.vueDetaillee;
|
|
||||||
this.render(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
// On pts de reve change
|
// On pts de reve change
|
||||||
this.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;
|
||||||
@@ -382,11 +330,6 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
this.actor.setPointsDeSeuil(event.currentTarget.value);
|
this.actor.setPointsDeSeuil(event.currentTarget.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
// On stress change
|
|
||||||
this.html.find('.compteur-edit').change(async event => {
|
|
||||||
let fieldName = event.currentTarget.attributes.name.value;
|
|
||||||
this.actor.updateCompteurValue(fieldName, parseInt(event.target.value));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.html.find('.stress-test').click(async event => {
|
this.html.find('.stress-test').click(async event => {
|
||||||
this.actor.transformerStress();
|
this.actor.transformerStress();
|
||||||
@@ -405,10 +348,10 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.jet-vie').click(async event => {
|
this.html.find('.jet-vie').click(async event => {
|
||||||
this.actor.jetVie();
|
this.actor.jetDeVie();
|
||||||
});
|
});
|
||||||
this.html.find('.jet-endurance').click(async event => {
|
this.html.find('.jet-endurance').click(async event => {
|
||||||
this.actor.jetEndurance();
|
await this.jetEndurance();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.vie-plus').click(async event => {
|
this.html.find('.vie-plus').click(async event => {
|
||||||
@@ -417,12 +360,6 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
this.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);
|
||||||
});
|
});
|
||||||
this.html.find('.endurance-plus').click(async event => {
|
|
||||||
this.actor.santeIncDec("endurance", 1);
|
|
||||||
});
|
|
||||||
this.html.find('.endurance-moins').click(async event => {
|
|
||||||
this.actor.santeIncDec("endurance", -1);
|
|
||||||
});
|
|
||||||
this.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);
|
||||||
});
|
});
|
||||||
@@ -437,6 +374,16 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async jetEndurance() {
|
||||||
|
const endurance = this.actor.getEnduranceActuelle()
|
||||||
|
const result = await this.actor.jetEndurance(endurance);
|
||||||
|
ChatMessage.create({
|
||||||
|
content: `Jet d'Endurance : ${result.jetEndurance} / ${endurance}
|
||||||
|
<br>${this.actor.name} a ${result.sonne ? 'échoué' : 'réussi'} son Jet d'Endurance ${result.sonne ? 'et devient Sonné' : ''}`,
|
||||||
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.actor.name)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
getBlessure(event) {
|
getBlessure(event) {
|
||||||
const itemId = this.html.find(event.currentTarget).parents(".item-blessure").data('item-id');
|
const itemId = this.html.find(event.currentTarget).parents(".item-blessure").data('item-id');
|
||||||
const blessure = this.actor.getItem(itemId, 'blessure');
|
const blessure = this.actor.getItem(itemId, 'blessure');
|
||||||
@@ -456,9 +403,9 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async selectTypeOeuvreToCreate() {
|
async selectTypeOeuvreToCreate() {
|
||||||
let typeObjets = RdDItem.getTypesOeuvres();
|
let types = RdDItem.getTypesOeuvres();
|
||||||
let content = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`;
|
let content = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`;
|
||||||
for (let typeName of typeObjets) {
|
for (let typeName of types) {
|
||||||
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
||||||
}
|
}
|
||||||
content += '</select>';
|
content += '</select>';
|
||||||
|
1247
module/actor.js
1247
module/actor.js
File diff suppressed because it is too large
Load Diff
64
module/actor/base-actor-reve-sheet.js
Normal file
64
module/actor/base-actor-reve-sheet.js
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
|
||||||
|
import { RdDBaseActorSheet } from "./base-actor-sheet.js";
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/**
|
||||||
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
|
* @extends {ActorSheet}
|
||||||
|
*/
|
||||||
|
export class RdDBaseActorReveSheet extends RdDBaseActorSheet {
|
||||||
|
|
||||||
|
/** @override */
|
||||||
|
static get defaultOptions() {
|
||||||
|
return mergeObject(RdDBaseActorSheet.defaultOptions, {
|
||||||
|
width: 550
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** @override */
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
// Everything below here is only needed if the sheet is editable
|
||||||
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
this.html.find('.encaisser-direct').click(async event => {
|
||||||
|
this.actor.encaisser();
|
||||||
|
})
|
||||||
|
this.html.find('.remise-a-neuf').click(async event => {
|
||||||
|
if (game.user.isGM) {
|
||||||
|
this.actor.remiseANeuf();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.html.find('.carac-label a').click(async event => {
|
||||||
|
let caracName = event.currentTarget.attributes.name.value;
|
||||||
|
this.actor.rollCarac(caracName.toLowerCase());
|
||||||
|
});
|
||||||
|
|
||||||
|
this.html.find('a.competence-label').click(async event => {
|
||||||
|
this.actor.rollCompetence(RdDSheetUtility.getItemId(event));
|
||||||
|
});
|
||||||
|
|
||||||
|
this.html.find('.delete-active-effect').click(async event => {
|
||||||
|
if (game.user.isGM) {
|
||||||
|
let effect = this.html.find(event.currentTarget).parents(".active-effect").data('effect');
|
||||||
|
this.actor.removeEffect(effect);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.html.find('.enlever-tous-effets').click(async event => {
|
||||||
|
if (game.user.isGM) {
|
||||||
|
await this.actor.removeEffects();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.html.find('.endurance-plus').click(async event => {
|
||||||
|
this.actor.santeIncDec("endurance", 1);
|
||||||
|
});
|
||||||
|
this.html.find('.endurance-moins').click(async event => {
|
||||||
|
this.actor.santeIncDec("endurance", -1);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
509
module/actor/base-actor-reve.js
Normal file
509
module/actor/base-actor-reve.js
Normal file
@@ -0,0 +1,509 @@
|
|||||||
|
import { ChatUtility } from "../chat-utility.js";
|
||||||
|
import { DialogValidationEncaissement } from "../dialog-validation-encaissement.js";
|
||||||
|
import { Grammar } from "../grammar.js";
|
||||||
|
import { RdDItemCompetence } from "../item-competence.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { RdDEmpoignade } from "../rdd-empoignade.js";
|
||||||
|
import { RdDResolutionTable } from "../rdd-resolution-table.js";
|
||||||
|
import { RdDEncaisser } from "../rdd-roll-encaisser.js";
|
||||||
|
import { RdDRoll } from "../rdd-roll.js";
|
||||||
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
|
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||||
|
import { RdDBaseActor } from "./base-actor.js";
|
||||||
|
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
|
||||||
|
import { StatusEffects } from "../settings/status-effects.js";
|
||||||
|
import { TYPES } from "../item.js";
|
||||||
|
import { Targets } from "../targets.js";
|
||||||
|
import { RdDPossession } from "../rdd-possession.js";
|
||||||
|
import { RdDCombat } from "../rdd-combat.js";
|
||||||
|
import { RdDConfirm } from "../rdd-confirm.js";
|
||||||
|
import { ENTITE_INCARNE, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
|
||||||
|
import { RdDItemArme } from "../item-arme.js";
|
||||||
|
|
||||||
|
const POSSESSION_SANS_DRACONIC = {
|
||||||
|
img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp',
|
||||||
|
name: 'Sans draconic',
|
||||||
|
system: {
|
||||||
|
niveau: 0,
|
||||||
|
defaut_carac: "reve-actuel",
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe de base pour les acteurs disposant de rêve (donc, pas des objets)
|
||||||
|
* - Entités de rêve
|
||||||
|
* - Créatures de "sang": créatures et humanoides
|
||||||
|
*/
|
||||||
|
export class RdDBaseActorReve extends RdDBaseActor {
|
||||||
|
|
||||||
|
getCaracChanceActuelle() {
|
||||||
|
return {
|
||||||
|
label: 'Chance actuelle',
|
||||||
|
value: this.getChanceActuel(),
|
||||||
|
type: "number"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getCaracReveActuel() {
|
||||||
|
return {
|
||||||
|
label: 'Rêve actuel',
|
||||||
|
value: this.getReveActuel(),
|
||||||
|
type: "number"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
getReveActuel() { return this.getReve() }
|
||||||
|
getChanceActuel() { return this.getChance() }
|
||||||
|
|
||||||
|
getReve() { return Number(this.system.carac.reve?.value ?? 0) }
|
||||||
|
getForce() { return this.getReve() }
|
||||||
|
getTaille() { return Number(this.system.carac.taille?.value ?? 0) }
|
||||||
|
getAgilite() { return this.getForce() }
|
||||||
|
getChance() { return this.getReve() }
|
||||||
|
getMoralTotal() { return 0 }
|
||||||
|
getBonusDegat() { return Number(this.system.attributs?.plusdom?.value ?? 0) }
|
||||||
|
getProtectionNaturelle() { return Number(this.system.attributs?.protection?.value ?? 0) }
|
||||||
|
getSConst() { return 0 }
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getEncombrementMax() { return 0 }
|
||||||
|
isSurenc() { return false }
|
||||||
|
computeMalusSurEncombrement() { return 0 }
|
||||||
|
|
||||||
|
ajustementAstrologique() { return 0 }
|
||||||
|
getMalusArmure() { return 0 }
|
||||||
|
|
||||||
|
getEnduranceActuelle() {
|
||||||
|
return Number(this.system.sante?.endurance?.value ?? 0);
|
||||||
|
}
|
||||||
|
async jetEndurance(resteEndurance = undefined) { return { jetEndurance: 0, sonne: false } }
|
||||||
|
isDead() { return false }
|
||||||
|
blessuresASoigner() { return [] }
|
||||||
|
getEtatGeneral(options = { ethylisme: false }) { return 0 }
|
||||||
|
|
||||||
|
async computeArmure(attackerRoll) { return this.getProtectionNaturelle() }
|
||||||
|
async remiseANeuf() { }
|
||||||
|
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
|
||||||
|
|
||||||
|
async santeIncDec(name, inc, isCritique = false) { }
|
||||||
|
|
||||||
|
async finDeRound(options = { terminer: false }) {
|
||||||
|
await this.$finDeRoundSuppressionEffetsTermines(options);
|
||||||
|
await this.finDeRoundBlessures();
|
||||||
|
await this.$finDeRoundSupprimerObsoletes();
|
||||||
|
await this.$finDeRoundEmpoignade();
|
||||||
|
}
|
||||||
|
|
||||||
|
async $finDeRoundSuppressionEffetsTermines(options) {
|
||||||
|
for (let effect of this.getEffects()) {
|
||||||
|
if (effect.duration.type !== 'none' && (effect.duration.remaining <= 0 || options.terminer)) {
|
||||||
|
await effect.delete();
|
||||||
|
ChatMessage.create({ content: `${this.name} n'est plus ${Misc.lowerFirst(game.i18n.localize(effect.system.label))} !` });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async finDeRoundBlessures() {
|
||||||
|
}
|
||||||
|
|
||||||
|
async $finDeRoundSupprimerObsoletes() {
|
||||||
|
const obsoletes = []
|
||||||
|
.concat(this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp <= 0))
|
||||||
|
.concat(this.itemTypes[TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2))
|
||||||
|
.map(it => it.id);
|
||||||
|
await this.deleteEmbeddedDocuments('Item', obsoletes);
|
||||||
|
}
|
||||||
|
|
||||||
|
async $finDeRoundEmpoignade() {
|
||||||
|
const immobilisations = this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id);
|
||||||
|
immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this,
|
||||||
|
game.actors.get(emp.system.empoigneid),
|
||||||
|
emp
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
async setSonne(sonne = true) { }
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getCompetence(idOrName, options = {}) {
|
||||||
|
if (idOrName instanceof Item) {
|
||||||
|
return idOrName.isCompetence() ? idOrName : undefined
|
||||||
|
}
|
||||||
|
return RdDItemCompetence.findCompetence(this.items, idOrName, options)
|
||||||
|
}
|
||||||
|
getCompetences(name) {
|
||||||
|
return RdDItemCompetence.findCompetences(this.items, name)
|
||||||
|
}
|
||||||
|
getCompetenceCorpsACorps(options = {}) {
|
||||||
|
return this.getCompetence("Corps à corps", options)
|
||||||
|
}
|
||||||
|
getCompetencesEsquive() {
|
||||||
|
return this.getCompetences("esquive")
|
||||||
|
}
|
||||||
|
|
||||||
|
getArmeParade(armeParadeId) {
|
||||||
|
const item = armeParadeId ? this.getEmbeddedDocument('Item', armeParadeId) : undefined;
|
||||||
|
return RdDItemArme.getArme(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
getDraconicOuPossession() {
|
||||||
|
return POSSESSION_SANS_DRACONIC
|
||||||
|
}
|
||||||
|
|
||||||
|
getPossession(possessionId) {
|
||||||
|
return this.itemTypes[TYPES.possession].find(it => it.system.possessionid == possessionId);
|
||||||
|
}
|
||||||
|
getPossessions() {
|
||||||
|
return this.itemTypes[TYPES.possession];
|
||||||
|
}
|
||||||
|
getEmpoignades() {
|
||||||
|
return this.itemTypes[TYPES.empoignade];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async updateCreatureCompetence(idOrName, fieldName, value) {
|
||||||
|
let competence = this.getCompetence(idOrName);
|
||||||
|
if (competence) {
|
||||||
|
function getFieldPath(fieldName) {
|
||||||
|
switch (fieldName) {
|
||||||
|
case "niveau": return 'system.niveau';
|
||||||
|
case "dommages": return 'system.dommages';
|
||||||
|
case "carac_value": return 'system.carac_value';
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
const path = getFieldPath(fieldName);
|
||||||
|
if (path) {
|
||||||
|
await this.updateEmbeddedDocuments('Item', [{ _id: competence.id, [path]: value }]); // updates one EmbeddedEntity
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
isEffectAllowed(statusId) { return true }
|
||||||
|
|
||||||
|
getEffects(filter = e => true) {
|
||||||
|
return this.getEmbeddedCollection("ActiveEffect").filter(filter);
|
||||||
|
}
|
||||||
|
|
||||||
|
getEffect(statusId) {
|
||||||
|
return this.getEmbeddedCollection("ActiveEffect").find(it => it.flags?.core?.statusId == statusId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async setEffect(statusId, status) {
|
||||||
|
if (this.isEffectAllowed(statusId)) {
|
||||||
|
const effect = this.getEffect(statusId);
|
||||||
|
if (!status && effect) {
|
||||||
|
await this.deleteEmbeddedDocuments('ActiveEffect', [effect.id]);
|
||||||
|
}
|
||||||
|
if (status && !effect) {
|
||||||
|
await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.status(statusId)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeEffect(statusId) {
|
||||||
|
const effect = this.getEffect(statusId);
|
||||||
|
if (effect) {
|
||||||
|
await this.deleteEmbeddedDocuments('ActiveEffect', [effect.id]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeEffects(filter = e => true) {
|
||||||
|
if (game.user.isGM) {
|
||||||
|
const ids = this.getEffects(filter).map(it => it.id);
|
||||||
|
await this.deleteEmbeddedDocuments('ActiveEffect', ids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getSurprise(isCombat = undefined) {
|
||||||
|
let niveauSurprise = this.getEffects()
|
||||||
|
.map(effect => StatusEffects.valeurSurprise(effect, isCombat))
|
||||||
|
.reduce(Misc.sum(), 0);
|
||||||
|
if (niveauSurprise > 1) {
|
||||||
|
return 'totale';
|
||||||
|
}
|
||||||
|
if (niveauSurprise == 1) {
|
||||||
|
return 'demi';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async computeEtatGeneral() {
|
||||||
|
// Par défaut, on ne calcule pas d'état général, seuls les personnages/créatures sont affectés
|
||||||
|
this.system.compteurs.etat.value = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async openRollDialog({ name, label, template, rollData, callbackAction }) {
|
||||||
|
const dialog = await RdDRoll.create(this, rollData,
|
||||||
|
{ html: template, close: async html => await this._onCloseRollDialog(html) },
|
||||||
|
{
|
||||||
|
name: name,
|
||||||
|
label: label,
|
||||||
|
callbacks: [
|
||||||
|
this.createCallbackExperience(),
|
||||||
|
this.createCallbackAppelAuMoral(),
|
||||||
|
{ action: callbackAction }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
dialog.render(true);
|
||||||
|
return dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
createEmptyCallback() {
|
||||||
|
return {
|
||||||
|
condition: r => false,
|
||||||
|
action: r => { }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
createCallbackExperience() { return this.createEmptyCallback(); }
|
||||||
|
createCallbackAppelAuMoral() { return this.createEmptyCallback(); }
|
||||||
|
async _onCloseRollDialog(html) { }
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async roll() {
|
||||||
|
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||||
|
|
||||||
|
const carac = this.getCarac()
|
||||||
|
const selectedCaracName = ['apparence', 'perception', 'force', 'reve'].find(it => carac[it] != undefined)
|
||||||
|
|
||||||
|
await this.openRollDialog({
|
||||||
|
name: `jet-${this.id}`,
|
||||||
|
label: `Jet de ${this.name}`,
|
||||||
|
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll.html',
|
||||||
|
rollData: {
|
||||||
|
carac: carac,
|
||||||
|
selectedCarac: carac[selectedCaracName],
|
||||||
|
selectedCaracName: selectedCaracName,
|
||||||
|
competences: this.itemTypes['competence']
|
||||||
|
},
|
||||||
|
callbackAction: r => this.$onRollCaracResult(r)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getCarac() {
|
||||||
|
// TODO: le niveau d'une entité de cauchemar devrait être exclu...
|
||||||
|
const carac = mergeObject(duplicate(this.system.carac),
|
||||||
|
{
|
||||||
|
'reve-actuel': this.getCaracReveActuel(),
|
||||||
|
'chance-actuelle': this.getCaracChanceActuelle()
|
||||||
|
});
|
||||||
|
return carac;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async rollCarac(caracName, jetResistance = undefined) {
|
||||||
|
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||||
|
let selectedCarac = this.getCaracByName(caracName)
|
||||||
|
await this.openRollDialog({
|
||||||
|
name: 'jet-' + caracName,
|
||||||
|
label: 'Jet ' + Grammar.apostrophe('de', selectedCarac.label),
|
||||||
|
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html',
|
||||||
|
rollData: {
|
||||||
|
selectedCarac: selectedCarac,
|
||||||
|
competences: this.itemTypes['competence'],
|
||||||
|
jetResistance: jetResistance ? caracName : undefined
|
||||||
|
},
|
||||||
|
callbackAction: r => this.$onRollCaracResult(r)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async $onRollCaracResult(rollData) {
|
||||||
|
// Final chat message
|
||||||
|
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-general.html');
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async rollCompetence(idOrName, options = { tryTarget: true }) {
|
||||||
|
RdDEmpoignade.checkEmpoignadeEnCours(this)
|
||||||
|
const competence = this.getCompetence(idOrName);
|
||||||
|
let rollData = { carac: this.system.carac, competence: competence }
|
||||||
|
if (competence.type == TYPES.competencecreature) {
|
||||||
|
const arme = RdDItemCompetenceCreature.armeCreature(competence)
|
||||||
|
if (arme && options.tryTarget && Targets.hasTargets()) {
|
||||||
|
Targets.selectOneToken(target => {
|
||||||
|
if (arme.action == "possession") {
|
||||||
|
RdDPossession.onAttaquePossession(target, this, competence)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RdDCombat.rddCombatTarget(target, this).attaque(competence, arme)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Transformer la competence de créature
|
||||||
|
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
||||||
|
}
|
||||||
|
|
||||||
|
await this.openRollDialog({
|
||||||
|
name: 'jet-competence',
|
||||||
|
label: 'Jet ' + Grammar.apostrophe('de', competence.name),
|
||||||
|
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html',
|
||||||
|
rollData: rollData,
|
||||||
|
callbackAction: r => this.$onRollCompetence(r, options)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async $onRollCompetence(rollData, options) {
|
||||||
|
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-competence.html')
|
||||||
|
if (options?.onRollAutomate) {
|
||||||
|
options.onRollAutomate(rollData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** --------------------------------------------
|
||||||
|
* @param {*} arme item d'arme/compétence de créature
|
||||||
|
* @param {*} categorieArme catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
rollArme(arme, categorieArme = "competence") {
|
||||||
|
let compToUse = this.$getCompetenceArme(arme, categorieArme)
|
||||||
|
if (!Targets.hasTargets()) {
|
||||||
|
RdDConfirm.confirmer({
|
||||||
|
settingConfirmer: "confirmer-combat-sans-cible",
|
||||||
|
content: `<p>Voulez vous faire un jet de ${compToUse} sans choisir de cible valide?
|
||||||
|
<br>Tous les jets de combats devront être gérés à la main
|
||||||
|
</p>`,
|
||||||
|
title: 'Ne pas utiliser les automatisation de combat',
|
||||||
|
buttonLabel: "Pas d'automatisation",
|
||||||
|
onAction: async () => {
|
||||||
|
this.rollCompetence(compToUse, { tryTarget: false })
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Targets.selectOneToken(target => {
|
||||||
|
if (Targets.isTargetEntite(target)) {
|
||||||
|
ui.notifications.warn(`Vous ne pouvez pas attaquer une entité non incarnée avec votre ${arme.name}!!!!`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const competence = this.getCompetence(compToUse)
|
||||||
|
//console.log("RollArme", competence, arme)
|
||||||
|
if (competence.isCompetencePossession()) {
|
||||||
|
return RdDPossession.onAttaquePossession(target, this, competence);
|
||||||
|
}
|
||||||
|
RdDCombat.rddCombatTarget(target, this).attaque(competence, arme);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
$getCompetenceArme(arme, competenceName) {
|
||||||
|
switch (arme.type) {
|
||||||
|
case TYPES.competencecreature:
|
||||||
|
return arme.name
|
||||||
|
case TYPES.arme:
|
||||||
|
switch (competenceName) {
|
||||||
|
case 'competence': return arme.system.competence;
|
||||||
|
case 'unemain': return RdDItemArme.competence1Mains(arme);
|
||||||
|
case 'deuxmains': return RdDItemArme.competence2Mains(arme);
|
||||||
|
case 'tir': return arme.system.tir;
|
||||||
|
case 'lancer': return arme.system.lancer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
verifierForceMin(item) {
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async resetItemUse() { }
|
||||||
|
async incDecItemUse(itemId, inc = 1) { }
|
||||||
|
getItemUse(itemId) { return 0; }
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async encaisser() { await RdDEncaisser.encaisser(this) }
|
||||||
|
|
||||||
|
async encaisserDommages(rollData, attacker = undefined, show = undefined) {
|
||||||
|
if (attacker && !await attacker.accorder(this, 'avant-encaissement')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const attackerId = attacker?.id;
|
||||||
|
if (ReglesOptionnelles.isUsing('validation-encaissement-gr') && !game.user.isGM) {
|
||||||
|
RdDBaseActor.remoteActorCall({
|
||||||
|
tokenId: this.token?.id,
|
||||||
|
actorId: this.id,
|
||||||
|
method: 'appliquerEncaissement',
|
||||||
|
args: [rollData, show, attackerId]
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const armure = await this.computeArmure(rollData);
|
||||||
|
if (ReglesOptionnelles.isUsing('validation-encaissement-gr')) {
|
||||||
|
DialogValidationEncaissement.validerEncaissement(this, rollData, armure,
|
||||||
|
jet => this.$onEncaissement(jet, show, attacker));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const jet = await RdDUtility.jetEncaissement(rollData, armure, { showDice: SHOW_DICE });
|
||||||
|
await this.$onEncaissement(jet, show, attacker);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async $onEncaissement(jet, show, attacker) {
|
||||||
|
await this.onAppliquerJetEncaissement(jet, attacker);
|
||||||
|
await this.$afficherEncaissement(jet, show);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onAppliquerJetEncaissement(encaissement, attacker) { }
|
||||||
|
|
||||||
|
async $afficherEncaissement(encaissement, show) {
|
||||||
|
mergeObject(encaissement, {
|
||||||
|
alias: this.name,
|
||||||
|
hasPlayerOwner: this.hasPlayerOwner,
|
||||||
|
show: show ?? {}
|
||||||
|
});
|
||||||
|
|
||||||
|
await ChatUtility.createChatWithRollMode(this.name, {
|
||||||
|
roll: encaissement.roll,
|
||||||
|
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html', encaissement)
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!encaissement.hasPlayerOwner && encaissement.endurance != 0) {
|
||||||
|
encaissement = duplicate(encaissement);
|
||||||
|
encaissement.isGM = true;
|
||||||
|
ChatMessage.create({
|
||||||
|
whisper: ChatMessage.getWhisperRecipients("GM"),
|
||||||
|
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html', encaissement)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async accorder(entite, when = 'avant-encaissement') {
|
||||||
|
if (when != game.settings.get(SYSTEM_RDD, "accorder-entite-cauchemar")
|
||||||
|
|| entite == undefined
|
||||||
|
|| !entite.isEntite([ENTITE_INCARNE])
|
||||||
|
|| entite.isEntiteAccordee(this)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
const rolled = await RdDResolutionTable.roll(this.getReveActuel(), - Number(entite.system.carac.niveau.value));
|
||||||
|
const rollData = {
|
||||||
|
alias: this.name,
|
||||||
|
rolled: rolled,
|
||||||
|
entite: entite.name,
|
||||||
|
selectedCarac: this.system.carac.reve
|
||||||
|
};
|
||||||
|
|
||||||
|
if (rolled.isSuccess) {
|
||||||
|
await entite.setEntiteReveAccordee(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-accorder-cauchemar.html');
|
||||||
|
if (rolled.isPart) {
|
||||||
|
await this.appliquerAjoutExperience(rollData, true);
|
||||||
|
}
|
||||||
|
return rolled.isSuccess;
|
||||||
|
}
|
||||||
|
|
||||||
|
isEntiteAccordee(attacker) { return true }
|
||||||
|
|
||||||
|
async setEntiteReveAccordee(attacker) {
|
||||||
|
ui.notifications.error("Impossible de s'accorder à " + this.name + ": ce n'est pas une entite de cauchemer/rêve");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
291
module/actor/base-actor-sang.js
Normal file
291
module/actor/base-actor-sang.js
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
import { MAX_ENDURANCE_FATIGUE, RdDUtility } from "../rdd-utility.js";
|
||||||
|
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||||
|
import { STATUSES } from "../settings/status-effects.js";
|
||||||
|
import { TYPES } from "../item.js";
|
||||||
|
import { RdDBaseActorReve } from "./base-actor-reve.js";
|
||||||
|
import { RdDDice } from "../rdd-dice.js";
|
||||||
|
import { RdDItemBlessure } from "../item/blessure.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classe de base pour les acteurs qui peuvent subir des blessures
|
||||||
|
* - créatures
|
||||||
|
* - humanoides
|
||||||
|
*/
|
||||||
|
export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||||
|
|
||||||
|
|
||||||
|
getForce() { return Number(this.system.carac.force?.value ?? 0) }
|
||||||
|
|
||||||
|
getBonusDegat() { return Number(this.system.attributs?.plusdom?.value ?? 0) }
|
||||||
|
getProtectionNaturelle() { return Number(this.system.attributs?.protection?.value ?? 0) }
|
||||||
|
getSConst() { return 0 }
|
||||||
|
|
||||||
|
getEnduranceMax() {
|
||||||
|
return Math.max(1, Math.min(this.system.sante.endurance.max, MAX_ENDURANCE_FATIGUE));
|
||||||
|
}
|
||||||
|
|
||||||
|
getFatigueActuelle() {
|
||||||
|
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||||
|
return Math.max(0, Math.min(this.getFatigueMax(), this.system.sante.fatigue?.value));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFatigueRestante() {
|
||||||
|
return this.getFatigueMax() - this.getFatigueActuelle();
|
||||||
|
}
|
||||||
|
|
||||||
|
getFatigueMin() {
|
||||||
|
return this.system.sante.endurance.max - this.system.sante.endurance.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
getFatigueMax() { return this.getEnduranceMax() * 2 }
|
||||||
|
|
||||||
|
malusFatigue() {
|
||||||
|
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||||
|
return RdDUtility.calculMalusFatigue(this.getFatigueActuelle(), this.getEnduranceMax())
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getEncombrementMax() { return Number(this.system.attributs?.encombrement?.value ?? 0) }
|
||||||
|
isSurenc() { return this.computeMalusSurEncombrement() < 0 }
|
||||||
|
|
||||||
|
computeMalusSurEncombrement() {
|
||||||
|
return Math.min(0, Math.floor(this.getEncombrementMax() - this.encTotal));
|
||||||
|
}
|
||||||
|
|
||||||
|
isDead() {
|
||||||
|
return this.system.sante.vie.value < -this.getSConst()
|
||||||
|
}
|
||||||
|
|
||||||
|
nbBlessuresLegeres() {
|
||||||
|
return this.itemTypes[TYPES.blessure].filter(it => it.isLegere()).length;
|
||||||
|
}
|
||||||
|
nbBlessuresGraves() {
|
||||||
|
return this.itemTypes[TYPES.blessure].filter(it => it.isGrave()).length;
|
||||||
|
}
|
||||||
|
nbBlessuresCritiques() {
|
||||||
|
return this.itemTypes[TYPES.blessure].filter(it => it.isCritique()).length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
computeResumeBlessure() {
|
||||||
|
const nbLegeres = this.nbBlessuresLegeres()
|
||||||
|
const nbGraves = this.nbBlessuresGraves()
|
||||||
|
const nbCritiques = this.nbBlessuresCritiques()
|
||||||
|
|
||||||
|
if (nbLegeres + nbGraves + nbCritiques == 0) {
|
||||||
|
return "Aucune blessure";
|
||||||
|
}
|
||||||
|
let resume = "Blessures:";
|
||||||
|
if (nbLegeres > 0) {
|
||||||
|
resume += " " + nbLegeres + " légère" + (nbLegeres > 1 ? "s" : "");
|
||||||
|
}
|
||||||
|
if (nbGraves > 0) {
|
||||||
|
if (nbLegeres > 0)
|
||||||
|
resume += ",";
|
||||||
|
resume += " " + nbGraves + " grave" + (nbGraves > 1 ? "s" : "");
|
||||||
|
}
|
||||||
|
if (nbCritiques > 0) {
|
||||||
|
if (nbGraves > 0 || nbLegeres > 0)
|
||||||
|
resume += ",";
|
||||||
|
resume += " une CRITIQUE !";
|
||||||
|
}
|
||||||
|
return resume;
|
||||||
|
}
|
||||||
|
|
||||||
|
blessuresASoigner() { return [] }
|
||||||
|
getEtatGeneral(options = { ethylisme: false }) { return 0 }
|
||||||
|
|
||||||
|
async computeArmure(attackerRoll) { return this.getProtectionNaturelle() }
|
||||||
|
async remiseANeuf() { }
|
||||||
|
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
async onAppliquerJetEncaissement(encaissement, attacker) {
|
||||||
|
const santeOrig = duplicate(this.system.sante);
|
||||||
|
const blessure = await this.ajouterBlessure(encaissement, attacker); // Will update the result table
|
||||||
|
const perteVie = await this.santeIncDec("vie", -encaissement.vie);
|
||||||
|
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, blessure?.isCritique());
|
||||||
|
|
||||||
|
mergeObject(encaissement, {
|
||||||
|
resteEndurance: perteEndurance.newValue,
|
||||||
|
sonne: perteEndurance.sonne,
|
||||||
|
jetEndurance: perteEndurance.jetEndurance,
|
||||||
|
endurance: perteEndurance.perte,
|
||||||
|
vie: santeOrig.vie.value - perteVie.newValue,
|
||||||
|
blessure: blessure
|
||||||
|
});
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async santeIncDec(name, inc, isCritique = false) {
|
||||||
|
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const sante = duplicate(this.system.sante)
|
||||||
|
let compteur = sante[name];
|
||||||
|
if (!compteur) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let result = {
|
||||||
|
sonne: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let minValue = name == "vie" ? -this.getSConst() - 1 : 0;
|
||||||
|
|
||||||
|
result.newValue = Math.max(minValue, Math.min(compteur.value + inc, compteur.max));
|
||||||
|
//console.log("New value ", inc, minValue, result.newValue);
|
||||||
|
let fatigue = 0;
|
||||||
|
if (name == "endurance") {
|
||||||
|
if (result.newValue == 0 && inc < 0 && !isCritique) { // perte endurance et endurance devient 0 (sauf critique) -> -1 vie
|
||||||
|
sante.vie.value--;
|
||||||
|
result.perteVie = true;
|
||||||
|
}
|
||||||
|
result.newValue = Math.max(0, result.newValue);
|
||||||
|
if (inc > 0) { // le max d'endurance s'applique seulement à la récupération
|
||||||
|
result.newValue = Math.min(result.newValue, this._computeEnduranceMax())
|
||||||
|
}
|
||||||
|
const perte = compteur.value - result.newValue;
|
||||||
|
result.perte = perte;
|
||||||
|
if (perte > 1) {
|
||||||
|
// Peut-être sonné si 2 points d'endurance perdus d'un coup
|
||||||
|
mergeObject(result, await this.jetEndurance(result.newValue));
|
||||||
|
} else if (inc > 0) {
|
||||||
|
await this.setSonne(false);
|
||||||
|
}
|
||||||
|
if (sante.fatigue && inc < 0) { // Each endurance lost -> fatigue lost
|
||||||
|
fatigue = perte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
compteur.value = result.newValue;
|
||||||
|
// If endurance lost, then the same amount of fatigue cannot be recovered
|
||||||
|
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && sante.fatigue && fatigue > 0) {
|
||||||
|
sante.fatigue.value = Math.max(sante.fatigue.value + fatigue, this.getFatigueMin());
|
||||||
|
}
|
||||||
|
await this.update({ "system.sante": sante })
|
||||||
|
if (this.isDead()) {
|
||||||
|
await this.setEffect(STATUSES.StatusComma, true);
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async ajouterBlessure(encaissement, attacker = undefined) {
|
||||||
|
if (encaissement.gravite < 0) return;
|
||||||
|
if (encaissement.gravite > 0) {
|
||||||
|
while (this.countBlessures(it => it.system.gravite == encaissement.gravite) >= RdDItemBlessure.maxBlessures(encaissement.gravite) && encaissement.gravite <= 6) {
|
||||||
|
// Aggravation
|
||||||
|
encaissement.gravite += 2
|
||||||
|
if (encaissement.gravite > 2) {
|
||||||
|
encaissement.vie += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const endActuelle = this.getEnduranceActuelle();
|
||||||
|
const blessure = await RdDItemBlessure.createBlessure(this, encaissement.gravite, encaissement.dmg.loc.label, attacker);
|
||||||
|
if (blessure.isCritique()) {
|
||||||
|
encaissement.endurance = endActuelle;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (blessure.isMort()) {
|
||||||
|
this.setEffect(STATUSES.StatusComma, true);
|
||||||
|
encaissement.mort = true;
|
||||||
|
ChatMessage.create({
|
||||||
|
content: `<img class="chat-icon" src="icons/svg/skull.svg" alt="charge" />
|
||||||
|
<strong>${this.name} vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !</strong>`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return blessure;
|
||||||
|
}
|
||||||
|
|
||||||
|
async supprimerBlessures(filterToDelete) {
|
||||||
|
const toDelete = this.filterItems(filterToDelete, TYPES.blessure)
|
||||||
|
.map(it => it.id);
|
||||||
|
await this.deleteEmbeddedDocuments('Item', toDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
countBlessures(filter = it => !it.isContusion()) {
|
||||||
|
return this.filterItems(filter, 'blessure').length
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async jetDeVie() {
|
||||||
|
if (this.isDead()) {
|
||||||
|
ChatMessage.create({ content: `Jet de Vie: ${this.name} est déjà mort, ce n'est pas la peine d'en rajouter !!!!!`, whisper: ChatMessage.getWhisperRecipients(this.name) });
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const jetDeVie = await RdDDice.roll("1d20");
|
||||||
|
|
||||||
|
const sConst = this.getSConst();
|
||||||
|
const vie = this.system.sante.vie.value;
|
||||||
|
const isCritique = this.nbBlessuresCritiques() > 0;
|
||||||
|
const isGrave = this.nbBlessuresGraves();
|
||||||
|
const isEchecTotal = jetDeVie.total == 20;
|
||||||
|
const isSuccess = jetDeVie.total == 1 || jetDeVie.total <= vie;
|
||||||
|
const perte = isSuccess ? 0 : 1 + (isEchecTotal ? vie + sConst : 0)
|
||||||
|
const prochainJet = (jetDeVie.total == 1 && vie > 0 ? 20 : 1) * (isCritique ? 1 : isGrave > 0 ? sConst : 0)
|
||||||
|
|
||||||
|
let msgText = `Jet de Vie: <strong>${jetDeVie.total} / ${vie}</strong>`
|
||||||
|
if (isSuccess) {
|
||||||
|
msgText += "<br>Réussi, pas de perte de point de vie."
|
||||||
|
} else {
|
||||||
|
msgText += `<br>Echoué, perte ${perte} point de vie`;
|
||||||
|
await this.santeIncDec("vie", -perte);
|
||||||
|
}
|
||||||
|
if (this.isDead()) {
|
||||||
|
msgText += `<br><strong>${this.name} est mort !!!!</strong>`;
|
||||||
|
}
|
||||||
|
else if (prochainJet > 0) {
|
||||||
|
msgText += `<br>Prochain jet de vie dans ${prochainJet} ${isCritique ? 'round' : 'minute'}${prochainJet > 1 ? 's' : ''} ${isCritique ? '(état critique)' : '(état grave)'}`
|
||||||
|
}
|
||||||
|
ChatMessage.create({ content: msgText, whisper: ChatMessage.getWhisperRecipients(this.name) });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async jetEndurance(resteEndurance = undefined) {
|
||||||
|
const jetEndurance = (await RdDDice.roll("1d20")).total;
|
||||||
|
const sonne = jetEndurance == 20 || jetEndurance > (resteEndurance ?? this.system.sante.endurance.value)
|
||||||
|
if (sonne) {
|
||||||
|
await this.setSonne();
|
||||||
|
}
|
||||||
|
return { jetEndurance, sonne }
|
||||||
|
}
|
||||||
|
|
||||||
|
async finDeRoundBlessures() {
|
||||||
|
const nbGraves = this.filterItems(it => it.isGrave(), 'blessure').length;
|
||||||
|
if (nbGraves > 0) {
|
||||||
|
// Gestion blessure graves : -1 pt endurance par blessure grave
|
||||||
|
await this.santeIncDec("endurance", -nbGraves);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async setSonne(sonne = true) {
|
||||||
|
if (!game.combat && sonne) {
|
||||||
|
ui.notifications.info(`${this.name} est hors combat, il ne reste donc pas sonné`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.setEffect(STATUSES.StatusStunned, sonne);
|
||||||
|
}
|
||||||
|
|
||||||
|
getSonne() {
|
||||||
|
return this.getEffect(STATUSES.StatusStunned);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async computeEtatGeneral() {
|
||||||
|
this.system.compteurs.etat.value = this.malusVie() + this.malusFatigue() + this.malusEthylisme();
|
||||||
|
}
|
||||||
|
|
||||||
|
malusVie() {
|
||||||
|
return Math.min(this.system.sante.vie.value - this.system.sante.vie.max, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
malusEthylisme() { return 0 }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -3,7 +3,8 @@ import { Misc } from "../misc.js";
|
|||||||
import { DialogSplitItem } from "../dialog-split-item.js";
|
import { DialogSplitItem } from "../dialog-split-item.js";
|
||||||
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
|
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
|
||||||
import { Monnaie } from "../item-monnaie.js";
|
import { Monnaie } from "../item-monnaie.js";
|
||||||
import { RdDItem } from "../item.js";
|
import { RdDItem, TYPES } from "../item.js";
|
||||||
|
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/**
|
/**
|
||||||
@@ -15,13 +16,10 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
RdDUtility.initAfficheContenu();
|
RdDUtility.initAfficheContenu();
|
||||||
return mergeObject(super.defaultOptions, {
|
return mergeObject(ActorSheet.defaultOptions, {
|
||||||
classes: ["rdd", "sheet", "actor"],
|
classes: ["rdd", "sheet", "actor"],
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html",
|
|
||||||
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,
|
|
||||||
vueDetaillee: false
|
vueDetaillee: false
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -30,7 +28,7 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
async getData() {
|
async getData() {
|
||||||
Monnaie.validerMonnaies(this.actor.itemTypes['monnaie']);
|
Monnaie.validerMonnaies(this.actor.itemTypes['monnaie']);
|
||||||
|
|
||||||
this.actor.recompute();
|
this.actor.computeEtatGeneral();
|
||||||
let formData = {
|
let formData = {
|
||||||
title: this.title,
|
title: this.title,
|
||||||
id: this.actor.id,
|
id: this.actor.id,
|
||||||
@@ -50,16 +48,18 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
encTotal: await this.actor.computeEncTotal(),
|
encTotal: await this.actor.computeEncTotal(),
|
||||||
}
|
}
|
||||||
|
|
||||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
|
||||||
this._appliquerRechercheObjets(formData.objets, formData.conteneurs);
|
this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires);
|
||||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||||
|
formData.competences.filter(it => it.type == TYPES.competencecreature)
|
||||||
|
.forEach(it => it.isdommages = RdDItemCompetenceCreature.isDommages(it))
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
_appliquerRechercheObjets(objets, conteneurs) {
|
_appliquerRechercheObjets(conteneurs, inventaires) {
|
||||||
if (this.options.recherche?.text) {
|
if (this.options.recherche?.text) {
|
||||||
const recherche = this.options.recherche;
|
const recherche = this.options.recherche;
|
||||||
const allVisible = objets.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id);
|
const allVisible = inventaires.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id);
|
||||||
let addVisible = conteneurs.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id)
|
let addVisible = conteneurs.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id)
|
||||||
do {
|
do {
|
||||||
allVisible.push(...addVisible)
|
allVisible.push(...addVisible)
|
||||||
@@ -67,11 +67,11 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
addVisible = parentsIds.filter(id => !allVisible.includes(id))
|
addVisible = parentsIds.filter(id => !allVisible.includes(id))
|
||||||
}
|
}
|
||||||
while (addVisible.length > 0)
|
while (addVisible.length > 0)
|
||||||
objets.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
inventaires.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
||||||
conteneurs.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
conteneurs.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
objets.forEach(it => it.system.isHidden = false)
|
inventaires.forEach(it => it.system.isHidden = false)
|
||||||
conteneurs.forEach(it => it.system.isHidden = false)
|
conteneurs.forEach(it => it.system.isHidden = false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -118,33 +118,41 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
formData.herbes = Misc.arrayOrEmpty(itemTypes['herbe']);
|
formData.herbes = Misc.arrayOrEmpty(itemTypes['herbe']);
|
||||||
formData.nourritureboissons = Misc.arrayOrEmpty(itemTypes['nourritureboisson']);
|
formData.nourritureboissons = Misc.arrayOrEmpty(itemTypes['nourritureboisson']);
|
||||||
formData.gemmes = Misc.arrayOrEmpty(itemTypes['gemme']);
|
formData.gemmes = Misc.arrayOrEmpty(itemTypes['gemme']);
|
||||||
formData.monnaie = Misc.arrayOrEmpty(itemTypes['monnaie']).sort(Monnaie.triValeurEntiere());
|
formData.monnaies = Misc.arrayOrEmpty(itemTypes['monnaie']).sort(Monnaie.triValeurEntiere());
|
||||||
|
formData.objets = Misc.arrayOrEmpty(itemTypes['objet'])
|
||||||
|
|
||||||
formData.objets = RdDItem.getItemTypesInventaire('all')
|
formData.inventaires = RdDItem.getItemTypesInventaire('all')
|
||||||
.map(t => Misc.arrayOrEmpty(itemTypes[t]))
|
.map(t => Misc.arrayOrEmpty(itemTypes[t]))
|
||||||
.reduce((a, b) => a.concat(b), [])
|
.reduce((a, b) => a.concat(b), [])
|
||||||
.sort(Misc.ascending(it => it.name));
|
.sort(Misc.ascending(it => it.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */ /** @override */
|
/* -------------------------------------------- */ /** @override */
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
this.html = html;
|
this.html = html;
|
||||||
|
|
||||||
this.html.find('.conteneur-name a').click(async event => {
|
if (!this.options.editable) return;
|
||||||
RdDUtility.toggleAfficheContenu(this.getItemId(event));
|
|
||||||
this.render(true);
|
this.html.find('.item-action').click(async event => {
|
||||||
});
|
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||||
this.html.find('.item-edit').click(async event => this.getItem(event)?.sheet.render(true))
|
item?.actionPrincipale(this.actor, async () => this.render())
|
||||||
this.html.find('.item-montrer').click(async event => this.getItem(event)?.postItemToChat());
|
});
|
||||||
this.html.find('.actor-montrer').click(async event => this.actor.postActorToChat());
|
|
||||||
this.html.find('.recherche')
|
this.html.find('.conteneur-name a').click(async event => {
|
||||||
.each((index, field) => {
|
RdDUtility.toggleAfficheContenu(this.getItemId(event));
|
||||||
this._rechercheSelectArea(field);
|
this.render(true);
|
||||||
})
|
});
|
||||||
.keyup(async event => this._rechercherKeyup(event))
|
this.html.find('.item-edit').click(async event => this.getItem(event)?.sheet.render(true))
|
||||||
.change(async event => this._rechercherKeyup(event));
|
this.html.find('.item-montrer').click(async event => this.getItem(event)?.postItemToChat());
|
||||||
this.html.find('.recherche').prop( "disabled", false );
|
this.html.find('.actor-montrer').click(async event => this.actor.postActorToChat());
|
||||||
|
this.html.find('.recherche')
|
||||||
|
.each((index, field) => {
|
||||||
|
this._rechercheSelectArea(field);
|
||||||
|
})
|
||||||
|
.keyup(async event => this._rechercherKeyup(event))
|
||||||
|
.change(async event => this._rechercherKeyup(event));
|
||||||
|
this.html.find('.recherche').prop("disabled", false);
|
||||||
// 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;
|
||||||
|
|
||||||
@@ -163,6 +171,26 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
this.html.find('.nettoyer-conteneurs').click(async event => {
|
this.html.find('.nettoyer-conteneurs').click(async event => {
|
||||||
this.actor.nettoyerConteneurs();
|
this.actor.nettoyerConteneurs();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.html.find('.vue-detaillee').click(async event => {
|
||||||
|
this.options.vueDetaillee = !this.options.vueDetaillee;
|
||||||
|
this.render(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.options.vueDetaillee) {
|
||||||
|
// On carac change
|
||||||
|
this.html.find('.carac-value').change(async event => {
|
||||||
|
let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", "");
|
||||||
|
this.actor.updateCarac(caracName, parseInt(event.target.value));
|
||||||
|
});
|
||||||
|
// On competence change
|
||||||
|
this.html.find('.competence-value').change(async event => {
|
||||||
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
|
//console.log("Competence changed :", compName);
|
||||||
|
this.actor.updateCompetence(compName, parseInt(event.target.value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_rechercherKeyup(event) {
|
_rechercherKeyup(event) {
|
||||||
@@ -230,9 +258,9 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async selectObjetTypeToCreate() {
|
async selectObjetTypeToCreate() {
|
||||||
let typeObjets = this.getTypesInventaire().sort(Misc.ascending(type => Misc.typeName('Item', type)));
|
let types = this.getTypesInventaire().sort(Misc.ascending(type => Misc.typeName('Item', type)));
|
||||||
let content = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
|
let content = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
|
||||||
for (let typeName of typeObjets) {
|
for (let typeName of types) {
|
||||||
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
||||||
}
|
}
|
||||||
content += '</select>';
|
content += '</select>';
|
||||||
|
@@ -1,13 +1,43 @@
|
|||||||
import { ChatUtility } from "../chat-utility.js";
|
import { ChatUtility } from "../chat-utility.js";
|
||||||
import { SYSTEM_SOCKET_ID } from "../constants.js";
|
import { SYSTEM_SOCKET_ID } from "../constants.js";
|
||||||
|
import { Grammar } from "../grammar.js";
|
||||||
import { Monnaie } from "../item-monnaie.js";
|
import { Monnaie } from "../item-monnaie.js";
|
||||||
|
import { TYPES } from "../item.js";
|
||||||
import { Misc } from "../misc.js";
|
import { Misc } from "../misc.js";
|
||||||
import { RdDAudio } from "../rdd-audio.js";
|
import { RdDAudio } from "../rdd-audio.js";
|
||||||
|
import { RdDConfirm } from "../rdd-confirm.js";
|
||||||
import { RdDUtility } from "../rdd-utility.js";
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
import { SystemCompendiums } from "../settings/system-compendiums.js";
|
import { SystemCompendiums } from "../settings/system-compendiums.js";
|
||||||
import { APP_ASTROLOGIE_REFRESH } from "../sommeil/app-astrologie.js";
|
import { APP_ASTROLOGIE_REFRESH } from "../sommeil/app-astrologie.js";
|
||||||
|
|
||||||
export class RdDBaseActor extends Actor {
|
export class RdDBaseActor extends Actor {
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static _findCaracByName(carac, name) {
|
||||||
|
name = Grammar.toLowerCaseNoAccent(name);
|
||||||
|
switch (name) {
|
||||||
|
case 'reve-actuel': case 'reve actuel':
|
||||||
|
return carac.reve;
|
||||||
|
case 'chance-actuelle': case 'chance actuelle':
|
||||||
|
return carac.chance;
|
||||||
|
}
|
||||||
|
|
||||||
|
const caracList = Object.entries(carac);
|
||||||
|
let entry = Misc.findFirstLike(name, caracList, { mapper: it => it[0], description: 'caractéristique' });
|
||||||
|
if (!entry || entry.length == 0) {
|
||||||
|
entry = Misc.findFirstLike(name, caracList, { mapper: it => it[1].label, description: 'caractéristique' });
|
||||||
|
}
|
||||||
|
return entry && entry.length > 0 ? carac[entry[0]] : undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCaracByName(name) {
|
||||||
|
switch (Grammar.toLowerCaseNoAccent(name)) {
|
||||||
|
case 'reve-actuel': case 'reve actuel':
|
||||||
|
return this.getCaracReveActuel();
|
||||||
|
case 'chance-actuelle': case 'chance-actuelle':
|
||||||
|
return this.getCaracChanceActuelle();
|
||||||
|
}
|
||||||
|
return RdDBaseActor._findCaracByName(this.system.carac, name);
|
||||||
|
}
|
||||||
|
|
||||||
static getDefaultImg(itemType) {
|
static getDefaultImg(itemType) {
|
||||||
return game.system.rdd.actorClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
|
return game.system.rdd.actorClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
|
||||||
@@ -49,7 +79,13 @@ export class RdDBaseActor extends Actor {
|
|||||||
|
|
||||||
static onRemoteActorCall(callData, userId) {
|
static onRemoteActorCall(callData, userId) {
|
||||||
if (userId == game.user.id) {
|
if (userId == game.user.id) {
|
||||||
const actor = game.actors.get(callData?.actorId);
|
let actor = game.actors.get(callData?.actorId);
|
||||||
|
if (callData.tokenId) {
|
||||||
|
let token = canvas.tokens.placeables.find(t => t.id == callData.tokenId)
|
||||||
|
if (token) {
|
||||||
|
actor = token.actor
|
||||||
|
}
|
||||||
|
}
|
||||||
if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
|
if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
|
||||||
const args = callData.args;
|
const args = callData.args;
|
||||||
console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')');
|
console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')');
|
||||||
@@ -104,11 +140,39 @@ export class RdDBaseActor extends Actor {
|
|||||||
super(docData, context);
|
super(docData, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
isCreatureEntite() { return this.type == 'creature' || this.type == 'entite'; }
|
/* -------------------------------------------- */
|
||||||
isCreature() { return this.type == 'creature'; }
|
async _preCreate(data, options, user) {
|
||||||
isEntite() { return this.type == 'entite'; }
|
await super._preCreate(data, options, user);
|
||||||
isPersonnage() { return this.type == 'personnage'; }
|
|
||||||
isVehicule() { return this.type == 'vehicule'; }
|
// Configure prototype token settings
|
||||||
|
const prototypeToken = {};
|
||||||
|
if (this.type === "personnage") Object.assign(prototypeToken, {
|
||||||
|
sight: { enabled: true }, actorLink: true, disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY
|
||||||
|
});
|
||||||
|
this.updateSource({ prototypeToken });
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
prepareData() {
|
||||||
|
super.prepareData()
|
||||||
|
this.prepareActorData()
|
||||||
|
this.cleanupConteneurs()
|
||||||
|
this.computeEtatGeneral()
|
||||||
|
this.computeEncTotal()
|
||||||
|
}
|
||||||
|
|
||||||
|
async prepareActorData() { }
|
||||||
|
async computeEtatGeneral() { }
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
findPlayer() {
|
||||||
|
return game.users.players.find(player => player.active && player.character?.id == this.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
isCreatureEntite() { return this.isCreature() || this.isEntite() }
|
||||||
|
isCreature() { return false }
|
||||||
|
isEntite(typeentite = []) { return false }
|
||||||
|
isVehicule() { return false }
|
||||||
|
isPersonnage() { return false }
|
||||||
getItem(id, type = undefined) {
|
getItem(id, type = undefined) {
|
||||||
const item = this.items.get(id);
|
const item = this.items.get(id);
|
||||||
if (type == undefined || (item?.type == type)) {
|
if (type == undefined || (item?.type == type)) {
|
||||||
@@ -118,16 +182,14 @@ export class RdDBaseActor extends Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); }
|
listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); }
|
||||||
filterItems(filter, type = undefined) { return type ? this.itemTypes[type]?.filter(filter) ?? [] : []; }
|
filterItems(filter, type = undefined) { return (type ? this.itemTypes[type] : this.items)?.filter(filter) ?? []; }
|
||||||
findItemLike(idOrName, type) {
|
findItemLike(idOrName, type) {
|
||||||
return this.getItem(idOrName, type)
|
return this.getItem(idOrName, type)
|
||||||
?? Misc.findFirstLike(idOrName, this.listItems(type), { description: Misc.typeName('Item', type) });
|
?? Misc.findFirstLike(idOrName, this.listItems(type), { description: Misc.typeName('Item', type) });
|
||||||
}
|
}
|
||||||
|
|
||||||
getMonnaie(id) { return this.findItemLike(id, 'monnaie'); }
|
getMonnaie(id) { return this.findItemLike(id, 'monnaie'); }
|
||||||
|
getEncombrementMax() { return 0 }
|
||||||
recompute() { }
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onPreUpdateItem(item, change, options, id) { }
|
async onPreUpdateItem(item, change, options, id) { }
|
||||||
@@ -143,6 +205,29 @@ export class RdDBaseActor extends Actor {
|
|||||||
.forEach(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp))
|
.forEach(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async creerObjetParMJ(object) {
|
||||||
|
if (!Misc.isUniqueConnectedGM()) {
|
||||||
|
RdDBaseActor.remoteActorCall({
|
||||||
|
tokenId: this.token?.id,
|
||||||
|
actorId: this.id,
|
||||||
|
method: 'creerObjetParMJ',
|
||||||
|
args: [object]
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await this.createEmbeddedDocuments('Item', [object])
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async cleanupConteneurs() {
|
||||||
|
let updates = this.itemTypes['conteneur']
|
||||||
|
.filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0)
|
||||||
|
.map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } });
|
||||||
|
if (updates.length > 0) {
|
||||||
|
await this.updateEmbeddedDocuments("Item", updates)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getFortune() {
|
getFortune() {
|
||||||
return Monnaie.getFortune(this.itemTypes['monnaie']);
|
return Monnaie.getFortune(this.itemTypes['monnaie']);
|
||||||
@@ -207,6 +292,7 @@ export class RdDBaseActor extends Actor {
|
|||||||
if (fromActorId && !game.user.isGM) {
|
if (fromActorId && !game.user.isGM) {
|
||||||
RdDBaseActor.remoteActorCall({
|
RdDBaseActor.remoteActorCall({
|
||||||
userId: Misc.connectedGMOrUser(),
|
userId: Misc.connectedGMOrUser(),
|
||||||
|
tokenId: this.token?.id,
|
||||||
actorId: this.id,
|
actorId: this.id,
|
||||||
method: 'ajouterSols', args: [sols, fromActorId]
|
method: 'ajouterSols', args: [sols, fromActorId]
|
||||||
});
|
});
|
||||||
@@ -247,13 +333,12 @@ export class RdDBaseActor extends Actor {
|
|||||||
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined;
|
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined;
|
||||||
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined;
|
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined;
|
||||||
const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
|
const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
|
||||||
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id) ?? achat.vente.item;
|
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id);
|
||||||
if (!itemVendu) {
|
if (!itemVendu) {
|
||||||
ui.notifications.warn("Erreur sur achat: rien à acheter<br>Si possible, transmettez les logs de la console aux développeurs");
|
ChatUtility.notifyUser(achat.userId, 'warn', vendeur ? `Le vendeur n'a pas plus de ${achat.vente.item.name} !` : `Impossible de retrouver: ${achat.vente.item.name} !`);
|
||||||
console.log('Erreur sur achat: rien à acheter', achat);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!this.verifierQuantite(vendeur, itemVendu, quantite)) {
|
if (vendeur && !vendeur.verifierQuantite(itemVendu, quantite)) {
|
||||||
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
|
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -264,7 +349,7 @@ export class RdDBaseActor extends Actor {
|
|||||||
await this.decrementerVente(vendeur, itemVendu, quantite, cout);
|
await this.decrementerVente(vendeur, itemVendu, quantite, cout);
|
||||||
if (acheteur) {
|
if (acheteur) {
|
||||||
await acheteur.depenserSols(cout);
|
await acheteur.depenserSols(cout);
|
||||||
const createdItemId = await acheteur.creerQuantiteItem(achat.vente.item, quantite);
|
const createdItemId = await acheteur.creerQuantiteItem(itemVendu, quantite);
|
||||||
await acheteur.consommerNourritureAchetee(achat, achat.vente, createdItemId);
|
await acheteur.consommerNourritureAchetee(achat, achat.vente, createdItemId);
|
||||||
}
|
}
|
||||||
if (cout > 0) {
|
if (cout > 0) {
|
||||||
@@ -305,9 +390,9 @@ export class RdDBaseActor extends Actor {
|
|||||||
return this.getFortune() >= cout;
|
return this.getFortune() >= cout;
|
||||||
}
|
}
|
||||||
|
|
||||||
verifierQuantite(vendeur, item, quantiteTotal) {
|
verifierQuantite(item, quantiteDemande) {
|
||||||
const disponible = vendeur?.getQuantiteDisponible(item);
|
const disponible = this.getQuantiteDisponible(item);
|
||||||
return disponible == undefined || disponible >= quantiteTotal;
|
return disponible == undefined || disponible >= quantiteDemande;
|
||||||
}
|
}
|
||||||
|
|
||||||
async consommerNourritureAchetee(achat, vente, createdItemId) {
|
async consommerNourritureAchetee(achat, vente, createdItemId) {
|
||||||
@@ -355,14 +440,6 @@ export class RdDBaseActor extends Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
computeMalusSurEncombrement() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
getEncombrementMax() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
async computeEncTotal() {
|
async computeEncTotal() {
|
||||||
if (!this.pack) {
|
if (!this.pack) {
|
||||||
this.encTotal = this.items.map(it => it.getEncTotal()).reduce(Misc.sum(), 0);
|
this.encTotal = this.items.map(it => it.getEncTotal()).reduce(Misc.sum(), 0);
|
||||||
@@ -371,6 +448,10 @@ export class RdDBaseActor extends Actor {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getEncTotal() {
|
||||||
|
return Math.floor(this.encTotal ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
async createItem(type, name = undefined) {
|
async createItem(type, name = undefined) {
|
||||||
if (!name) {
|
if (!name) {
|
||||||
name = 'Nouveau ' + Misc.typeName('Item', type);
|
name = 'Nouveau ' + Misc.typeName('Item', type);
|
||||||
@@ -435,62 +516,33 @@ export class RdDBaseActor extends Actor {
|
|||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
conteneurPeutContenir(dest, item) {
|
conteneurPeutContenir(dest, moved) {
|
||||||
if (!dest) {
|
if (!dest) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (!dest.isConteneur()) {
|
if (!dest.isConteneur()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const destData = dest
|
if (moved.isConteneurContenu(dest)) {
|
||||||
if (this._isConteneurContenu(item, dest)) {
|
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${moved.name}) dans un de ses contenus ${dest.name} !`);
|
||||||
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${item.name}) dans un de ses contenus ${destData.name} !`);
|
return false;
|
||||||
return false; // Loop detected !
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculer le total actuel des contenus
|
// Calculer le total actuel des contenus
|
||||||
let encContenu = this.getRecursiveEnc(dest) - Number(destData.system.encombrement);
|
const encContenu = dest.getEncContenu();
|
||||||
let newEnc = this.getRecursiveEnc(item); // Calculer le total actuel du nouvel objet
|
const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet
|
||||||
|
const placeDisponible = Math.roundDecimals(dest.system.capacite - encContenu - newEnc, 4)
|
||||||
|
|
||||||
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
|
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
|
||||||
if (Number(destData.system.capacite) < encContenu + newEnc) {
|
if (placeDisponible < 0) {
|
||||||
ui.notifications.warn(
|
ui.notifications.warn(
|
||||||
`Le conteneur ${dest.name} a une capacité de ${destData.system.capacite}, et contient déjà ${encContenu}.
|
`Le conteneur ${dest.name} a une capacité de ${dest.system.capacite}, et contient déjà ${encContenu}.
|
||||||
Impossible d'y ranger: ${item.name} d'encombrement ${newEnc}!`);
|
Impossible d'y ranger: ${moved.name} d'encombrement ${newEnc}!`);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
_isConteneurContenu(item, conteneur) {
|
|
||||||
if (item?.isConteneur()) { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant
|
|
||||||
for (let id of item.system.contenu) {
|
|
||||||
let subObjet = this.getItem(id);
|
|
||||||
if (subObjet?.id == conteneur.id) {
|
|
||||||
return true; // Loop detected !
|
|
||||||
}
|
|
||||||
if (subObjet?.isConteneur()) {
|
|
||||||
return this._isConteneurContenu(subObjet, conteneur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getRecursiveEnc(objet) {
|
|
||||||
if (!objet) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const tplData = objet.system;
|
|
||||||
if (objet.type != 'conteneur') {
|
|
||||||
return Number(tplData.encombrement) * Number(tplData.quantite);
|
|
||||||
}
|
|
||||||
const encContenus = tplData.contenu.map(idContenu => this.getRecursiveEnc(this.getItem(idContenu)));
|
|
||||||
return encContenus.reduce(Misc.sum(), 0)
|
|
||||||
+ Number(tplData.encombrement) /* TODO? Number(tplData.quantite) -- on pourrait avoir plusieurs conteneurs...*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/** Ajoute un item dans un conteneur, sur la base
|
/** Ajoute un item dans un conteneur, sur la base
|
||||||
* de leurs ID */
|
* de leurs ID */
|
||||||
@@ -628,5 +680,20 @@ export class RdDBaseActor extends Actor {
|
|||||||
.then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
|
.then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
actionImpossible(action) {
|
||||||
|
ui.notifications.info(`${this.name} ne peut pas faire cette action: ${action}`)
|
||||||
|
|
||||||
|
}
|
||||||
|
async roll() { this.actionImpossible("jet de caractéristiques") }
|
||||||
|
async jetEthylisme() { this.actionImpossible("jet d'éthylisme") }
|
||||||
|
async rollAppelChance() { this.actionImpossible("appel à la chance") }
|
||||||
|
async jetDeMoral() { this.actionImpossible("jet de moral") }
|
||||||
|
|
||||||
|
async actionPrincipale(item, onActionItem = async () => { }) {
|
||||||
|
switch (item.type) {
|
||||||
|
case TYPES.conteneur: return await item.sheet.render(true);
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -1,9 +1,7 @@
|
|||||||
import { DialogItemAchat } from "../dialog-item-achat.js";
|
import { DialogItemAchat } from "../dialog-item-achat.js";
|
||||||
import { RdDItem } from "../item.js";
|
import { RdDItem } from "../item.js";
|
||||||
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
|
|
||||||
import { RdDUtility } from "../rdd-utility.js";
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
import { RdDBaseActorSheet } from "./base-actor-sheet.js";
|
import { RdDBaseActorSheet } from "./base-actor-sheet.js";
|
||||||
import { RdDCommerce } from "./commerce.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the basic ActorSheet with some very simple modifications
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
@@ -14,12 +12,9 @@ export class RdDCommerceSheet extends RdDBaseActorSheet {
|
|||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
return mergeObject(super.defaultOptions, {
|
return mergeObject(super.defaultOptions, {
|
||||||
classes: ["rdd", "sheet", "actor"],
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.html",
|
template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.html",
|
||||||
width: 600,
|
width: 600, height: 720,
|
||||||
height: 720,
|
tabs: []
|
||||||
tabs: [],
|
|
||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
get title() {
|
get title() {
|
||||||
|
@@ -7,27 +7,18 @@ export class RdDCommerce extends RdDBaseActor {
|
|||||||
return "systems/foundryvtt-reve-de-dragon/icons/services/commerce.webp";
|
return "systems/foundryvtt-reve-de-dragon/icons/services/commerce.webp";
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareData() {
|
|
||||||
super.prepareData();
|
|
||||||
}
|
|
||||||
prepareDerivedData() {
|
|
||||||
super.prepareDerivedData();
|
|
||||||
}
|
|
||||||
|
|
||||||
canReceive(item) {
|
canReceive(item) {
|
||||||
if (item.isInventaire('all')) {
|
return item.isInventaire('all');
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.canReceive(item);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getQuantiteDisponible(item) {
|
getQuantiteDisponible(item) {
|
||||||
return this.system.illimite || item.isService() ? undefined : item.getQuantite();
|
return (this.system.illimite || item?.isService()) ? undefined : item.getQuantite();
|
||||||
}
|
}
|
||||||
|
|
||||||
verifierFortune(cout) {
|
verifierFortune(cout) {
|
||||||
return this.system.illimite || super.verifierFortune(cout);
|
return this.system.illimite || super.verifierFortune(cout);
|
||||||
}
|
}
|
||||||
|
|
||||||
async depenserSols(cout) {
|
async depenserSols(cout) {
|
||||||
if (this.system.illimite) {
|
if (this.system.illimite) {
|
||||||
return
|
return
|
||||||
|
@@ -1,20 +1,16 @@
|
|||||||
import { RdDActorSheet } from "./actor-sheet.js";
|
import { RdDBaseActorReveSheet } from "./base-actor-reve-sheet.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the basic ActorSheet with some very simple modifications
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
* @extends {ActorSheet}
|
* @extends {ActorSheet}
|
||||||
*/
|
*/
|
||||||
export class RdDActorCreatureSheet extends RdDActorSheet {
|
export class RdDCreatureSheet extends RdDBaseActorReveSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
return mergeObject(super.defaultOptions, {
|
return mergeObject(RdDBaseActorReveSheet.defaultOptions, {
|
||||||
classes: ["rdd", "sheet", "actor"],
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html",
|
template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html",
|
||||||
width: 640,
|
width: 640, height: 720
|
||||||
height: 720,
|
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
|
||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
65
module/actor/creature.js
Normal file
65
module/actor/creature.js
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { ENTITE_INCARNE } from "../constants.js";
|
||||||
|
import { STATUSES } from "../settings/status-effects.js";
|
||||||
|
import { RdDBaseActorSang } from "./base-actor-sang.js";
|
||||||
|
|
||||||
|
export class RdDCreature extends RdDBaseActorSang {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/creatures/bramart.svg";
|
||||||
|
}
|
||||||
|
|
||||||
|
isCreature() { return true }
|
||||||
|
|
||||||
|
canReceive(item) {
|
||||||
|
return item.type == TYPES.competencecreature || item.isInventaire();
|
||||||
|
}
|
||||||
|
|
||||||
|
async remiseANeuf() {
|
||||||
|
await this.removeEffects(e => true);
|
||||||
|
await this.supprimerBlessures(it => true);
|
||||||
|
const updates = {
|
||||||
|
'system.sante.endurance.value': this.system.sante.endurance.max,
|
||||||
|
'system.sante.vie.value': this.system.sante.vie.max,
|
||||||
|
'system.sante.fatigue.value': 0
|
||||||
|
};
|
||||||
|
await this.update(updates);
|
||||||
|
}
|
||||||
|
|
||||||
|
async finDeRoundBlessures() {
|
||||||
|
const nbGraves = this.filterItems(it => it.isGrave(), 'blessure').length;
|
||||||
|
if (nbGraves > 0) {
|
||||||
|
// Gestion blessure graves : -1 pt endurance par blessure grave
|
||||||
|
await this.santeIncDec("endurance", -nbGraves);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isEffectAllowed(statusId) {
|
||||||
|
return [STATUSES.StatusComma].includes(statusId);
|
||||||
|
}
|
||||||
|
|
||||||
|
isEntiteAccordee(attacker) {
|
||||||
|
if (this.isEntite([ENTITE_INCARNE])) {
|
||||||
|
let resonnance = this.system.sante.resonnance
|
||||||
|
return (resonnance.actors.find(it => it == attacker.id))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async setEntiteReveAccordee(attacker) {
|
||||||
|
if (this.isEntite([ENTITE_INCARNE])) {
|
||||||
|
let resonnance = duplicate(this.system.sante.resonnance);
|
||||||
|
if (resonnance.actors.find(it => it == attacker.id)) {
|
||||||
|
// déjà accordé
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resonnance.actors.push(attacker.id);
|
||||||
|
await this.update({ "system.sante.resonnance": resonnance });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.setEntiteReveAccordee(attacker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -1,20 +1,17 @@
|
|||||||
import { RdDActorSheet } from "./actor-sheet.js";
|
import { RdDBaseActorReveSheet } from "./base-actor-reve-sheet.js";
|
||||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
|
|
||||||
export class RdDActorEntiteSheet extends RdDActorSheet {
|
export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
return mergeObject(super.defaultOptions, {
|
return mergeObject(RdDBaseActorReveSheet.defaultOptions, {
|
||||||
classes: ["rdd", "sheet", "actor"],
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html",
|
template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html",
|
||||||
width: 640,
|
width: 640, height: 720,
|
||||||
height: 720,
|
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
|
||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async getData() {
|
async getData() {
|
||||||
let formData = await super.getData();
|
let formData = await super.getData();
|
||||||
formData.resonances = this.actor.system.sante.resonnance.actors.map(actorId => game.actors.get(actorId))
|
formData.resonances = this.actor.system.sante.resonnance.actors.map(actorId => game.actors.get(actorId))
|
110
module/actor/entite.js
Normal file
110
module/actor/entite.js
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
|
||||||
|
import { TYPES } from "../item.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { RdDEncaisser } from "../rdd-roll-encaisser.js";
|
||||||
|
import { STATUSES } from "../settings/status-effects.js";
|
||||||
|
import { RdDBaseActorReve } from "./base-actor-reve.js";
|
||||||
|
|
||||||
|
export class RdDEntite extends RdDBaseActorReve {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/entites/darquoine.webp";
|
||||||
|
}
|
||||||
|
|
||||||
|
canReceive(item) {
|
||||||
|
return item.type == TYPES.competencecreature
|
||||||
|
}
|
||||||
|
|
||||||
|
isEntite(typeentite = []) {
|
||||||
|
return (typeentite.length == 0 || typeentite.includes(this.system.definition.typeentite));
|
||||||
|
}
|
||||||
|
isNonIncarnee() { return this.isEntite([ENTITE_NONINCARNE]) }
|
||||||
|
|
||||||
|
getReveActuel() {
|
||||||
|
return Misc.toInt(this.system.carac.reve?.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
getForce() { return this.getReve() }
|
||||||
|
getAgilite() { return this.getReve() }
|
||||||
|
getChance() { return this.getReve() }
|
||||||
|
|
||||||
|
getDraconicOuPossession() {
|
||||||
|
return this.itemTypes[TYPES.competencecreature]
|
||||||
|
.filter(it => it.system.categorie == 'possession')
|
||||||
|
.sort(Misc.descending(it => it.system.niveau))
|
||||||
|
.find(it => true);
|
||||||
|
}
|
||||||
|
|
||||||
|
async remiseANeuf() {
|
||||||
|
await this.removeEffects(e => true);
|
||||||
|
if (!this.isNonIncarnee()) {
|
||||||
|
await this.update({
|
||||||
|
'system.sante.endurance.value': this.system.sante.endurance.max
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
isDead() {
|
||||||
|
return this.isNonIncarnee() ? false : this.system.sante.endurance.value <= 0
|
||||||
|
}
|
||||||
|
|
||||||
|
async santeIncDec(name, inc, isCritique = false) {
|
||||||
|
if (name == 'endurance' && !this.isNonIncarnee()) {
|
||||||
|
const oldValue = this.system.sante.endurance.value;
|
||||||
|
const endurance = Math.max(0,
|
||||||
|
Math.min(oldValue + inc,
|
||||||
|
this.system.sante.endurance.max));
|
||||||
|
await this.update({ "system.sante.endurance.value": endurance })
|
||||||
|
await this.setEffect(STATUSES.StatusComma, endurance <= 0);
|
||||||
|
return {
|
||||||
|
perte: oldValue - endurance,
|
||||||
|
newValue: endurance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
async encaisser() {
|
||||||
|
if (this.isNonIncarnee()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await RdDEncaisser.encaisser(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
isEffectAllowed(statusId) {
|
||||||
|
return [STATUSES.StatusComma].includes(statusId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onAppliquerJetEncaissement(encaissement, attacker) {
|
||||||
|
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance);
|
||||||
|
mergeObject(encaissement, {
|
||||||
|
resteEndurance: perteEndurance.newValue,
|
||||||
|
endurance: perteEndurance.perte
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isEntiteAccordee(attacker) {
|
||||||
|
if (this.isEntite([ENTITE_INCARNE])) {
|
||||||
|
let resonnance = this.system.sante.resonnance
|
||||||
|
return (resonnance.actors.find(it => it == attacker.id))
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async setEntiteReveAccordee(attacker) {
|
||||||
|
if (this.isEntite([ENTITE_INCARNE])) {
|
||||||
|
let resonnance = duplicate(this.system.sante.resonnance);
|
||||||
|
if (resonnance.actors.find(it => it == attacker.id)) {
|
||||||
|
// déjà accordé
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
resonnance.actors.push(attacker.id);
|
||||||
|
await this.update({ "system.sante.resonnance": resonnance });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
super.setEntiteReveAccordee(attacker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@@ -1,23 +1,35 @@
|
|||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
import { RdDActorSheet } from "./actor-sheet.js";
|
import { RdDBaseActorSheet } from "./base-actor-sheet.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDActorVehiculeSheet extends RdDActorSheet {
|
export class RdDActorVehiculeSheet extends RdDBaseActorSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
RdDUtility.initAfficheContenu();
|
RdDUtility.initAfficheContenu();
|
||||||
|
|
||||||
return mergeObject(super.defaultOptions, {
|
return mergeObject(RdDBaseActorSheet.defaultOptions, {
|
||||||
classes: ["rdd", "sheet", "actor"],
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html",
|
template: "systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html",
|
||||||
width: 640,
|
width: 640, height: 720,
|
||||||
height: 720,
|
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
|
||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async getData() {
|
||||||
|
let formData = await super.getData();
|
||||||
|
mergeObject(formData,
|
||||||
|
{
|
||||||
|
editable: this.isEditable,
|
||||||
|
cssClass: this.isEditable ? "editable" : "locked",
|
||||||
|
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
|
||||||
|
limited: this.actor.limited,
|
||||||
|
owner: this.actor.isOwner,
|
||||||
|
});
|
||||||
|
|
||||||
|
this.timerRecherche = undefined;
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
28
module/actor/vehicule.js
Normal file
28
module/actor/vehicule.js
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { RdDBaseActor } from "./base-actor.js";
|
||||||
|
|
||||||
|
export class RdDVehicule extends RdDBaseActor {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/vehicules/charette.webp";
|
||||||
|
}
|
||||||
|
isVehicule() { return true }
|
||||||
|
|
||||||
|
canReceive(item) {
|
||||||
|
return item.isInventaire();
|
||||||
|
}
|
||||||
|
|
||||||
|
getEncombrementMax() {
|
||||||
|
return this.system.capacite_encombrement;
|
||||||
|
}
|
||||||
|
|
||||||
|
async vehicleIncDec(name, inc) {
|
||||||
|
if (!['resistance', 'structure'].includes(name)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const newValue = this.system.etat[name].value + inc;
|
||||||
|
if (0 <= newValue && newValue <= this.system.etat[name].max) {
|
||||||
|
await this.update({ [`system.etat.${name}.value`]: newValue })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -78,11 +78,7 @@ export class ChatUtility {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async createChatWithRollMode(name, chatOptions) {
|
static async createChatWithRollMode(name, chatOptions) {
|
||||||
return await ChatUtility.createChatMessage(name, game.settings.get("core", "rollMode"), chatOptions);
|
let rollMode = game.settings.get("core", "rollMode")
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async createChatMessage(name, rollMode, chatOptions) {
|
|
||||||
switch (rollMode) {
|
switch (rollMode) {
|
||||||
case "blindroll": // GM only
|
case "blindroll": // GM only
|
||||||
if (!game.user.isGM) {
|
if (!game.user.isGM) {
|
||||||
|
@@ -114,7 +114,7 @@ export class DialogChronologie extends Dialog {
|
|||||||
heure: RdDTimestamp.definition(this.html.find("form.rdddialogchrono :input[name='chronologie.heure']").val()),
|
heure: RdDTimestamp.definition(this.html.find("form.rdddialogchrono :input[name='chronologie.heure']").val()),
|
||||||
minute: this.html.find("form.rdddialogchrono :input[name='chronologie.minute']").val(),
|
minute: this.html.find("form.rdddialogchrono :input[name='chronologie.minute']").val(),
|
||||||
},
|
},
|
||||||
dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val()
|
dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val().replace('T', ' ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -14,7 +14,7 @@ export class DialogCreateSigneDraconique extends Dialog {
|
|||||||
.map(actor => ({
|
.map(actor => ({
|
||||||
id: actor.id,
|
id: actor.id,
|
||||||
name: actor.name,
|
name: actor.name,
|
||||||
selected: true
|
selected: false
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ export class DialogCreateSigneDraconique extends Dialog {
|
|||||||
|
|
||||||
onSelectTmr(event) {
|
onSelectTmr(event) {
|
||||||
const tmrName = this.html.find(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.dialogData.tmrs.find(it => it.name == tmrName);
|
||||||
if (onTmr){
|
if (onTmr){
|
||||||
onTmr.selected = event.currentTarget.checked;
|
onTmr.selected = event.currentTarget.checked;
|
||||||
}
|
}
|
||||||
|
@@ -7,20 +7,19 @@ import { RdDUtility } from "./rdd-utility.js";
|
|||||||
*/
|
*/
|
||||||
export class DialogValidationEncaissement extends Dialog {
|
export class DialogValidationEncaissement extends Dialog {
|
||||||
|
|
||||||
static async validerEncaissement(actor, rollData, armure, show, onEncaisser) {
|
static async validerEncaissement(actor, rollData, armure, onEncaisser) {
|
||||||
let encaissement = await RdDUtility.jetEncaissement(rollData, armure, { showDice: HIDE_DICE });
|
let encaissement = await RdDUtility.jetEncaissement(rollData, armure, { showDice: HIDE_DICE });
|
||||||
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', {
|
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', {
|
||||||
actor: actor,
|
actor: actor,
|
||||||
rollData: rollData,
|
rollData: rollData,
|
||||||
encaissement: encaissement,
|
encaissement: encaissement
|
||||||
show: show
|
|
||||||
});
|
});
|
||||||
const dialog = new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, show, onEncaisser);
|
const dialog = new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, onEncaisser);
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(html, actor, rollData, armure, encaissement, show, onEncaisser) {
|
constructor(html, actor, rollData, armure, encaissement, onEncaisser) {
|
||||||
// Common conf
|
// Common conf
|
||||||
let buttons = {
|
let buttons = {
|
||||||
"valider": { label: "Valider", callback: html => this.onValider() },
|
"valider": { label: "Valider", callback: html => this.onValider() },
|
||||||
@@ -47,7 +46,6 @@ export class DialogValidationEncaissement extends Dialog {
|
|||||||
this.rollData = rollData;
|
this.rollData = rollData;
|
||||||
this.armure = armure;
|
this.armure = armure;
|
||||||
this.encaissement = encaissement;
|
this.encaissement = encaissement;
|
||||||
this.show = show;
|
|
||||||
this.onEncaisser = onEncaisser;
|
this.onEncaisser = onEncaisser;
|
||||||
this.forceDiceResult = {total: encaissement.roll.result };
|
this.forceDiceResult = {total: encaissement.roll.result };
|
||||||
}
|
}
|
||||||
@@ -66,6 +64,6 @@ export class DialogValidationEncaissement extends Dialog {
|
|||||||
|
|
||||||
async onValider() {
|
async onValider() {
|
||||||
this.encaissement = await RdDUtility.jetEncaissement(this.rollData, this.armure, { showDice: SHOW_DICE, forceDiceResult: this.forceDiceResult});
|
this.encaissement = await RdDUtility.jetEncaissement(this.rollData, this.armure, { showDice: SHOW_DICE, forceDiceResult: this.forceDiceResult});
|
||||||
this.onEncaisser(this.encaissement, this.show)
|
this.onEncaisser(this.encaissement)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
|
||||||
|
import { TYPES } from "./item.js";
|
||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
import { RdDCombatManager } from "./rdd-combat.js";
|
||||||
|
|
||||||
const nomCategorieParade = {
|
const nomCategorieParade = {
|
||||||
@@ -19,15 +20,15 @@ const nomCategorieParade = {
|
|||||||
export class RdDItemArme extends Item {
|
export class RdDItemArme extends Item {
|
||||||
|
|
||||||
static isArme(item) {
|
static isArme(item) {
|
||||||
return (item.type == 'competencecreature' && item.system.iscombat) || item.type == 'arme';
|
return item.type == TYPES.arme || RdDItemCompetenceCreature.getCategorieAttaque(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getArme(arme) {
|
static getArme(arme) {
|
||||||
switch (arme ? arme.type : '') {
|
switch (arme ? arme.type : '') {
|
||||||
case 'arme': return arme;
|
case TYPES.arme: return arme;
|
||||||
case 'competencecreature':
|
case TYPES.competencecreature:
|
||||||
return RdDItemCompetenceCreature.armeNaturelle(arme);
|
return RdDItemCompetenceCreature.armeCreature(arme);
|
||||||
}
|
}
|
||||||
return RdDItemArme.mainsNues();
|
return RdDItemArme.mainsNues();
|
||||||
}
|
}
|
||||||
@@ -67,14 +68,14 @@ export class RdDItemArme extends Item {
|
|||||||
return armeData.system.categorie_parade;
|
return armeData.system.categorie_parade;
|
||||||
}
|
}
|
||||||
// pour compatibilité avec des personnages existants
|
// pour compatibilité avec des personnages existants
|
||||||
if (armeData.type == 'competencecreature' || armeData.system.categorie == 'creature') {
|
if (armeData.type == TYPES.competencecreature || armeData.system.categorie == 'creature') {
|
||||||
return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '');
|
return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '');
|
||||||
}
|
}
|
||||||
if (!armeData.type.match(/arme|competencecreature/)) {
|
if (!armeData.type.match(/arme|competencecreature/)) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
if (armeData.system.competence == undefined) {
|
if (armeData.system.competence == undefined) {
|
||||||
return 'competencecreature';
|
return TYPES.competencecreature;
|
||||||
}
|
}
|
||||||
let compname = armeData.system.competence.toLowerCase();
|
let compname = armeData.system.competence.toLowerCase();
|
||||||
if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return '';
|
if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return '';
|
||||||
@@ -156,23 +157,33 @@ export class RdDItemArme extends Item {
|
|||||||
}
|
}
|
||||||
return armeData;
|
return armeData;
|
||||||
}
|
}
|
||||||
|
static competence2Mains(arme) {
|
||||||
|
return arme.system.competence.replace(" 1 main", " 2 mains");
|
||||||
|
}
|
||||||
|
|
||||||
|
static competence1Mains(arme) {
|
||||||
|
return arme.system.competence.replace(" 2 mains", " 1 main");
|
||||||
|
}
|
||||||
|
|
||||||
static isArmeUtilisable(arme) {
|
static isArmeUtilisable(arme) {
|
||||||
return arme.type == 'arme' && arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0);
|
return arme.type == 'arme' && arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static ajoutCorpsACorps(armes, competences, carac) {
|
static ajoutCorpsACorps(armes, actor) {
|
||||||
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { system: { niveau: -6 } };
|
armes.push(RdDItemArme.mainsNues(actor));
|
||||||
let init = RdDCombatManager.calculInitiative(corpsACorps.system.niveau, carac['melee'].value);
|
armes.push(RdDItemArme.empoignade(actor));
|
||||||
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.system.niveau, initiative: init }));
|
|
||||||
armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.system.niveau, initiative: init }));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static corpsACorps(mainsNuesActor) {
|
static corpsACorps(actor) {
|
||||||
const corpsACorps = {
|
let competence = actor?.getCompetenceCorpsACorps() ?? { system: { niveau: -6 } };
|
||||||
|
let melee = actor? actor.system.carac['melee'].value : 0
|
||||||
|
return {
|
||||||
|
_id: competence?.id,
|
||||||
name: 'Corps à corps',
|
name: 'Corps à corps',
|
||||||
|
type: TYPES.arme,
|
||||||
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp',
|
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp',
|
||||||
system: {
|
system: {
|
||||||
|
initiative: RdDCombatManager.calculInitiative(competence.system.niveau, melee),
|
||||||
equipe: true,
|
equipe: true,
|
||||||
rapide: true,
|
rapide: true,
|
||||||
force: 0,
|
force: 0,
|
||||||
@@ -180,23 +191,22 @@ export class RdDItemArme extends Item {
|
|||||||
dommagesReels: 0,
|
dommagesReels: 0,
|
||||||
mortalite: 'non-mortel',
|
mortalite: 'non-mortel',
|
||||||
competence: 'Corps à corps',
|
competence: 'Corps à corps',
|
||||||
|
deuxmains: true,
|
||||||
categorie_parade: 'sans-armes'
|
categorie_parade: 'sans-armes'
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
mergeObject(corpsACorps.system, mainsNuesActor ?? {}, { overwrite: false });
|
|
||||||
return corpsACorps;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static mainsNues(mainsNuesActor) {
|
static mainsNues(actor) {
|
||||||
const mainsNues = RdDItemArme.corpsACorps(mainsNuesActor)
|
const mainsNues = RdDItemArme.corpsACorps(actor)
|
||||||
mainsNues.name = 'Mains nues'
|
mainsNues.name = 'Mains nues'
|
||||||
mainsNues.system.cac = 'pugilat'
|
mainsNues.system.cac = 'pugilat'
|
||||||
mainsNues.system.baseInit = 4
|
mainsNues.system.baseInit = 4
|
||||||
return mainsNues;
|
return mainsNues;
|
||||||
}
|
}
|
||||||
|
|
||||||
static empoignade(mainsNuesActor) {
|
static empoignade(actor) {
|
||||||
const empoignade = RdDItemArme.corpsACorps(mainsNuesActor)
|
const empoignade = RdDItemArme.corpsACorps(actor)
|
||||||
empoignade.name = 'Empoignade'
|
empoignade.name = 'Empoignade'
|
||||||
empoignade.system.cac = 'empoignade'
|
empoignade.system.cac = 'empoignade'
|
||||||
empoignade.system.baseInit = 3
|
empoignade.system.baseInit = 3
|
||||||
|
@@ -8,22 +8,22 @@ 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, "reste": 100 },
|
{ niveau: 0, nombreMax: 100 },
|
||||||
{ "niveau": 1, "nombreMax": 10, "reste": 10 },
|
{ niveau: 1, nombreMax: 10 },
|
||||||
{ "niveau": 2, "nombreMax": 9, "reste": 9 },
|
{ niveau: 2, nombreMax: 9 },
|
||||||
{ "niveau": 3, "nombreMax": 8, "reste": 8 },
|
{ niveau: 3, nombreMax: 8 },
|
||||||
{ "niveau": 4, "nombreMax": 7, "reste": 7 },
|
{ niveau: 4, nombreMax: 7 },
|
||||||
{ "niveau": 5, "nombreMax": 6, "reste": 6 },
|
{ niveau: 5, nombreMax: 6 },
|
||||||
{ "niveau": 6, "nombreMax": 5, "reste": 5 },
|
{ niveau: 6, nombreMax: 5 },
|
||||||
{ "niveau": 7, "nombreMax": 4, "reste": 4 },
|
{ niveau: 7, nombreMax: 4 },
|
||||||
{ "niveau": 8, "nombreMax": 3, "reste": 3 },
|
{ niveau: 8, nombreMax: 3 },
|
||||||
{ "niveau": 9, "nombreMax": 2, "reste": 2 },
|
{ niveau: 9, nombreMax: 2 },
|
||||||
{ "niveau": 10, "nombreMax": 1, "reste": 1 },
|
{ niveau: 10, nombreMax: 1 },
|
||||||
{ "niveau": 11, "nombreMax": 1, "reste": 1 }
|
{ niveau: 11, nombreMax: 1 },
|
||||||
];
|
];
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const categorieCompetences = {
|
const categoriesCompetences = {
|
||||||
"generale": { base: -4, label: "Générales" },
|
"generale": { base: -4, label: "Générales" },
|
||||||
"particuliere": { base: -8, label: "Particulières" },
|
"particuliere": { base: -8, label: "Particulières" },
|
||||||
"specialisee": { base: -11, label: "Spécialisées" },
|
"specialisee": { base: -11, label: "Spécialisées" },
|
||||||
@@ -49,16 +49,16 @@ const competence_xp_cumul = _buildCumulXP();
|
|||||||
|
|
||||||
export class RdDItemCompetence extends Item {
|
export class RdDItemCompetence extends Item {
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getCategorieCompetences() {
|
static getCategories() {
|
||||||
return categorieCompetences;
|
return categoriesCompetences;
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static getNiveauBase(category) {
|
|
||||||
return categorieCompetences[category].base;
|
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getLabelCategorie(category) {
|
static getLabelCategorie(category) {
|
||||||
return categorieCompetences[category].label;
|
return categoriesCompetences[category].label;
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static getNiveauBase(category, categories = categoriesCompetences) {
|
||||||
|
return categories[category]?.base ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -79,10 +79,9 @@ export class RdDItemCompetence extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isCompetenceArme(competence) {
|
static isCompetenceArme(competence) {
|
||||||
if (competence.isCompetence()) {
|
if (competence.isCompetence() && !competence.isCorpsACorps() && !competence.isEsquive()) {
|
||||||
switch (competence.system.categorie) {
|
switch (competence.system.categorie) {
|
||||||
case 'melee':
|
case 'melee':
|
||||||
return !Grammar.toLowerCaseNoAccent(competence.name).includes('esquive');
|
|
||||||
case 'tir':
|
case 'tir':
|
||||||
case 'lancer':
|
case 'lancer':
|
||||||
return true;
|
return true;
|
||||||
@@ -93,10 +92,10 @@ export class RdDItemCompetence extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isArmeUneMain(competence) {
|
static isArmeUneMain(competence) {
|
||||||
return RdDItemCompetence.isCompetenceArme(competence) && competence.name.toLowerCase().includes("1 main");
|
return competence.isCompetenceArme() && competence.name.toLowerCase().includes("1 main");
|
||||||
}
|
}
|
||||||
static isArme2Main(competence) {
|
static isArme2Main(competence) {
|
||||||
return RdDItemCompetence.isCompetenceArme(competence) && competence.name.toLowerCase().includes("2 main");
|
return competence.isCompetenceArme() && competence.name.toLowerCase().includes("2 main");
|
||||||
}
|
}
|
||||||
|
|
||||||
static isThanatos(competence) {
|
static isThanatos(competence) {
|
||||||
@@ -192,7 +191,7 @@ export class RdDItemCompetence extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isNiveauBase(item) {
|
static isNiveauBase(item) {
|
||||||
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie);
|
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie, item.getCategories());
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -259,13 +258,17 @@ export class RdDItemCompetence extends Item {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static computeResumeArchetype(competences) {
|
static computeResumeArchetype(competences) {
|
||||||
const computed = duplicate(limitesArchetypes);
|
const computed = duplicate(limitesArchetypes);
|
||||||
|
computed.forEach(it => { it.nombre = 0; it.reste = it.nombreMax; });
|
||||||
|
|
||||||
competences.map(it => Math.max(0, it.system.niveau_archetype))
|
competences.map(it => Math.max(0, it.system.niveau_archetype))
|
||||||
.filter(n => n > 0)
|
.filter(n => n > 0)
|
||||||
.forEach(n => {
|
.forEach(n => {
|
||||||
computed[n] = computed[n] ?? { niveau: n, nombreMax: 0, reste: 0 };
|
computed[n] = computed[n] ?? { niveau: n, nombreMax: 0, reste: 0, nombre: 0 };
|
||||||
computed[n].reste = computed[n].reste - 1;
|
computed[n].reste--;
|
||||||
|
computed[n].nombre++;
|
||||||
|
|
||||||
});
|
});
|
||||||
return computed.filter(it => it.reste > 0 && it.niveau > 0);
|
return computed.filter(it => it.niveau > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@@ -1,49 +1,110 @@
|
|||||||
|
|
||||||
|
import { TYPES } from "./item.js";
|
||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
import { RdDCombatManager } from "./rdd-combat.js";
|
||||||
|
|
||||||
|
const categories = {
|
||||||
|
"generale": { base: 0, label: "Générale" },
|
||||||
|
"naturelle": { base: 0, label: "Arme naturelle" },
|
||||||
|
"melee": { base: 0, label: "Mêlée" },
|
||||||
|
"parade": { base: 0, label: "Parade" },
|
||||||
|
"tir": { base: 0, label: "Tir" },
|
||||||
|
"lancer": { base: 0, label: "Lancer" },
|
||||||
|
"possession": { base: 0, label: "Possession" },
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDItemCompetenceCreature extends Item {
|
export class RdDItemCompetenceCreature extends Item {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
static getCategories() {
|
||||||
static setRollDataCreature(rollData) {
|
return categories;
|
||||||
rollData.competence = rollData.competence
|
|
||||||
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } }
|
|
||||||
rollData.competence.system.defaut_carac = "carac_creature"
|
|
||||||
rollData.competence.system.categorie = "creature"
|
|
||||||
rollData.selectedCarac = rollData.carac.carac_creature
|
|
||||||
if (rollData.competence.system.iscombat) {
|
|
||||||
rollData.arme = RdDItemCompetenceCreature.armeNaturelle(rollData.competence);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static armeNaturelle(competencecreature) {
|
static setRollDataCreature(rollData) {
|
||||||
if (RdDItemCompetenceCreature.isCompetenceAttaque(competencecreature)) {
|
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } }
|
||||||
// si c'est un Item compétence: cloner pour ne pas modifier lma compétence
|
rollData.competence.system.defaut_carac = "carac_creature"
|
||||||
let arme = (competencecreature instanceof Item) ? competencecreature.clone(): competencecreature;
|
rollData.selectedCarac = rollData.carac.carac_creature
|
||||||
mergeObject(arme.system,
|
rollData.arme = RdDItemCompetenceCreature.armeCreature(rollData.competence);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static armeCreature(item) {
|
||||||
|
const categorieAttaque = RdDItemCompetenceCreature.getCategorieAttaque(item)
|
||||||
|
if (categorieAttaque != undefined) {
|
||||||
|
// si c'est un Item compétence: cloner pour ne pas modifier la compétence
|
||||||
|
let arme = item.clone();
|
||||||
|
mergeObject(arme,
|
||||||
{
|
{
|
||||||
competence: arme.name,
|
action: item.isCompetencePossession() ? 'possession' : 'attaque',
|
||||||
initiative: RdDCombatManager.calculInitiative(competencecreature.system.niveau, competencecreature.system.carac_value),
|
system: {
|
||||||
niveau: competencecreature.system.niveau,
|
competence: arme.name,
|
||||||
equipe: true,
|
cac: categorieAttaque == "naturelle" ? "naturelle" : "",
|
||||||
resistance: 100,
|
niveau: item.system.niveau,
|
||||||
dommagesReels: arme.system.dommages,
|
initiative: RdDCombatManager.calculInitiative(item.system.niveau, item.system.carac_value),
|
||||||
penetration: 0,
|
equipe: true,
|
||||||
force: 0,
|
resistance: 100,
|
||||||
rapide: true,
|
dommagesReels: arme.system.dommages,
|
||||||
cac: competencecreature.system.isnaturelle ? "naturelle" : "",
|
penetration: 0,
|
||||||
action: 'attaque'
|
force: 0,
|
||||||
|
rapide: true,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return arme;
|
return arme;
|
||||||
}
|
}
|
||||||
console.error("RdDItemCompetenceCreature.toActionArme(", competencecreature, ") : impossible de transformer l'Item en arme");
|
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isCompetenceAttaque(item) {
|
static isCompetenceAttaque(item) {
|
||||||
return item.type == 'competencecreature' && item.system.iscombat;
|
if (item.type == TYPES.competencecreature) {
|
||||||
|
switch (item.system.categorie) {
|
||||||
|
case "melee":
|
||||||
|
case "tir":
|
||||||
|
case "lancer":
|
||||||
|
case "naturelle":
|
||||||
|
case "possession":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
static getCategorieAttaque(item) {
|
||||||
|
if (item.type == TYPES.competencecreature) {
|
||||||
|
switch (item.system.categorie) {
|
||||||
|
case "melee":
|
||||||
|
case "tir":
|
||||||
|
case "lancer":
|
||||||
|
case "naturelle":
|
||||||
|
case "possession":
|
||||||
|
case "parade":
|
||||||
|
return item.system.categorie
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
static isDommages(item) {
|
||||||
|
if (item.type == TYPES.competencecreature) {
|
||||||
|
switch (item.system.categorie) {
|
||||||
|
case "melee":
|
||||||
|
case "tir":
|
||||||
|
case "lancer":
|
||||||
|
case "naturelle":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
static isParade(item) {
|
||||||
|
if (item.type == TYPES.competencecreature) {
|
||||||
|
switch (item.system.categorie) {
|
||||||
|
case "melee":
|
||||||
|
case "naturelle":
|
||||||
|
case "parade":
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@@ -5,12 +5,14 @@ import { RdDItemCompetence } from "./item-competence.js";
|
|||||||
import { RdDHerbes } from "./rdd-herbes.js";
|
import { RdDHerbes } from "./rdd-herbes.js";
|
||||||
import { RdDGemme } from "./rdd-gemme.js";
|
import { RdDGemme } from "./rdd-gemme.js";
|
||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.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 { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||||
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||||
|
import { TYPES } from "./item.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the basic ItemSheet for RdD specific items
|
* Extend the basic ItemSheet for RdD specific items
|
||||||
@@ -98,16 +100,20 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
isComestible: this.item.getUtilisationCuisine(),
|
isComestible: this.item.getUtilisationCuisine(),
|
||||||
options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable)
|
options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable)
|
||||||
}
|
}
|
||||||
|
if (this.item.type == TYPES.competencecreature) {
|
||||||
|
formData.isparade = RdDItemCompetenceCreature.isParade(this.item)
|
||||||
|
formData.isdommages = RdDItemCompetenceCreature.isDommages(this.item)
|
||||||
|
}
|
||||||
|
|
||||||
const competences = await SystemCompendiums.getCompetences('personnage');
|
const competences = await SystemCompendiums.getCompetences('personnage');
|
||||||
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences()
|
formData.categories = this.item.getCategories()
|
||||||
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 = competences;
|
formData.competences = competences;
|
||||||
}
|
}
|
||||||
if (this.item.type == 'arme') {
|
if (this.item.type == 'arme') {
|
||||||
formData.competences = competences.filter(it => RdDItemCompetence.isCompetenceArme(it))
|
formData.competences = competences.filter(it => it.isCompetenceArme())
|
||||||
}
|
}
|
||||||
if (['sort', 'sortreserve'].includes(this.item.type)) {
|
if (['sort', 'sortreserve'].includes(this.item.type)) {
|
||||||
formData.competences = competences.filter(it => RdDItemCompetence.isDraconic(it));
|
formData.competences = competences.filter(it => RdDItemCompetence.isDraconic(it));
|
||||||
@@ -151,7 +157,7 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
this.html = html;
|
this.html = html;
|
||||||
|
|
||||||
HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs')
|
HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionnelles.isUsing('afficher-prix-joueurs')
|
||||||
|| game.user.isGM
|
|| game.user.isGM
|
||||||
|| !this.item.isOwned);
|
|| !this.item.isOwned);
|
||||||
HtmlUtility.showControlWhen(this.html.find(".item-magique"), this.item.isMagique());
|
HtmlUtility.showControlWhen(this.html.find(".item-magique"), this.item.isMagique());
|
||||||
@@ -189,7 +195,8 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
|
|
||||||
this.html.find('.creer-tache-livre').click((event) => this._getEventActor(event).creerTacheDepuisLivre(this.item));
|
this.html.find('.creer-tache-livre').click((event) => this._getEventActor(event).creerTacheDepuisLivre(this.item));
|
||||||
this.html.find('.consommer-potion').click((event) => this._getEventActor(event).consommerPotion(this.item, this.getActionRenderItem()));
|
this.html.find('.consommer-potion').click((event) => this._getEventActor(event).consommerPotion(this.item, this.getActionRenderItem()));
|
||||||
this.html.find('.creer-potion-base').click((event) => this._getEventActor(event).dialogFabriquerPotion(this.item));
|
this.html.find('.creer-potion-base').click((event) => this._getEventActor(event).actionHerbe(this.item));
|
||||||
|
this.html.find('input[name="system.cacher_points_de_tache"]').change(async event => await this.item.update({ 'system.cacher_points_de_tache': event.currentTarget.checked }));
|
||||||
|
|
||||||
this.html.find('.alchimie-tache a').click((event) => {
|
this.html.find('.alchimie-tache a').click((event) => {
|
||||||
let actor = this._getEventActor(event);
|
let actor = this._getEventActor(event);
|
||||||
@@ -249,7 +256,8 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if (this.item.isCompetence()) {
|
if (this.item.isCompetence()) {
|
||||||
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
|
const categorie = event.currentTarget.value;
|
||||||
|
const level = RdDItemCompetence.getNiveauBase(categorie, this.item.getCategories());
|
||||||
this.item.system.base = level;
|
this.item.system.base = level;
|
||||||
this.html.find('[name="system.base"]').val(level);
|
this.html.find('[name="system.base"]').val(level);
|
||||||
}
|
}
|
||||||
|
130
module/item.js
130
module/item.js
@@ -6,44 +6,55 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
|||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||||
import { RdDRaretes } from "./item/raretes.js";
|
import { RdDRaretes } from "./item/raretes.js";
|
||||||
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||||
|
|
||||||
export const TYPES = {
|
export const TYPES = {
|
||||||
competence: 'competence',
|
competence: 'competence',
|
||||||
competencecreature: 'competencecreature',
|
competencecreature: 'competencecreature',
|
||||||
|
empoignade: 'empoignade',
|
||||||
|
possession: 'possession',
|
||||||
|
blessure: 'blessure',
|
||||||
|
maladie: 'maladie',
|
||||||
|
poison: 'poison',
|
||||||
arme: 'arme',
|
arme: 'arme',
|
||||||
armure: 'armure',
|
armure: 'armure',
|
||||||
conteneur: 'conteneur',
|
conteneur: 'conteneur',
|
||||||
sort: 'sort',
|
objet: 'objet',
|
||||||
|
monnaie: 'monnaie',
|
||||||
|
gemme: 'gemme',
|
||||||
|
munition: 'munition',
|
||||||
|
nourritureboisson: 'nourritureboisson',
|
||||||
herbe: 'herbe',
|
herbe: 'herbe',
|
||||||
faune: 'faune',
|
plante: 'plante',
|
||||||
ingredient: 'ingredient',
|
ingredient: 'ingredient',
|
||||||
|
faune: 'faune',
|
||||||
livre: 'livre',
|
livre: 'livre',
|
||||||
potion: 'potion',
|
potion: 'potion',
|
||||||
|
service: 'service',
|
||||||
|
musique: 'musique',
|
||||||
|
danse: 'danse',
|
||||||
|
chant: 'chant',
|
||||||
|
jeu: 'jeu',
|
||||||
|
recettecuisine: 'recettecuisine',
|
||||||
|
oeuvre: 'oeuvre',
|
||||||
|
recettealchimique: 'recettealchimique',
|
||||||
|
tache: 'tache',
|
||||||
|
sort: 'sort',
|
||||||
|
sortreserve: 'sortreserve',
|
||||||
rencontre: 'rencontre',
|
rencontre: 'rencontre',
|
||||||
queue: 'queue',
|
queue: 'queue',
|
||||||
ombre: 'ombre',
|
ombre: 'ombre',
|
||||||
souffle: 'souffle',
|
souffle: 'souffle',
|
||||||
tete: 'tete',
|
tete: 'tete',
|
||||||
|
casetmr: 'casetmr',
|
||||||
meditation: 'meditation',
|
meditation: 'meditation',
|
||||||
recettealchimique: 'recettealchimique',
|
|
||||||
chant: 'chant',
|
|
||||||
danse: 'danse',
|
|
||||||
jeu: 'jeu',
|
|
||||||
recettecuisine: 'recettecuisine',
|
|
||||||
musique: 'musique',
|
|
||||||
maladie: 'maladie',
|
|
||||||
poison: 'poison',
|
|
||||||
oeuvre: 'oeuvre',
|
|
||||||
nourritureboisson: 'nourritureboisson',
|
|
||||||
service: 'service',
|
|
||||||
signedraconique: 'signedraconique',
|
signedraconique: 'signedraconique',
|
||||||
gemme: 'gemme',
|
|
||||||
possession: 'possession',
|
|
||||||
sortreserve: 'sortreserve',
|
|
||||||
extraitpoetique: 'extraitpoetique',
|
|
||||||
tarot: 'tarot',
|
tarot: 'tarot',
|
||||||
empoignade: 'empoignade'
|
nombreastral: 'nombreastral',
|
||||||
|
extraitpoetique: 'extraitpoetique',
|
||||||
}
|
}
|
||||||
|
|
||||||
const typesInventaireMateriel = [
|
const typesInventaireMateriel = [
|
||||||
TYPES.arme,
|
TYPES.arme,
|
||||||
TYPES.armure,
|
TYPES.armure,
|
||||||
@@ -209,6 +220,33 @@ export class RdDItem extends Item {
|
|||||||
isService() { return this.type == TYPES.service; }
|
isService() { return this.type == TYPES.service; }
|
||||||
|
|
||||||
isCompetence() { return typesObjetsCompetence.includes(this.type) }
|
isCompetence() { return typesObjetsCompetence.includes(this.type) }
|
||||||
|
isEsquive() {
|
||||||
|
return (this.isCompetence()
|
||||||
|
&& this.system.categorie == 'melee'
|
||||||
|
&& Grammar.includesLowerCaseNoAccent(this.name, 'Esquive'));
|
||||||
|
}
|
||||||
|
|
||||||
|
isCorpsACorps() {
|
||||||
|
return (this.isCompetence()
|
||||||
|
&& this.system.categorie == 'melee'
|
||||||
|
&& Grammar.includesLowerCaseNoAccent(this.name, 'Corps à Corps'));
|
||||||
|
}
|
||||||
|
|
||||||
|
isCompetenceArme() {
|
||||||
|
if (this.isCompetence()) {
|
||||||
|
switch (this.system.categorie) {
|
||||||
|
case 'melee':
|
||||||
|
return !this.isCorpsACorps() && !this.isEsquive()
|
||||||
|
case 'tir':
|
||||||
|
case 'lancer':
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
isCompetencePossession() { return TYPES.competencecreature == this.type && this.system.categorie == "possession" }
|
||||||
isTemporel() { return typesObjetsTemporels.includes(this.type) }
|
isTemporel() { return typesObjetsTemporels.includes(this.type) }
|
||||||
isOeuvre() { return typesObjetsOeuvres.includes(this.type) }
|
isOeuvre() { return typesObjetsOeuvres.includes(this.type) }
|
||||||
isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
|
isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
|
||||||
@@ -225,6 +263,13 @@ export class RdDItem extends Item {
|
|||||||
isPresentDansMilieux(milieux) {
|
isPresentDansMilieux(milieux) {
|
||||||
return this.getEnvironnements(milieux).length > 0
|
return this.getEnvironnements(milieux).length > 0
|
||||||
}
|
}
|
||||||
|
getCategories() {
|
||||||
|
switch (this.type) {
|
||||||
|
case TYPES.competence: return RdDItemCompetence.getCategories()
|
||||||
|
case TYPES.competencecreature: return RdDItemCompetenceCreature.getCategories()
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
getEnvironnements(milieux = undefined) {
|
getEnvironnements(milieux = undefined) {
|
||||||
const environnements = this.isInventaire() ? this.system.environnement : undefined;
|
const environnements = this.isInventaire() ? this.system.environnement : undefined;
|
||||||
@@ -361,7 +406,7 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getEncTotal() {
|
getEncTotal() {
|
||||||
return (this.isService() ? 0 : this.getQuantite()) * this.getEnc();
|
return (this.getQuantite() ?? 0) * this.getEnc();
|
||||||
}
|
}
|
||||||
|
|
||||||
getEnc() {
|
getEnc() {
|
||||||
@@ -376,6 +421,16 @@ export class RdDItem extends Item {
|
|||||||
return Math.max(this.system.encombrement ?? 0, 0);
|
return Math.max(this.system.encombrement ?? 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getEncContenu() {
|
||||||
|
return this.getContenu()
|
||||||
|
.map(it => it.getRecursiveEnc())
|
||||||
|
.reduce(Misc.sum(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRecursiveEnc() {
|
||||||
|
return this.getEncTotal() + this.getEncContenu()
|
||||||
|
}
|
||||||
|
|
||||||
getEncHerbe() {
|
getEncHerbe() {
|
||||||
switch (this.system.categorie) {
|
switch (this.system.categorie) {
|
||||||
case 'Repos': case 'Soin': case 'Alchimie':
|
case 'Repos': case 'Soin': case 'Alchimie':
|
||||||
@@ -385,6 +440,18 @@ export class RdDItem extends Item {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getContenu() {
|
||||||
|
if (this.isConteneur()) {
|
||||||
|
return this.system.contenu.map(idContenu => this.actor.getItem(idContenu));
|
||||||
|
}
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
isConteneurContenu(conteneur) {
|
||||||
|
return this.getContenu()
|
||||||
|
.find(it => it.id == conteneur.id || it.isConteneurContenu(conteneur))
|
||||||
|
}
|
||||||
|
|
||||||
valeurTotale() {
|
valeurTotale() {
|
||||||
return (this.isService() ? 1 : this.getQuantite()) * this.valeur()
|
return (this.isService() ? 1 : this.getQuantite()) * this.valeur()
|
||||||
}
|
}
|
||||||
@@ -431,11 +498,11 @@ export class RdDItem extends Item {
|
|||||||
if (this.actor?.isPersonnage()) {
|
if (this.actor?.isPersonnage()) {
|
||||||
const warn = options.warnIfNot;
|
const warn = options.warnIfNot;
|
||||||
if (this.getUtilisationCuisine() == 'brut') {
|
if (this.getUtilisationCuisine() == 'brut') {
|
||||||
return 'Utiliser';
|
return 'Cuisiner';
|
||||||
}
|
}
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
|
case TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
|
||||||
case TYPES.potion: return this._actionOrWarnQuantiteZero('Boire', warn);
|
case TYPES.potion: return this._actionOrWarnQuantiteZero('Consommer', warn);
|
||||||
case TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn);
|
case TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn);
|
||||||
case TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
|
case TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
|
||||||
case TYPES.queue: case TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined;
|
case TYPES.queue: case TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined;
|
||||||
@@ -446,19 +513,8 @@ export class RdDItem extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async actionPrincipale(actor, onActionItem = async () => { }) {
|
async actionPrincipale(actor, onActionItem = async () => { }) {
|
||||||
if (!this.getActionPrincipale()) {
|
if (!this.getActionPrincipale()) { return }
|
||||||
return;
|
await actor?.actionPrincipale(this, onActionItem);
|
||||||
}
|
|
||||||
if (await actor.actionNourritureboisson(this, onActionItem)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
switch (this.type) {
|
|
||||||
case TYPES.potion: return await actor.consommerPotion(this, onActionItem);
|
|
||||||
case TYPES.livre: return await actor.actionLire(this);
|
|
||||||
case TYPES.conteneur: return await this.sheet.render(true);
|
|
||||||
case TYPES.herbe: return await actor.actionHerbe(this, onActionItem);
|
|
||||||
case TYPES.queue: case TYPES.ombre: return await actor.actionRefoulement(this);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_actionOrWarnQuantiteZero(actionName, warn) {
|
_actionOrWarnQuantiteZero(actionName, warn) {
|
||||||
@@ -656,7 +712,7 @@ export class RdDItem extends Item {
|
|||||||
_armeChatData() {
|
_armeChatData() {
|
||||||
return [
|
return [
|
||||||
`<b>Compétence</b>: ${this.system.competence}`,
|
`<b>Compétence</b>: ${this.system.competence}`,
|
||||||
`<b>Dommages</b>: ${this.system.dommages}`,
|
`<b>Dommages</b>: ${this.system.dommages} ${this.system.mortalite == 'non-mortel' ? '(Non mortel)' : ''}`,
|
||||||
`<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}`,
|
||||||
...this._inventaireTemplateChatData()
|
...this._inventaireTemplateChatData()
|
||||||
@@ -741,7 +797,7 @@ export class RdDItem extends Item {
|
|||||||
`<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}`,
|
||||||
RdDItem.propertyIfDefined('Points de Tâche', this.system.points_de_tache, this.system.cacher_points_de_tache),
|
RdDItem.propertyIfDefined('Points de Tâche', this.system.points_de_tache, !this.system.cacher_points_de_tache),
|
||||||
`<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}`]
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -750,7 +806,7 @@ 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}`,
|
||||||
RdDItem.propertyIfDefined('Points de Tâche', this.system.points_de_tache, this.system.cacher_points_de_tache),
|
RdDItem.propertyIfDefined('Points de Tâche', this.system.points_de_tache, !this.system.cacher_points_de_tache),
|
||||||
...this._inventaireTemplateChatData()
|
...this._inventaireTemplateChatData()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { RdDItem } from "../item.js";
|
import { RdDItem } from "../item.js";
|
||||||
import { Misc } from "../misc.js";
|
import { Misc } from "../misc.js";
|
||||||
import { ReglesOptionelles } from "../settings/regles-optionelles.js";
|
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||||
|
|
||||||
export class RdDItemArmure extends RdDItem {
|
export class RdDItemArmure extends RdDItem {
|
||||||
|
|
||||||
@@ -9,7 +9,7 @@ export class RdDItemArmure extends RdDItem {
|
|||||||
}
|
}
|
||||||
|
|
||||||
deteriorerArmure(dmg) {
|
deteriorerArmure(dmg) {
|
||||||
if (!ReglesOptionelles.isUsing('deteriorationArmure') || this.system.protection == '0') {
|
if (!ReglesOptionnelles.isUsing('deteriorationArmure') || this.system.protection == '0') {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let deterioration = (this.system.deterioration ?? 0) + dmg;
|
let deterioration = (this.system.deterioration ?? 0) + dmg;
|
||||||
|
@@ -29,7 +29,7 @@ export class RdDConteneurItemSheet extends RdDItemInventaireSheet {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
prepareConteneurData(formData) {
|
prepareConteneurData(formData) {
|
||||||
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
||||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
|
||||||
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
|
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ import { RdDBaseActor } from "./actor/base-actor.js";
|
|||||||
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
|
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { Monnaie } from "./item-monnaie.js";
|
import { Monnaie } from "./item-monnaie.js";
|
||||||
import { RdDItem } from "./item.js";
|
import { RdDItem, TYPES } from "./item.js";
|
||||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||||
import { RdDRaretes } from "./item/raretes.js";
|
import { RdDRaretes } from "./item/raretes.js";
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ class Migration {
|
|||||||
|
|
||||||
async applyItemsUpdates(computeUpdates) {
|
async applyItemsUpdates(computeUpdates) {
|
||||||
await game.actors.forEach(async (actor) => {
|
await game.actors.forEach(async (actor) => {
|
||||||
const actorItemUpdates = computeUpdates(actor.items);
|
const actorItemUpdates = computeUpdates(actor.items).filter(it => it != undefined);
|
||||||
if (actorItemUpdates.length > 0) {
|
if (actorItemUpdates.length > 0) {
|
||||||
console.log(
|
console.log(
|
||||||
this.code,
|
this.code,
|
||||||
@@ -24,7 +24,7 @@ class Migration {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const itemUpdates = computeUpdates(game.items);
|
const itemUpdates = computeUpdates(game.items).filter(it => it != undefined);
|
||||||
if (itemUpdates.length > 0) {
|
if (itemUpdates.length > 0) {
|
||||||
console.log(this.code, "Applying updates on items", itemUpdates);
|
console.log(this.code, "Applying updates on items", itemUpdates);
|
||||||
await Item.updateDocuments(itemUpdates);
|
await Item.updateDocuments(itemUpdates);
|
||||||
@@ -65,7 +65,6 @@ class _1_5_34_migrationPngWebp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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"; }
|
||||||
@@ -370,6 +369,7 @@ class _10_4_6_ServicesEnCommerces extends Migration {
|
|||||||
return itemToCreate;
|
return itemToCreate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _10_5_0_UpdatePeriodicite extends Migration {
|
class _10_5_0_UpdatePeriodicite extends Migration {
|
||||||
get code() { return "migration-periodicite-poisons-maladies"; }
|
get code() { return "migration-periodicite-poisons-maladies"; }
|
||||||
get version() { return "10.5.0"; }
|
get version() { return "10.5.0"; }
|
||||||
@@ -458,6 +458,62 @@ class _10_7_0_MigrationBlessures extends Migration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _10_7_19_CategorieCompetenceCreature extends Migration {
|
||||||
|
get code() { return "categorie-competence-creature"; }
|
||||||
|
get version() { return "10.7.19"; }
|
||||||
|
|
||||||
|
async migrate() {
|
||||||
|
await this.applyItemsUpdates(items => items
|
||||||
|
.filter(it => TYPES.competencecreature == it.type)
|
||||||
|
.map(it => this.migrateCompetenceCreature(it))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
migrateCompetenceCreature(it) {
|
||||||
|
const categorie = this.getCategorie(it)
|
||||||
|
if (categorie == it.system.categorie) {
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
return { _id: it.id, 'system.categorie': categorie }
|
||||||
|
}
|
||||||
|
|
||||||
|
getCategorie(it) {
|
||||||
|
if (it.system.ispossession) {
|
||||||
|
return 'possession'
|
||||||
|
}
|
||||||
|
switch (it.system.categorie) {
|
||||||
|
case "melee":
|
||||||
|
if (it.system.isnaturelle) {
|
||||||
|
return 'naturelle'
|
||||||
|
}
|
||||||
|
return 'melee'
|
||||||
|
case "particuliere": case "specialisee": case "connaissance":
|
||||||
|
return "generale"
|
||||||
|
default:
|
||||||
|
return it.system.categorie
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _10_7_19_PossessionsEntiteVictime extends Migration {
|
||||||
|
get code() { return "possessions-entite-victime"; }
|
||||||
|
get version() { return "10.7.19"; }
|
||||||
|
|
||||||
|
async migrate() {
|
||||||
|
await this.applyItemsUpdates(items => items
|
||||||
|
.filter(it => TYPES.possession == it.type)
|
||||||
|
.map(it => this.migratePossession(it))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
migratePossession(it) {
|
||||||
|
return { _id: it.id,
|
||||||
|
'system.entite.actorid': it.system.possesseurid,
|
||||||
|
'system.victime.actorid': it.system.possedeid
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Migrations {
|
export class Migrations {
|
||||||
static getMigrations() {
|
static getMigrations() {
|
||||||
return [
|
return [
|
||||||
@@ -474,6 +530,8 @@ export class Migrations {
|
|||||||
new _10_4_6_ServicesEnCommerces(),
|
new _10_4_6_ServicesEnCommerces(),
|
||||||
new _10_5_0_UpdatePeriodicite(),
|
new _10_5_0_UpdatePeriodicite(),
|
||||||
new _10_7_0_MigrationBlessures(),
|
new _10_7_0_MigrationBlessures(),
|
||||||
|
new _10_7_19_CategorieCompetenceCreature(),
|
||||||
|
new _10_7_19_PossessionsEntiteVictime(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,7 +548,7 @@ export class Migrations {
|
|||||||
migrate() {
|
migrate() {
|
||||||
const currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion");
|
const currentVersion = game.settings.get(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 */
|
// 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) => this.compareVersions(a, b));
|
migrations.sort((a, b) => this.compareVersions(a, b));
|
||||||
|
@@ -42,7 +42,7 @@ export class Misc {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static typeName(type, subType) {
|
static typeName(type, subType) {
|
||||||
return subType ? game.i18n.localize(`${type.toUpperCase()}.Type${Misc.upperFirst(subType)}`)
|
return subType ? game.i18n.localize(`TYPES.${type}.${Misc.upperFirst(subType)}`)
|
||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,8 +63,8 @@ export class Misc {
|
|||||||
|
|
||||||
static keepDecimals(num, decimals) {
|
static keepDecimals(num, decimals) {
|
||||||
if (decimals <= 0 || decimals > 6) return num;
|
if (decimals <= 0 || decimals > 6) return num;
|
||||||
const decimal = Math.pow(10, parseInt(decimals));
|
const power10n = Math.pow(10, parseInt(decimals));
|
||||||
return Math.round(num * decimal) / decimal;
|
return Math.round(num * power10n) / power10n;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getFractionHtml(diviseur) {
|
static getFractionHtml(diviseur) {
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
|
import { RdDPossession } from "./rdd-possession.js";
|
||||||
|
|
||||||
const conditionsTactiques = [
|
const conditionsTactiques = [
|
||||||
{ type: '', descr: '', dmg: 0, attaque: 0, parade: 0, esquive: true },
|
{ type: '', descr: '', dmg: 0, attaque: 0, parade: 0, esquive: true },
|
||||||
@@ -27,6 +28,9 @@ export class RdDBonus {
|
|||||||
if (rollData.isEmpoignade && rollData.rolled?.isPart) {
|
if (rollData.isEmpoignade && rollData.rolled?.isPart) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if (RdDPossession.isDefensePossession(rollData)) {
|
||||||
|
return RdDPossession.isPossessionFinesse(rollData)
|
||||||
|
}
|
||||||
return rollData.attackerRoll?.particuliere == 'finesse';
|
return rollData.attackerRoll?.particuliere == 'finesse';
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +78,7 @@ export class RdDBonus {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _dmgArme(rollData) {
|
static _dmgArme(rollData) {
|
||||||
if ( rollData.arme) {
|
if (rollData.arme) {
|
||||||
let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0);
|
let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0);
|
||||||
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
|
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
|
||||||
return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0);
|
return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
|
|
||||||
const tableCaracDerivee = {
|
const TABLE_CARACTERISTIQUES_DERIVEES = {
|
||||||
// xp: coût pour passer du niveau inférieur à ce niveau
|
// xp: coût pour passer du niveau inférieur à ce niveau
|
||||||
1: { xp: 3, poids: "moins de 1kg", plusdom: -5, sconst: 0.5, sust: 0.1 },
|
1: { xp: 3, poids: "moins de 1kg", plusdom: -5, sconst: 0.5, sust: 0.1 },
|
||||||
2: { xp: 3, poids: "1-5", plusdom: -4, sconst: 0.5, sust: 0.3 },
|
2: { xp: 3, poids: "1-5", plusdom: -4, sconst: 0.5, sust: 0.3 },
|
||||||
@@ -58,15 +58,10 @@ export class RdDCarac {
|
|||||||
selectedCarac?.label.match(/(Apparence|Force|Agilité|Dextérité|Vue|Ouïe|Odorat-Goût|Empathie|Dérobée|Mêlée|Tir|Lancer)/);
|
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 getCaracDerivee(value) {
|
||||||
const selectedCarac = rollData.selectedCarac;
|
return TABLE_CARACTERISTIQUES_DERIVEES[Math.min(Math.max(Number(value), 1), 32)];
|
||||||
return !selectedCarac ||
|
|
||||||
rollData.ethylisme ||
|
|
||||||
RdDCarac.isChance(selectedCarac) ||
|
|
||||||
(RdDCarac.isReve(selectedCarac) && !rollData.competence);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static computeTotal(carac, beaute = undefined) {
|
static computeTotal(carac, beaute = undefined) {
|
||||||
const total = Object.values(carac ?? {}).filter(c => !c.derivee)
|
const total = Object.values(carac ?? {}).filter(c => !c.derivee)
|
||||||
.map(it => parseInt(it.value))
|
.map(it => parseInt(it.value))
|
||||||
@@ -82,7 +77,7 @@ export class RdDCarac {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static calculSConst(constitution) {
|
static calculSConst(constitution) {
|
||||||
return Number(tableCaracDerivee[Number(constitution)].sconst);
|
return RdDCarac.getCaracDerivee(constitution).sconst;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -93,7 +88,7 @@ export class RdDCarac {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static getCaracXp(targetValue) {
|
static getCaracXp(targetValue) {
|
||||||
return tableCaracDerivee[targetValue]?.xp ?? 200;
|
return RdDCarac.getCaracDerivee(targetValue)?.xp ?? 200;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -106,37 +101,4 @@ export class RdDCarac {
|
|||||||
return Grammar.toLowerCaseNoAccent(selectedCarac?.label)?.match(/(apparence|force|agilite|dexterite|vue|ouie|odorat|empathie|melee|tir|lancer|derobee)/);
|
return Grammar.toLowerCaseNoAccent(selectedCarac?.label)?.match(/(apparence|force|agilite|dexterite|vue|ouie|odorat|empathie|melee|tir|lancer|derobee)/);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static computeCarac(system) {
|
|
||||||
system.carac.force.value = Math.min(system.carac.force.value, parseInt(system.carac.taille.value) + 4);
|
|
||||||
|
|
||||||
system.carac.derobee.value = Math.floor(parseInt(((21 - system.carac.taille.value)) + parseInt(system.carac.agilite.value)) / 2);
|
|
||||||
let bonusDomKey = Math.floor((parseInt(system.carac.force.value) + parseInt(system.carac.taille.value)) / 2);
|
|
||||||
bonusDomKey = Math.min(Math.max(bonusDomKey, 0), 32); // Clamp de securite
|
|
||||||
|
|
||||||
let tailleData = tableCaracDerivee[bonusDomKey];
|
|
||||||
system.attributs.plusdom.value = tailleData.plusdom;
|
|
||||||
|
|
||||||
system.attributs.sconst.value = RdDCarac.calculSConst(system.carac.constitution.value);
|
|
||||||
system.attributs.sust.value = tableCaracDerivee[Number(system.carac.taille.value)].sust;
|
|
||||||
|
|
||||||
system.attributs.encombrement.value = (parseInt(system.carac.force.value) + parseInt(system.carac.taille.value)) / 2;
|
|
||||||
system.carac.melee.value = Math.floor((parseInt(system.carac.force.value) + parseInt(system.carac.agilite.value)) / 2);
|
|
||||||
system.carac.tir.value = Math.floor((parseInt(system.carac.vue.value) + parseInt(system.carac.dexterite.value)) / 2);
|
|
||||||
system.carac.lancer.value = Math.floor((parseInt(system.carac.tir.value) + parseInt(system.carac.force.value)) / 2);
|
|
||||||
|
|
||||||
system.sante.vie.max = Math.ceil((parseInt(system.carac.taille.value) + parseInt(system.carac.constitution.value)) / 2);
|
|
||||||
|
|
||||||
system.sante.vie.value = Math.min(system.sante.vie.value, system.sante.vie.max)
|
|
||||||
system.sante.endurance.max = Math.max(parseInt(system.carac.taille.value) + parseInt(system.carac.constitution.value), parseInt(system.sante.vie.max) + parseInt(system.carac.volonte.value));
|
|
||||||
system.sante.endurance.value = Math.min(system.sante.endurance.value, system.sante.endurance.max);
|
|
||||||
system.sante.fatigue.max = system.sante.endurance.max * 2;
|
|
||||||
system.sante.fatigue.value = Math.min(system.sante.fatigue.value, system.sante.fatigue.max);
|
|
||||||
|
|
||||||
//Compteurs
|
|
||||||
system.reve.reve.max = system.carac.reve.value;
|
|
||||||
system.compteurs.chance.max = system.carac.chance.value;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@ import { RdDBonus } from "./rdd-bonus.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 { RdDRollTables } from "./rdd-rolltables.js";
|
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||||
import { STATUSES } from "./settings/status-effects.js";
|
import { STATUSES } from "./settings/status-effects.js";
|
||||||
import { Targets } from "./targets.js";
|
import { Targets } from "./targets.js";
|
||||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||||
@@ -87,7 +87,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0);
|
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0);
|
||||||
if (!formula) {
|
if (!formula) {
|
||||||
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
|
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
|
||||||
const competence = combatant.actor.items.find(it => it.system.iscombat)
|
const competence = combatant.actor.items.find(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
|
||||||
if (competence) {
|
if (competence) {
|
||||||
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, 0);
|
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, 0);
|
||||||
}
|
}
|
||||||
@@ -171,8 +171,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
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)",
|
||||||
@@ -187,7 +186,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
arme: arme,
|
arme: arme,
|
||||||
infoMain: "(2 mains)",
|
infoMain: "(2 mains)",
|
||||||
dommagesReel: Number(tableauDommages[1]),
|
dommagesReel: Number(tableauDommages[1]),
|
||||||
competence: arme.system.competence.replace(" 1 main", " 2 mains"),
|
competence: RdDItemArme.competence2Mains(arme),
|
||||||
carac: carac,
|
carac: carac,
|
||||||
competences: competences
|
competences: competences
|
||||||
}));
|
}));
|
||||||
@@ -230,15 +229,17 @@ export class RdDCombatManager extends Combat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static listActionsCreature(competences) {
|
static listActionsCreature(competences) {
|
||||||
return competences.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
|
return competences
|
||||||
.map(it => RdDItemCompetenceCreature.armeNaturelle(it));
|
.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
|
||||||
|
.map(it => RdDItemCompetenceCreature.armeCreature(it))
|
||||||
|
.filter(it => it != undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
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: 'possession',
|
||||||
system: {
|
system: {
|
||||||
competence: p.name,
|
competence: p.name,
|
||||||
possessionid: p.system.possessionid,
|
possessionid: p.system.possessionid,
|
||||||
@@ -255,15 +256,14 @@ export class RdDCombatManager extends Combat {
|
|||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
if (actor.isCreatureEntite()) {
|
if (actor.isCreatureEntite()) {
|
||||||
actions = actions.concat(RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']));
|
actions = RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']);
|
||||||
} else if (actor.isPersonnage()) {
|
} else if (actor.isPersonnage()) {
|
||||||
// Recupération des items 'arme'
|
// Recupération des items 'arme'
|
||||||
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
|
|
||||||
.concat(RdDItemArme.empoignade())
|
|
||||||
.concat(RdDItemArme.mainsNues());
|
|
||||||
|
|
||||||
const competences = actor.itemTypes['competence'];
|
const competences = actor.itemTypes['competence'];
|
||||||
actions = actions.concat(RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac));
|
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
|
||||||
|
.concat(RdDItemArme.empoignade(actor))
|
||||||
|
.concat(RdDItemArme.mainsNues(actor));
|
||||||
|
actions = RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac);
|
||||||
|
|
||||||
if (actor.system.attributs.hautrevant.value) {
|
if (actor.system.attributs.hautrevant.value) {
|
||||||
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
|
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
|
||||||
@@ -351,7 +351,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
} else if (combatant.actor.getSurprise() == "demi") {
|
} else if (combatant.actor.getSurprise() == "demi") {
|
||||||
initOffset = 0;
|
initOffset = 0;
|
||||||
initInfo = "Demi Surprise"
|
initInfo = "Demi Surprise"
|
||||||
} else if (action.action == 'conjurer') {
|
} else if (action.action == 'possession') {
|
||||||
initOffset = 10;
|
initOffset = 10;
|
||||||
caracForInit = combatant.actor.getReveActuel();
|
caracForInit = combatant.actor.getReveActuel();
|
||||||
initInfo = "Possession"
|
initInfo = "Possession"
|
||||||
@@ -450,7 +450,7 @@ export class RdDCombat {
|
|||||||
if (Misc.isUniqueConnectedGM()) {
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
let turn = combat.turns.find(t => t.token?.id == combat.current.tokenId);
|
let turn = combat.turns.find(t => t.token?.id == combat.current.tokenId);
|
||||||
if (turn?.actor) {
|
if (turn?.actor) {
|
||||||
RdDCombat.displayActorCombatStatus(combat, turn.actor);
|
RdDCombat.displayActorCombatStatus(combat, turn.actor, turn.token.id);
|
||||||
// TODO Playaudio for player??
|
// TODO Playaudio for player??
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -514,8 +514,12 @@ export class RdDCombat {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _callJetDeVie(event) {
|
static _callJetDeVie(event) {
|
||||||
let actorId = event.currentTarget.attributes['data-actorId'].value;
|
let actorId = event.currentTarget.attributes['data-actorId'].value;
|
||||||
let actor = game.actors.get(actorId);
|
let tokenId = event.currentTarget.attributes['data-tokenId'].value;
|
||||||
actor.jetVie();
|
let token = canvas.tokens.placeables.find(t => t.id == tokenId)
|
||||||
|
const actor = token?.actor ?? game.actors.get(actorId);
|
||||||
|
if (actor?.isOwner) {
|
||||||
|
actor.jetDeVie();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -541,7 +545,7 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
html.on("click", '#chat-jet-vie', event => {
|
html.on("click", 'a.chat-jet-vie', event => {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
RdDCombat._callJetDeVie(event);
|
RdDCombat._callJetDeVie(event);
|
||||||
});
|
});
|
||||||
@@ -789,7 +793,6 @@ export class RdDCombat {
|
|||||||
let rollData = {
|
let rollData = {
|
||||||
passeArme: randomID(16),
|
passeArme: randomID(16),
|
||||||
mortalite: arme?.system.mortalite,
|
mortalite: arme?.system.mortalite,
|
||||||
coupsNonMortels: false,
|
|
||||||
competence: competence,
|
competence: competence,
|
||||||
surprise: this.attacker.getSurprise(true),
|
surprise: this.attacker.getSurprise(true),
|
||||||
surpriseDefenseur: this.defender.getSurprise(true),
|
surpriseDefenseur: this.defender.getSurprise(true),
|
||||||
@@ -821,8 +824,8 @@ export class RdDCombat {
|
|||||||
// finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum
|
// finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum
|
||||||
// rapidité seulement en mêlée, si l'arme le permet, et si la difficulté libre est de -1 minimum
|
// rapidité seulement en mêlée, si l'arme le permet, et si la difficulté libre est de -1 minimum
|
||||||
const isForce = !rollData.arme.system.empoignade;
|
const isForce = !rollData.arme.system.empoignade;
|
||||||
const isFinesse = rollData.arme.system.empoignade || isMeleeDiffNegative;
|
const isFinesse = rollData.tactique != 'charge' && (rollData.arme.system.empoignade || isMeleeDiffNegative);
|
||||||
const isRapide = !rollData.arme.system.empoignade && isMeleeDiffNegative && rollData.arme.system.rapide;
|
const isRapide = rollData.tactique != 'charge' && !rollData.arme.system.empoignade && isMeleeDiffNegative && rollData.arme.system.rapide;
|
||||||
// si un seul choix possible, le prendre
|
// si un seul choix possible, le prendre
|
||||||
if (isForce && !isFinesse && !isRapide) {
|
if (isForce && !isFinesse && !isRapide) {
|
||||||
return await this.choixParticuliere(rollData, "force");
|
return await this.choixParticuliere(rollData, "force");
|
||||||
@@ -886,8 +889,8 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// # utilisation esquive
|
// # utilisation esquive
|
||||||
const corpsACorps = this.defender.getCompetence("Corps à corps", { onMessage: it => console.info(it, this.defender) });
|
const corpsACorps = this.defender.getCompetenceCorpsACorps({ onMessage: it => console.info(it, this.defender) });
|
||||||
const esquives = duplicate(this.defender.getCompetences("esquive", { onMessage: it => console.info(it, this.defender) }))
|
const esquives = duplicate(this.defender.getCompetencesEsquive())
|
||||||
esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0);
|
esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0);
|
||||||
|
|
||||||
const paramChatDefense = {
|
const paramChatDefense = {
|
||||||
@@ -1048,7 +1051,7 @@ export class RdDCombat {
|
|||||||
competence: this.defender.getCompetence(competenceParade),
|
competence: this.defender.getCompetence(competenceParade),
|
||||||
arme: armeParade,
|
arme: armeParade,
|
||||||
surprise: this.defender.getSurprise(true),
|
surprise: this.defender.getSurprise(true),
|
||||||
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
|
needParadeSignificative: ReglesOptionnelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
|
||||||
needResist: RdDItemArme.needArmeResist(attackerRoll.arme, armeParade),
|
needResist: RdDItemArme.needArmeResist(attackerRoll.arme, armeParade),
|
||||||
carac: this.defender.system.carac,
|
carac: this.defender.system.carac,
|
||||||
show: {}
|
show: {}
|
||||||
@@ -1166,7 +1169,7 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async computeDeteriorationArme(defenderRoll) {
|
async computeDeteriorationArme(defenderRoll) {
|
||||||
if (!ReglesOptionelles.isUsing('resistanceArmeParade')) {
|
if (!ReglesOptionnelles.isUsing('resistanceArmeParade')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const attackerRoll = defenderRoll.attackerRoll;
|
const attackerRoll = defenderRoll.attackerRoll;
|
||||||
@@ -1215,7 +1218,7 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
|
// Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
|
||||||
if (ReglesOptionelles.isUsing('defenseurDesarme') && resistance > 0 && RdDItemArme.getCategorieParade(defenderRoll.arme) != 'boucliers') {
|
if (ReglesOptionnelles.isUsing('defenseurDesarme') && resistance > 0 && RdDItemArme.getCategorieParade(defenderRoll.arme) != 'boucliers') {
|
||||||
let desarme = await RdDResolutionTable.rollData({
|
let desarme = await RdDResolutionTable.rollData({
|
||||||
caracValue: this.defender.getForce(),
|
caracValue: this.defender.getForce(),
|
||||||
finalLevel: Misc.toInt(defenderRoll.competence.system.niveau) - dmg,
|
finalLevel: Misc.toInt(defenderRoll.competence.system.niveau) - dmg,
|
||||||
@@ -1230,7 +1233,7 @@ export class RdDCombat {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async computeRecul(defenderRoll) { // Calcul du recul (p. 132)
|
async computeRecul(defenderRoll) { // Calcul du recul (p. 132)
|
||||||
const attackerRoll = defenderRoll.attackerRoll;
|
const attackerRoll = defenderRoll.attackerRoll;
|
||||||
if (ReglesOptionelles.isUsing('recul') && this._isForceOuCharge(attackerRoll)) {
|
if (ReglesOptionnelles.isUsing('recul') && this._isForceOuCharge(attackerRoll)) {
|
||||||
const impact = this._computeImpactRecul(attackerRoll);
|
const impact = this._computeImpactRecul(attackerRoll);
|
||||||
const rollRecul = await RdDResolutionTable.rollData({ caracValue: 10, finalLevel: impact });
|
const rollRecul = await RdDResolutionTable.rollData({ caracValue: 10, finalLevel: impact });
|
||||||
if (rollRecul.rolled.isSuccess) {
|
if (rollRecul.rolled.isSuccess) {
|
||||||
@@ -1295,7 +1298,7 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async displayActorCombatStatus(combat, actor) {
|
static async displayActorCombatStatus(combat, actor, tokenId) {
|
||||||
let formData = {
|
let formData = {
|
||||||
combatId: combat._id,
|
combatId: combat._id,
|
||||||
alias: actor.name,
|
alias: actor.name,
|
||||||
@@ -1304,12 +1307,18 @@ export class RdDCombat {
|
|||||||
blessuresStatus: actor.computeResumeBlessure(),
|
blessuresStatus: actor.computeResumeBlessure(),
|
||||||
SConst: actor.getSConst(),
|
SConst: actor.getSConst(),
|
||||||
actorId: actor.id,
|
actorId: actor.id,
|
||||||
|
tokenId: tokenId,
|
||||||
isGrave: actor.countBlessures(it => it.isGrave()) > 0,
|
isGrave: actor.countBlessures(it => it.isGrave()) > 0,
|
||||||
isCritique: actor.countBlessures(it => it.isCritique()) > 0
|
isCritique: actor.countBlessures(it => it.isCritique()) > 0
|
||||||
}
|
}
|
||||||
|
await ChatMessage.create({
|
||||||
ChatUtility.createChatWithRollMode(actor.name, {
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-acteur.hbs`, formData),
|
||||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html`, formData)
|
alias: actor.name
|
||||||
|
});
|
||||||
|
await ChatMessage.create({
|
||||||
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs`, formData),
|
||||||
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(actor.name),
|
||||||
|
alias: actor.name
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,10 +1,10 @@
|
|||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||||
|
|
||||||
export class RdDConfirm {
|
export class RdDConfirm {
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static confirmer(options, autresActions) {
|
static confirmer(options, autresActions) {
|
||||||
options.bypass = options.bypass || !(options.settingConfirmer == undefined || ReglesOptionelles.isUsing(options.settingConfirmer));
|
options.bypass = options.bypass || !(options.settingConfirmer == undefined || ReglesOptionnelles.isUsing(options.settingConfirmer));
|
||||||
if (options.bypass) {
|
if (options.bypass) {
|
||||||
options.onAction();
|
options.onAction();
|
||||||
}
|
}
|
||||||
@@ -47,7 +47,7 @@ export class RdDConfirm {
|
|||||||
icon: '<i class="fas fa-user-check"></i>',
|
icon: '<i class="fas fa-user-check"></i>',
|
||||||
label: options.buttonLabel + "<br>et ne plus demander",
|
label: options.buttonLabel + "<br>et ne plus demander",
|
||||||
callback: () => {
|
callback: () => {
|
||||||
ReglesOptionelles.set(options.settingConfirmer, false);
|
ReglesOptionnelles.set(options.settingConfirmer, false);
|
||||||
options.onAction();
|
options.onAction();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -4,6 +4,8 @@ import { RdDRoll } from "./rdd-roll.js";
|
|||||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { STATUSES } from "./settings/status-effects.js";
|
import { STATUSES } from "./settings/status-effects.js";
|
||||||
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||||
|
import { TYPES } from "./item.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
@@ -14,6 +16,47 @@ export class RdDEmpoignade {
|
|||||||
static init() {
|
static init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static registerChatCallbacks(html) {
|
||||||
|
html.on("click", '.defense-empoignade-cac', event => {
|
||||||
|
const chatMessage = ChatUtility.getChatMessage(event);
|
||||||
|
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||||
|
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
||||||
|
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee")
|
||||||
|
});
|
||||||
|
html.on("click", '.defense-empoignade-esquive', event => {
|
||||||
|
const chatMessage = ChatUtility.getChatMessage(event);
|
||||||
|
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||||
|
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
||||||
|
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee")
|
||||||
|
});
|
||||||
|
html.on("click", '.empoignade-poursuivre', event => {
|
||||||
|
let attackerId = event.currentTarget.attributes['data-attackerId'].value
|
||||||
|
let defenderId = event.currentTarget.attributes['data-defenderId'].value
|
||||||
|
RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId))
|
||||||
|
});
|
||||||
|
html.on("click", '.empoignade-entrainer-sol', event => {
|
||||||
|
const chatMessage = ChatUtility.getChatMessage(event);
|
||||||
|
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||||
|
RdDEmpoignade.entrainerAuSol(rollData)
|
||||||
|
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||||
|
});
|
||||||
|
html.on("click", '.empoignade-projeter-sol', event => {
|
||||||
|
const chatMessage = ChatUtility.getChatMessage(event);
|
||||||
|
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||||
|
RdDEmpoignade.projeterAuSol(rollData)
|
||||||
|
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||||
|
});
|
||||||
|
html.on("change", '.empoignade-perte-endurance', event => {
|
||||||
|
const chatMessage = ChatUtility.getChatMessage(event);
|
||||||
|
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
||||||
|
if (event.currentTarget.value && event.currentTarget.value != "none") {
|
||||||
|
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
|
||||||
|
ChatUtility.removeChatMessageId(chatMessage.id)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static checkEmpoignadeEnCours(actor) {
|
static checkEmpoignadeEnCours(actor) {
|
||||||
// TODO: autoriser la perception? la comédie/séduction?
|
// TODO: autoriser la perception? la comédie/séduction?
|
||||||
@@ -24,74 +67,92 @@ export class RdDEmpoignade {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static $storeRollEmpoignade(msg, rollData) {
|
||||||
|
RdDEmpoignade.$reduceActorToIds(rollData);
|
||||||
|
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData);
|
||||||
|
}
|
||||||
|
|
||||||
|
static $reduceActorToIds(rollData) {
|
||||||
|
rollData.attacker = { id: rollData.attacker.id };
|
||||||
|
rollData.defender = { id: rollData.defender.id };
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static $readRollEmpoignade(msg) {
|
||||||
|
const rollData = ChatUtility.getMessageData(msg, 'empoignade-roll-data');
|
||||||
|
RdDEmpoignade.$replaceIdsWithActors(rollData);
|
||||||
|
return rollData
|
||||||
|
}
|
||||||
|
|
||||||
|
static $replaceIdsWithActors(rollData) {
|
||||||
|
rollData.attacker = game.actors.get(rollData.attacker.id);
|
||||||
|
rollData.defender = game.actors.get(rollData.defender.id);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isEmpoignadeEnCours(actor) {
|
static isEmpoignadeEnCours(actor) {
|
||||||
return actor.itemTypes['empoignade'].find(it => it.system.pointsemp > 0)
|
return actor.itemTypes[TYPES.empoignade].find(it => it.system.pointsemp > 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getEmpoignadeById(actor, id) {
|
static getEmpoignadeById(actor, id) {
|
||||||
let emp = actor.itemTypes['empoignade'].find(it => it.system.empoignadeid == id)
|
let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id)
|
||||||
return emp && duplicate(emp) || undefined;
|
return emp && duplicate(emp) || undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getEmpoignade(attacker, defender) {
|
static getEmpoignade(attacker, defender) {
|
||||||
let emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id)
|
let emp = attacker.itemTypes[TYPES.empoignade].find(it =>
|
||||||
if (!emp) {
|
(it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) ||
|
||||||
emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
|
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
|
||||||
}
|
)
|
||||||
if (emp) {
|
if (emp) {
|
||||||
return duplicate(emp);
|
return duplicate(emp);
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getMalusTaille(emp, attacker, defender) {
|
static getMalusTaille(emp, attacker, defender) {
|
||||||
// Si pas empoigné, alors 0
|
// Si pas empoigné, alors 0
|
||||||
if (emp.system.pointsemp == 0) {
|
if (emp.system.pointsemp == 0) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
// Malus de -1 si différence de taille de 2 ou plus (p 135)
|
// p135: Malus de -1 par point de taille de différence de taille au delà de 1 (donc -2 pour une différence de 3, ...)
|
||||||
if (attacker.system.carac.taille.value < defender.system.carac.taille.value - 1) {
|
const diffTaille = attacker.system.carac.taille.value - defender.system.carac.taille.value;
|
||||||
return attacker.system.carac.taille.value - (defender.system.carac.taille.value - 1)
|
const diffTailleAbs = Math.abs(diffTaille)
|
||||||
|
const signDiff = diffTaille > 0 ? 1 : -1
|
||||||
|
|
||||||
|
if (diffTailleAbs > 2) {
|
||||||
|
return signDiff * (diffTailleAbs - 1)
|
||||||
}
|
}
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
static isActionAutorisee(mode, attacker, defender) {
|
||||||
static async onAttaqueEmpoignadeValidee(attacker, defender) {
|
const acting = RdDEmpoignade.isActionDefenseur(mode) ? defender : attacker;
|
||||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
if (acting.getUserLevel(game.user) < CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) {
|
||||||
const isNouvelle = empoignade == undefined;
|
ui.notifications.warn(`Vous n'êtes pas autorisé à choisir l'action de ${acting.name}`)
|
||||||
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
return false;
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
let mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer"
|
static isActionDefenseur(mode) {
|
||||||
|
switch (mode) {
|
||||||
let rollData = {
|
case "liberer":
|
||||||
mode: mode,
|
case "contrer-empoigner":
|
||||||
isEmpoignade: true,
|
return true;
|
||||||
competence: attacker.getCompetence("Corps à corps"),
|
|
||||||
selectedCarac: attacker.system.carac.melee,
|
|
||||||
empoignade: empoignade,
|
|
||||||
attackerId: attacker.id,
|
|
||||||
attackerName: attacker.name,
|
|
||||||
defenderName: defender.name,
|
|
||||||
defenderId: defender.id,
|
|
||||||
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
|
|
||||||
}
|
|
||||||
if (attacker.isCreatureEntite()) {
|
|
||||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
|
||||||
}
|
|
||||||
if (empoignade.system.pointsemp >= 2) {
|
|
||||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-actions.html');
|
|
||||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
|
||||||
} else {
|
|
||||||
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle);
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async onAttaqueEmpoignade(attacker, defender) {
|
static async onAttaqueEmpoignade(attacker, defender) {
|
||||||
|
if (!RdDEmpoignade.isActionAutorisee("empoigner", attacker, defender)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||||
const isNouvelle = empoignade == undefined;
|
const isNouvelle = empoignade == undefined;
|
||||||
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
||||||
@@ -105,6 +166,38 @@ export class RdDEmpoignade {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async onAttaqueEmpoignadeValidee(attacker, defender) {
|
||||||
|
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||||
|
const isNouvelle = empoignade == undefined;
|
||||||
|
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
||||||
|
|
||||||
|
let mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer"
|
||||||
|
|
||||||
|
if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let rollData = {
|
||||||
|
mode, empoignade, attacker, defender,
|
||||||
|
isEmpoignade: true,
|
||||||
|
competence: attacker.getCompetenceCorpsACorps(),
|
||||||
|
selectedCarac: attacker.system.carac.melee,
|
||||||
|
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
|
||||||
|
}
|
||||||
|
if (attacker.isCreatureEntite()) {
|
||||||
|
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
||||||
|
}
|
||||||
|
if (empoignade.system.pointsemp >= 2) {
|
||||||
|
if (!empoignade.system.ausol) {
|
||||||
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.html');
|
||||||
|
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async onAttaqueEmpoignadeFromItem(empoignade) {
|
static async onAttaqueEmpoignadeFromItem(empoignade) {
|
||||||
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||||
@@ -112,6 +205,20 @@ export class RdDEmpoignade {
|
|||||||
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async onImmobilisation(attacker, defender, empoignade) {
|
||||||
|
const rollData = {
|
||||||
|
mode: "immobilise",
|
||||||
|
empoignade, attacker, defender,
|
||||||
|
isEmpoignade: true,
|
||||||
|
competence: attacker.getCompetenceCorpsACorps()
|
||||||
|
}
|
||||||
|
const msg = await ChatMessage.create({
|
||||||
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(attacker.name),
|
||||||
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-immobilise.html`, rollData)
|
||||||
|
})
|
||||||
|
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) {
|
static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) {
|
||||||
const dialog = await RdDRoll.create(attacker, rollData,
|
const dialog = await RdDRoll.create(attacker, rollData,
|
||||||
@@ -119,35 +226,40 @@ export class RdDEmpoignade {
|
|||||||
{
|
{
|
||||||
name: 'jet-empoignade',
|
name: 'jet-empoignade',
|
||||||
label: 'Empoigner',
|
label: 'Empoigner',
|
||||||
callbacks: [
|
callbacks: [{ action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, isNouvelle) },]
|
||||||
{ condition: r => (r.rolled.isSuccess), action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, true, isNouvelle) },
|
|
||||||
{ condition: r => (r.rolled.isEchec), action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, false, isNouvelle) },
|
|
||||||
]
|
|
||||||
});
|
});
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async $onRollEmpoignade(rollData, isSuccess, isNouvelle = false) {
|
static async $onRollEmpoignade(rollData, isNouvelle = false) {
|
||||||
let attacker = game.actors.get(rollData.attackerId)
|
let attacker = game.actors.get(rollData.attacker.id)
|
||||||
let defender = game.actors.get(rollData.defenderId)
|
let defender = game.actors.get(rollData.defender.id)
|
||||||
|
|
||||||
let empoignade = rollData.empoignade
|
|
||||||
empoignade.isSuccess = isSuccess;
|
|
||||||
|
|
||||||
if (isSuccess && isNouvelle) {
|
if (rollData.rolled.isSuccess && isNouvelle) {
|
||||||
|
const objectEmpoignade = rollData.empoignade.toObject();
|
||||||
// Creer l'empoignade sur attaquant/defenseur
|
// Creer l'empoignade sur attaquant/defenseur
|
||||||
await attacker.createEmbeddedDocuments('Item', [empoignade.toObject()])
|
attacker.creerObjetParMJ(objectEmpoignade);
|
||||||
await defender.createEmbeddedDocuments('Item', [empoignade.toObject()])
|
defender.creerObjetParMJ(objectEmpoignade);
|
||||||
|
}
|
||||||
|
|
||||||
|
rollData.empoignade.isSuccess = rollData.rolled.isSuccess;
|
||||||
|
if (rollData.rolled.isPart) {
|
||||||
|
rollData.particuliere = "finesse";
|
||||||
}
|
}
|
||||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-resultat.html');
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-resultat.html');
|
||||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async onDefenseEmpoignade(rollData, defenseMode, competenceName = "Corps à corps", carac = "melee") {
|
static async onDefenseEmpoignade(attackerRoll, mode, competenceName = "Corps à corps", carac = "melee") {
|
||||||
let attacker = game.actors.get(rollData.attackerId)
|
let attacker = game.actors.get(attackerRoll.attacker.id)
|
||||||
let defender = game.actors.get(rollData.defenderId)
|
let defender = game.actors.get(attackerRoll.defender.id)
|
||||||
|
if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
let empoignade = this.getEmpoignade(attacker, defender)
|
let empoignade = this.getEmpoignade(attacker, defender)
|
||||||
|
|
||||||
if (!empoignade) {
|
if (!empoignade) {
|
||||||
@@ -156,18 +268,23 @@ export class RdDEmpoignade {
|
|||||||
}
|
}
|
||||||
|
|
||||||
empoignade = duplicate(empoignade)
|
empoignade = duplicate(empoignade)
|
||||||
rollData.mode = defenseMode
|
let defenderRoll = {
|
||||||
rollData.empoignade = empoignade
|
mode, attacker, defender, empoignade, attackerRoll,
|
||||||
rollData.competence = defender.getCompetence(competenceName),
|
diffLibre: attackerRoll.diffLibre,
|
||||||
rollData.selectedCarac = defender.system.carac[carac],
|
attaqueParticuliere: attackerRoll.particuliere,
|
||||||
rollData.malusTaille = RdDEmpoignade.getMalusTaille(empoignade, defender, attacker)
|
competence: defender.getCompetence(competenceName),
|
||||||
|
surprise: defender.getSurprise(true),
|
||||||
await RdDEmpoignade.$rollDefenseEmpoignade(defender, rollData);
|
carac: defender.system.carac,
|
||||||
|
selectedCarac: defender.system.carac[carac],
|
||||||
|
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, defender, attacker),
|
||||||
|
show: {}
|
||||||
|
};
|
||||||
|
await RdDEmpoignade.$rollDefenseEmpoignade(defender, defenderRoll);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async $rollDefenseEmpoignade(defender, rollData) {
|
static async $rollDefenseEmpoignade(defender, defenderRoll) {
|
||||||
const dialog = await RdDRoll.create(defender, rollData,
|
const dialog = await RdDRoll.create(defender, defenderRoll,
|
||||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-empoignade.html' },
|
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-empoignade.html' },
|
||||||
{
|
{
|
||||||
name: 'empoignade',
|
name: 'empoignade',
|
||||||
@@ -193,12 +310,11 @@ export class RdDEmpoignade {
|
|||||||
RdDEmpoignade.$updateEtatEmpoignade(empoignade)
|
RdDEmpoignade.$updateEtatEmpoignade(empoignade)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empoignade.system.pointsemp >= 2) {
|
|
||||||
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
|
||||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-actions.html');
|
|
||||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
|
||||||
}
|
|
||||||
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-empoignade-resultat.html')
|
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-empoignade-resultat.html')
|
||||||
|
if (empoignade.system.pointsemp >= 2) {
|
||||||
|
let msg = await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-empoignade-entrainer.html');
|
||||||
|
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -223,16 +339,15 @@ export class RdDEmpoignade {
|
|||||||
let defender = game.actors.get(empoignade.system.empoigneid)
|
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||||
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
||||||
await defender.deleteEmbeddedDocuments('Item', [emp._id])
|
await defender.deleteEmbeddedDocuments('Item', [emp._id])
|
||||||
|
|
||||||
//let attacker = game.actors.get(empoignade.system.empoigneurid)
|
|
||||||
//emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
|
|
||||||
//await attacker.deleteEmbeddedDocuments('Item', [emp._id])
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async entrainerAuSol(rollData) {
|
static async entrainerAuSol(rollData) {
|
||||||
let attacker = game.actors.get(rollData.attackerId)
|
let attacker = game.actors.get(rollData.attacker.id)
|
||||||
let defender = game.actors.get(rollData.defenderId)
|
let defender = game.actors.get(rollData.defender.id)
|
||||||
|
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
let empoignade = this.getEmpoignade(attacker, defender)
|
let empoignade = this.getEmpoignade(attacker, defender)
|
||||||
|
|
||||||
empoignade.system.ausol = true
|
empoignade.system.ausol = true
|
||||||
@@ -242,25 +357,32 @@ export class RdDEmpoignade {
|
|||||||
await defender.setEffect(STATUSES.StatusProne, true);
|
await defender.setEffect(STATUSES.StatusProne, true);
|
||||||
|
|
||||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.html');
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.html');
|
||||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async projeterAuSol(rollData) {
|
static async projeterAuSol(rollData) {
|
||||||
let attacker = game.actors.get(rollData.attackerId)
|
let attacker = game.actors.get(rollData.attacker.id)
|
||||||
let defender = game.actors.get(rollData.defenderId)
|
let defender = game.actors.get(rollData.defender.id)
|
||||||
|
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
let empoignade = this.getEmpoignade(attacker, defender)
|
let empoignade = this.getEmpoignade(attacker, defender)
|
||||||
|
|
||||||
await defender.setEffect(STATUSES.StatusProne, true);
|
await defender.setEffect(STATUSES.StatusProne, true);
|
||||||
await this.$deleteEmpoignade(empoignade)
|
await this.$deleteEmpoignade(empoignade)
|
||||||
|
|
||||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-projeter-sol.html');
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-projeter-sol.html');
|
||||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async perteEndurance(rollData, perteMode) {
|
static async perteEndurance(rollData, perteMode) {
|
||||||
let attacker = game.actors.get(rollData.attackerId)
|
let attacker = game.actors.get(rollData.attacker.id)
|
||||||
let defender = game.actors.get(rollData.defenderId)
|
let defender = game.actors.get(rollData.defender.id)
|
||||||
|
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
let empoignade = this.getEmpoignade(attacker, defender)
|
let empoignade = this.getEmpoignade(attacker, defender)
|
||||||
|
|
||||||
//console.log("Perte d'endurance :!!!", perteMode)
|
//console.log("Perte d'endurance :!!!", perteMode)
|
||||||
@@ -278,7 +400,7 @@ export class RdDEmpoignade {
|
|||||||
await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4)));
|
await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4)));
|
||||||
}
|
}
|
||||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.html');
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.html');
|
||||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@@ -1,12 +1,17 @@
|
|||||||
|
import { RdDItemArme } from "./item-arme.js";
|
||||||
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||||
|
import { TYPES } from "./item.js";
|
||||||
|
|
||||||
export class RdDHotbar {
|
export class RdDHotbar {
|
||||||
|
|
||||||
static async addToHotbar(item, slot) {
|
static async createItemMacro(item, slot, armeCompetence = undefined) {
|
||||||
let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}");`;
|
const itemName = item.name;
|
||||||
let macro = game.macros.contents.find(m => (m.name === item.name) && (m.command === command));
|
let macroName = itemName + RdDHotbar.$macroNameSuffix(armeCompetence);
|
||||||
|
let command = `game.system.rdd.RdDHotbar.rollMacro("${itemName}", "${item.type}", "${armeCompetence}");`
|
||||||
|
let macro = game.macros.contents.find(m => (m.name === itemName) && (m.command === command));
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
macro = await Macro.create({
|
macro = await Macro.create({
|
||||||
name: item.name,
|
name: macroName,
|
||||||
type: "script",
|
type: "script",
|
||||||
img: item.img,
|
img: item.img,
|
||||||
command: command
|
command: command
|
||||||
@@ -15,6 +20,59 @@ export class RdDHotbar {
|
|||||||
await game.user.assignHotbarMacro(macro, slot);
|
await game.user.assignHotbarMacro(macro, slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static $macroNameSuffix(armeCompetence) {
|
||||||
|
switch (armeCompetence) {
|
||||||
|
case 'unemain': return ' (1 main)';
|
||||||
|
case 'deuxmains': return ' (2 main)';
|
||||||
|
case 'tir': return ' (tir)';
|
||||||
|
case 'lancer': return ' (lancer)';
|
||||||
|
case 'pugilat': return ' (pugilat)';
|
||||||
|
case 'empoignade': return ' (empoignade)';
|
||||||
|
|
||||||
|
}
|
||||||
|
return ''
|
||||||
|
}
|
||||||
|
|
||||||
|
static async addToHotbar(item, slot) {
|
||||||
|
switch (item?.type ?? '') {
|
||||||
|
case TYPES.arme:
|
||||||
|
{
|
||||||
|
// Les armes peuvent avoir plusieurs usages
|
||||||
|
if (item.system.competence != '') {
|
||||||
|
if (item.system.unemain) {
|
||||||
|
await this.createItemMacro(item, slot++, 'unemain')
|
||||||
|
}
|
||||||
|
if (item.system.deuxmains) {
|
||||||
|
await this.createItemMacro(item, slot++, 'deuxmains')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (item.system.lancer != '') {
|
||||||
|
await this.createItemMacro(item, slot++, 'lancer')
|
||||||
|
}
|
||||||
|
if (item.system.tir != '') {
|
||||||
|
await this.createItemMacro(item, slot++, 'lancer')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
|
case TYPES.competencecreature:
|
||||||
|
const categorie = RdDItemCompetenceCreature.getCategorieAttaque(item) ?? 'competence';
|
||||||
|
await this.createItemMacro(item, slot, categorie)
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
case TYPES.competence:
|
||||||
|
await this.createItemMacro(item, slot++, 'competence')
|
||||||
|
if (item.isCorpsACorps()) {
|
||||||
|
await this.createItemMacro(item, slot++, 'pugilat')
|
||||||
|
await this.createItemMacro(item, slot++, 'empoignade')
|
||||||
|
}
|
||||||
|
if (item.isCompetenceArme()) {
|
||||||
|
ui.notifications.info(`${item.name} est une compétence d'arme, la macro n'est pas liée à un arme.<br>
|
||||||
|
Créez la macro depuis l'arme ou l'onglet combat pour garder les automatisations de combat.`);
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a macro when dropping an entity on the hotbar
|
* Create a macro when dropping an entity on the hotbar
|
||||||
* Item - open roll dialog for item
|
* Item - open roll dialog for item
|
||||||
@@ -23,20 +81,19 @@ export class RdDHotbar {
|
|||||||
*/
|
*/
|
||||||
static initDropbar() {
|
static initDropbar() {
|
||||||
|
|
||||||
Hooks.on("hotbarDrop", (bar, documentData, slot) => {
|
Hooks.on('hotbarDrop', (bar, documentData, slot) => {
|
||||||
|
|
||||||
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill
|
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill
|
||||||
if (documentData.type == "Item") {
|
if (documentData.type == 'Item') {
|
||||||
let item = fromUuidSync(documentData.uuid)
|
const item = fromUuidSync(documentData.uuid) ?? this.actor.items.get(documentData.uuid)
|
||||||
if (item == undefined) {
|
console.log('DROP', documentData, item)
|
||||||
item = this.actor.items.get(documentData.uuid)
|
switch (item?.type) {
|
||||||
|
case TYPES.arme:
|
||||||
|
case TYPES.competence:
|
||||||
|
case TYPES.competencecreature:
|
||||||
|
this.addToHotbar(item, slot)
|
||||||
|
return false
|
||||||
}
|
}
|
||||||
console.log("DROP", documentData, item)
|
|
||||||
if (!item || (item.type != "arme" && item.type != "competence")) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
this.addToHotbar(item, slot)
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
return true
|
||||||
@@ -44,12 +101,14 @@ export class RdDHotbar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Roll macro */
|
/** Roll macro */
|
||||||
static rollMacro(itemName, itemType, bypassData) {
|
static rollMacro(itemName, itemType, categorieArme = 'competence') {
|
||||||
const speaker = ChatMessage.getSpeaker();
|
const speaker = ChatMessage.getSpeaker();
|
||||||
let actor;
|
let actor;
|
||||||
if (speaker.token) actor = game.actors.tokens[speaker.token];
|
if (speaker.token) actor = game.actors.tokens[speaker.token];
|
||||||
if (!actor) actor = game.actors.get(speaker.actor);
|
if (!actor) actor = game.actors.get(speaker.actor);
|
||||||
|
if (!actor) {
|
||||||
|
return ui.notifications.warn(`Impossible de trouver le personnage concerné`);
|
||||||
|
}
|
||||||
let item = actor?.items.find(it => it.name === itemName && it.type == itemType) ?? undefined;
|
let item = actor?.items.find(it => it.name === itemName && it.type == itemType) ?? undefined;
|
||||||
if (!item) {
|
if (!item) {
|
||||||
return ui.notifications.warn(`Impossible de trouver l'objet de cette macro`);
|
return ui.notifications.warn(`Impossible de trouver l'objet de cette macro`);
|
||||||
@@ -57,10 +116,23 @@ export class RdDHotbar {
|
|||||||
|
|
||||||
// Trigger the item roll
|
// Trigger the item roll
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case "arme":
|
case TYPES.arme:
|
||||||
return actor.rollArme(item);
|
return actor.rollArme(item, categorieArme);
|
||||||
case "competence":
|
case TYPES.competence:
|
||||||
return actor.rollCompetence(itemName);
|
if (item.isCorpsACorps()) {
|
||||||
|
switch (categorieArme) {
|
||||||
|
case 'pugilat':
|
||||||
|
return actor.rollArme(RdDItemArme.mainsNues(actor), 'competence');
|
||||||
|
case 'empoignade':
|
||||||
|
return actor.rollArme(RdDItemArme.empoignade(actor), 'competence');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return actor.rollCompetence(item);
|
||||||
|
case TYPES.competencecreature:
|
||||||
|
return item.system.iscombat && !item.system.isparade
|
||||||
|
? actor.rollArme(item, categorieArme)
|
||||||
|
: actor.rollCompetence(item);
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -15,7 +15,7 @@ import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
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 { ReglesOptionnelles } from "./settings/regles-optionnelles.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";
|
||||||
@@ -29,11 +29,13 @@ import { Environnement } from "./environnement.js";
|
|||||||
import { RdDActor } from "./actor.js";
|
import { RdDActor } from "./actor.js";
|
||||||
import { RdDBaseActor } from "./actor/base-actor.js";
|
import { RdDBaseActor } from "./actor/base-actor.js";
|
||||||
import { RdDCommerce } from "./actor/commerce.js";
|
import { RdDCommerce } from "./actor/commerce.js";
|
||||||
|
import { RdDEntite } from "./actor/entite.js";
|
||||||
|
import { RdDVehicule } from "./actor/vehicule.js";
|
||||||
import { RdDActorSheet } from "./actor-sheet.js";
|
import { RdDActorSheet } from "./actor-sheet.js";
|
||||||
import { RdDCommerceSheet } from "./actor/commerce-sheet.js";
|
import { RdDCommerceSheet } from "./actor/commerce-sheet.js";
|
||||||
import { RdDActorCreatureSheet } from "./actor-creature-sheet.js";
|
import { RdDCreatureSheet } from "./actor/creature-sheet.js";
|
||||||
import { RdDActorVehiculeSheet } from "./actor-vehicule-sheet.js";
|
import { RdDActorEntiteSheet } from "./actor/entite-sheet.js";
|
||||||
import { RdDActorEntiteSheet } from "./actor-entite-sheet.js";
|
import { RdDActorVehiculeSheet } from "./actor/vehicule-sheet.js";
|
||||||
|
|
||||||
import { RdDItem } from "./item.js";
|
import { RdDItem } from "./item.js";
|
||||||
import { RdDItemBlessure } from "./item/blessure.js";
|
import { RdDItemBlessure } from "./item/blessure.js";
|
||||||
@@ -59,6 +61,8 @@ import { RdDSigneDraconiqueItemSheet } from "./item/sheet-signedraconique.js";
|
|||||||
import { RdDItemInventaireSheet } from "./item/sheet-base-inventaire.js";
|
import { RdDItemInventaireSheet } from "./item/sheet-base-inventaire.js";
|
||||||
import { AppAstrologie } from "./sommeil/app-astrologie.js";
|
import { AppAstrologie } from "./sommeil/app-astrologie.js";
|
||||||
import { RdDItemArmure } from "./item/armure.js";
|
import { RdDItemArmure } from "./item/armure.js";
|
||||||
|
import { AutoAdjustDarkness as AutoAdjustDarkness } from "./time/auto-adjust-darkness.js";
|
||||||
|
import { RdDCreature } from "./actor/creature.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RdD system
|
* RdD system
|
||||||
@@ -90,10 +94,10 @@ export class SystemReveDeDragon {
|
|||||||
}
|
}
|
||||||
this.actorClasses = {
|
this.actorClasses = {
|
||||||
commerce: RdDCommerce,
|
commerce: RdDCommerce,
|
||||||
creature: RdDActor,
|
creature: RdDCreature,
|
||||||
entite: RdDActor,
|
entite: RdDEntite,
|
||||||
personnage: RdDActor,
|
personnage: RdDActor,
|
||||||
vehicule: RdDActor,
|
vehicule: RdDVehicule,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +153,7 @@ export class SystemReveDeDragon {
|
|||||||
Actors.unregisterSheet("core", ActorSheet);
|
Actors.unregisterSheet("core", ActorSheet);
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDCommerceSheet, { types: ["commerce"], makeDefault: true });
|
Actors.registerSheet(SYSTEM_RDD, RdDCommerceSheet, { types: ["commerce"], makeDefault: true });
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true });
|
Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true });
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDActorCreatureSheet, { types: ["creature"], makeDefault: true });
|
Actors.registerSheet(SYSTEM_RDD, RdDCreatureSheet, { types: ["creature"], makeDefault: true });
|
||||||
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);
|
||||||
@@ -182,11 +186,12 @@ export class SystemReveDeDragon {
|
|||||||
CONFIG.Combat.documentClass = RdDCombatManager;
|
CONFIG.Combat.documentClass = RdDCombatManager;
|
||||||
|
|
||||||
// préparation des différents modules
|
// préparation des différents modules
|
||||||
|
AutoAdjustDarkness.init();
|
||||||
RdDTimestamp.init();
|
RdDTimestamp.init();
|
||||||
RdDCalendrier.init();
|
RdDCalendrier.init();
|
||||||
SystemCompendiums.init();
|
SystemCompendiums.init();
|
||||||
DialogChronologie.init();
|
DialogChronologie.init();
|
||||||
ReglesOptionelles.init();
|
ReglesOptionnelles.init();
|
||||||
RdDUtility.init();
|
RdDUtility.init();
|
||||||
RdDDice.init();
|
RdDDice.init();
|
||||||
RdDCommands.init();
|
RdDCommands.init();
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
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";
|
import { Targets } from "./targets.js";
|
||||||
|
import { TYPES } from "./item.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* On part du principe qu'une entité démarre tjs
|
/* On part du principe qu'une entité démarre tjs
|
||||||
@@ -20,9 +20,9 @@ export class RdDPossession {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static searchPossessionFromEntite(attacker, defender) {
|
static searchPossessionFromEntite(attacker, defender) {
|
||||||
let poss = attacker.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id);
|
let poss = attacker.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id);
|
||||||
if (!poss) {
|
if (!poss) {
|
||||||
poss = defender.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id);
|
poss = defender.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id);
|
||||||
}
|
}
|
||||||
return poss && duplicate(poss) || undefined;
|
return poss && duplicate(poss) || undefined;
|
||||||
}
|
}
|
||||||
@@ -31,13 +31,13 @@ export class RdDPossession {
|
|||||||
static async onAttaquePossession(target, attacker, competence, suitePossession = undefined) {
|
static async onAttaquePossession(target, attacker, competence, suitePossession = undefined) {
|
||||||
const defender = target.actor;
|
const defender = target.actor;
|
||||||
const fromEntite = RdDPossession.searchPossessionFromEntite(attacker, defender);
|
const fromEntite = RdDPossession.searchPossessionFromEntite(attacker, defender);
|
||||||
const isNouvelle = !suitePossession && ! fromEntite;
|
const isNouvelle = !suitePossession && !fromEntite;
|
||||||
const possession = (suitePossession ?? fromEntite ?? (await RdDPossession.createPossession(attacker, defender)));
|
const possession = (suitePossession ?? fromEntite ?? (await RdDPossession.createPossession(attacker, defender)));
|
||||||
|
|
||||||
RdDPossession.$updateEtatPossession(possession)
|
RdDPossession.$updateEtatPossession(possession)
|
||||||
|
|
||||||
let rollData = {
|
let rollData = {
|
||||||
mode: "possession",
|
mode: "attaque",
|
||||||
isECNIDefender: false,
|
isECNIDefender: false,
|
||||||
competence: competence,
|
competence: competence,
|
||||||
possession: possession,
|
possession: possession,
|
||||||
@@ -45,25 +45,26 @@ export class RdDPossession {
|
|||||||
defender: defender,
|
defender: defender,
|
||||||
targetToken: Targets.extractTokenData(target)
|
targetToken: Targets.extractTokenData(target)
|
||||||
};
|
};
|
||||||
if (attacker.isCreatureEntite()) {
|
RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker)
|
||||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
|
||||||
}
|
|
||||||
|
|
||||||
await RdDPossession.$rollAttaquePossession(attacker, rollData, isNouvelle);
|
await RdDPossession.$rollAttaquePossession(attacker, rollData, isNouvelle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async onConjurerPossession(attacker, competence, possession) {
|
static async onConjurerPossession(attacker, possession) {
|
||||||
possession = duplicate(possession);
|
possession = duplicate(possession);
|
||||||
RdDPossession.$updateEtatPossession(possession)
|
RdDPossession.$updateEtatPossession(possession)
|
||||||
|
|
||||||
|
const defender = game.actors.get(possession.system.entite.actorid);
|
||||||
let rollData = {
|
let rollData = {
|
||||||
mode: "possession",
|
mode: "attaque",
|
||||||
isECNIDefender: true,
|
isECNIDefender: true,
|
||||||
competence: competence,
|
|
||||||
possession: possession,
|
possession: possession,
|
||||||
attacker: attacker,
|
attacker: attacker,
|
||||||
defender: game.actors.get(possession.system.possesseurid)
|
defender: defender,
|
||||||
};
|
};
|
||||||
|
RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker)
|
||||||
|
|
||||||
await RdDPossession.$rollAttaquePossession(attacker, rollData);
|
await RdDPossession.$rollAttaquePossession(attacker, rollData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,7 +72,7 @@ export class RdDPossession {
|
|||||||
static async onDefensePossession(attackerId, defenderId, possessionId) {
|
static async onDefensePossession(attackerId, defenderId, possessionId) {
|
||||||
let attacker = game.actors.get(attackerId)
|
let attacker = game.actors.get(attackerId)
|
||||||
let possession = attacker?.getPossession(possessionId)
|
let possession = attacker?.getPossession(possessionId)
|
||||||
defenderId = defenderId ?? possession?.system.possesseurid ?? undefined
|
defenderId = defenderId ?? possession?.system.entite.actorid ?? undefined
|
||||||
let defender = game.actors.get(defenderId)
|
let defender = game.actors.get(defenderId)
|
||||||
possession = possession ?? defender?.getPossession(possessionId) ?? undefined;
|
possession = possession ?? defender?.getPossession(possessionId) ?? undefined;
|
||||||
|
|
||||||
@@ -82,20 +83,30 @@ export class RdDPossession {
|
|||||||
possession = duplicate(possession)
|
possession = duplicate(possession)
|
||||||
// Update for draconic roll
|
// Update for draconic roll
|
||||||
let rollData = {
|
let rollData = {
|
||||||
mode: "conjuration",
|
mode: "defense",
|
||||||
isECNIDefender: defender.type == "entite",
|
isECNIDefender: defender.type == "entite",
|
||||||
possession: possession,
|
possession: possession,
|
||||||
attacker: attacker,
|
attacker: attacker,
|
||||||
defender: defender,
|
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'
|
RdDPossession.selectCompetenceDraconicOuPossession(rollData, defender)
|
||||||
|
rollData.diffLibre = RdDPossession.getInfoAttaque(rollData).diffLibre
|
||||||
|
|
||||||
await RdDPossession.$rollDefensePossession(defender, rollData);
|
await RdDPossession.$rollDefensePossession(defender, rollData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
|
||||||
|
rollData.competence = rollingActor.getDraconicOuPossession();
|
||||||
|
if (rollingActor.isCreatureEntite()) {
|
||||||
|
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
rollData.selectedCarac = rollingActor.system.carac.reve
|
||||||
|
rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } }
|
||||||
|
rollData.competence.system.defaut_carac = 'reve-actuel'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) {
|
static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) {
|
||||||
const dialog = await RdDRoll.create(attacker, rollData,
|
const dialog = await RdDRoll.create(attacker, rollData,
|
||||||
@@ -104,21 +115,22 @@ export class RdDPossession {
|
|||||||
name: 'jet-possession',
|
name: 'jet-possession',
|
||||||
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',
|
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',
|
||||||
callbacks: [
|
callbacks: [
|
||||||
{ condition: r => (r.rolled.isSuccess), action: async (r) => await RdDPossession.$onRollPossession(r, true, isNouvelle) },
|
{ action: async (r) => await RdDPossession.$onRollPossession(r, isNouvelle) },
|
||||||
{ condition: r => (r.rolled.isEchec), action: async (r) => await RdDPossession.$onRollPossession(r, false, isNouvelle) },
|
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async $onRollPossession(rollData, isSuccess, isNouvelle = false) {
|
static async $onRollPossession(rollData, isNouvelle = false) {
|
||||||
rollData.possession.isSuccess = isSuccess;
|
rollData.possession.isSuccess = rollData.rolled.isSuccess;
|
||||||
RdDPossession.$updateEtatPossession(rollData.possession);
|
RdDPossession.$updateEtatPossession(rollData.possession, rollData);
|
||||||
if (isNouvelle) {
|
if (isNouvelle) {
|
||||||
// Creer la possession sur le defenseur
|
// Creer la possession sur le defenseur
|
||||||
rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()])
|
await rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()])
|
||||||
}
|
}
|
||||||
|
const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid)
|
||||||
|
RdDPossession.storePossessionAttaque(possession, rollData)
|
||||||
await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html');
|
await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +139,7 @@ export class RdDPossession {
|
|||||||
const dialog = await RdDRoll.create(defender, rollData,
|
const dialog = await RdDRoll.create(defender, rollData,
|
||||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html' },
|
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html' },
|
||||||
{
|
{
|
||||||
name: 'conjurer',
|
name: 'possession',
|
||||||
label: 'Conjurer une Possession',
|
label: 'Conjurer une Possession',
|
||||||
callbacks: [
|
callbacks: [
|
||||||
{ action: async (r) => await RdDPossession.$onRollConjuration(r) }
|
{ action: async (r) => await RdDPossession.$onRollConjuration(r) }
|
||||||
@@ -139,23 +151,30 @@ export class RdDPossession {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async $onRollConjuration(rollData) {
|
static async $onRollConjuration(rollData) {
|
||||||
let actor = game.actors.get(rollData.possession.system.possedeid)
|
let victime = game.actors.get(rollData.possession.system.victime.actorid)
|
||||||
|
let compteur = rollData.possession.system.compteur
|
||||||
if (!rollData.rolled.isSuccess) {
|
if (!rollData.rolled.isSuccess) {
|
||||||
if (rollData.isECNIDefender) {
|
if (rollData.isECNIDefender) {
|
||||||
rollData.possession.system.compteur--
|
compteur--
|
||||||
} else {
|
} else {
|
||||||
rollData.possession.system.compteur++
|
compteur++
|
||||||
}
|
}
|
||||||
let update = { _id: rollData.possession._id, "system.compteur": rollData.possession.system.compteur }
|
|
||||||
await actor.updateEmbeddedDocuments('Item', [update])
|
|
||||||
}
|
}
|
||||||
|
const possession = victime.getPossession(rollData.possession.system.possessionid)
|
||||||
|
await possession.update({
|
||||||
|
system: {
|
||||||
|
compteur: compteur,
|
||||||
|
entite: { diffLibre: 0, finesse: false },
|
||||||
|
victime: { diffLibre: 0, finesse: false }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
rollData.possession = possession
|
||||||
RdDPossession.$updateEtatPossession(rollData.possession)
|
RdDPossession.$updateEtatPossession(rollData.possession)
|
||||||
|
|
||||||
await RdDResolutionTable.displayRollData(rollData,rollData.defender, 'chat-resultat-possession.html')
|
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html')
|
||||||
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
|
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
|
||||||
// conjuration
|
// conjuration
|
||||||
actor.deleteEmbeddedDocuments("Item", [rollData.possession._id])
|
victime.deleteEmbeddedDocuments("Item", [rollData.possession._id])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -180,13 +199,43 @@ export class RdDPossession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static isPossessionFinesse(rollData) {
|
||||||
|
return RdDPossession.getInfoAttaque(rollData).finesse
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static getInfoAttaque(rollData) {
|
||||||
|
return rollData.possession.system[rollData.isECNIDefender ? 'victime' : 'entite'];
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static isDefensePossession(rollData) {
|
||||||
|
return rollData.possession && rollData.mode == "defense"
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static storePossessionAttaque(possession, rollData = undefined) {
|
||||||
|
const attaquant = rollData?.isECNIDefender ? 'victime' : 'entite'
|
||||||
|
possession.update({
|
||||||
|
[`system.${attaquant}`]: {
|
||||||
|
diffLibre: rollData?.diffLibre ?? 0,
|
||||||
|
finesse: rollData?.rolled.isPart ?? false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async createPossession(attacker, defender) {
|
static async createPossession(attacker, defender) {
|
||||||
return await Item.create({
|
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),
|
||||||
|
entite: { actorid: attacker.id },
|
||||||
|
victime: { actorid: defender.id },
|
||||||
|
compteur: 0
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
temporary: true
|
temporary: true
|
||||||
})
|
})
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* difficultés au delà de -10
|
* difficultés au delà de -10
|
||||||
@@ -28,7 +28,7 @@ const reussites = [
|
|||||||
|
|
||||||
const reussiteInsuffisante = { code: "notSign", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: false, isETotal: false, ptTache: 0, ptQualite: -2, quality: "Réussite insuffisante", condition: (target, roll) => false }
|
const reussiteInsuffisante = { code: "notSign", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: false, isETotal: false, ptTache: 0, ptQualite: -2, quality: "Réussite insuffisante", condition: (target, roll) => false }
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const caracMaximumResolution = 60;
|
const CARAC_MAXIMUM_RESOLUTION = 40;
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDResolutionTable {
|
export class RdDResolutionTable {
|
||||||
static resolutionTable = this.build()
|
static resolutionTable = this.build()
|
||||||
@@ -36,7 +36,7 @@ export class RdDResolutionTable {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static build() {
|
static build() {
|
||||||
let table = []
|
let table = []
|
||||||
for (var caracValue = 0; caracValue <= caracMaximumResolution; caracValue++) {
|
for (var caracValue = 0; caracValue <= CARAC_MAXIMUM_RESOLUTION; caracValue++) {
|
||||||
table[caracValue] = this._computeRow(caracValue);
|
table[caracValue] = this._computeRow(caracValue);
|
||||||
}
|
}
|
||||||
return table;
|
return table;
|
||||||
@@ -91,13 +91,17 @@ export class RdDResolutionTable {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
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(RdDResolutionTable.actorChatName(actor), {
|
||||||
content: await RdDResolutionTable.buildRollDataHtml(rollData, actor, template)
|
content: await RdDResolutionTable.buildRollDataHtml(rollData, template)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static actorChatName(actor) {
|
||||||
|
return actor?.userName ?? game.user.name;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async buildRollDataHtml(rollData, actor, template = 'chat-resultat-general.html') {
|
static async buildRollDataHtml(rollData, template = 'chat-resultat-general.html') {
|
||||||
rollData.show = rollData.show || {};
|
rollData.show = rollData.show || {};
|
||||||
return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/${template}`, rollData);
|
return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/${template}`, rollData);
|
||||||
}
|
}
|
||||||
@@ -122,7 +126,7 @@ export class RdDResolutionTable {
|
|||||||
rolled.bonus = rollData.bonus;
|
rolled.bonus = rollData.bonus;
|
||||||
rolled.factorHtml = Misc.getFractionHtml(rollData.diviseurSignificative);
|
rolled.factorHtml = Misc.getFractionHtml(rollData.diviseurSignificative);
|
||||||
|
|
||||||
if (ReglesOptionelles.isUsing("afficher-colonnes-reussite")) {
|
if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) {
|
||||||
rolled.niveauNecessaire = this.findNiveauNecessaire(caracValue, rolled.roll);
|
rolled.niveauNecessaire = this.findNiveauNecessaire(caracValue, rolled.roll);
|
||||||
rolled.ajustementNecessaire = rolled.niveauNecessaire - finalLevel;
|
rolled.ajustementNecessaire = rolled.niveauNecessaire - finalLevel;
|
||||||
}
|
}
|
||||||
|
@@ -112,7 +112,7 @@ export class RdDRollResolutionTable extends Dialog {
|
|||||||
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 = Misc.toInt(rollData.diffConditions) + Misc.toInt(rollData.diffLibre);
|
||||||
|
|
||||||
const htmlTable = await RdDResolutionTable.buildHTMLTable({
|
const htmlTable = await RdDResolutionTable.buildHTMLTable({
|
||||||
carac: rollData.caracValue,
|
carac: rollData.caracValue,
|
||||||
@@ -129,12 +129,6 @@ export class RdDRollResolutionTable extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_computeFinalLevel(rollData) {
|
|
||||||
const diffConditions = Misc.toInt(rollData.diffConditions);
|
|
||||||
const diffLibre = Misc.toInt(rollData.diffLibre);
|
|
||||||
|
|
||||||
return diffLibre + diffConditions;
|
|
||||||
}
|
|
||||||
|
|
||||||
async close() {
|
async close() {
|
||||||
await super.close();
|
await super.close();
|
||||||
|
@@ -6,7 +6,7 @@ import { Misc } from "./misc.js";
|
|||||||
import { RdDBonus } from "./rdd-bonus.js";
|
import { RdDBonus } from "./rdd-bonus.js";
|
||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the base Dialog entity to select roll parameters
|
* Extend the base Dialog entity to select roll parameters
|
||||||
@@ -22,7 +22,7 @@ export class RdDRoll extends Dialog {
|
|||||||
|
|
||||||
const html = await renderTemplate(dialogConfig.html, rollData);
|
const html = await renderTemplate(dialogConfig.html, rollData);
|
||||||
|
|
||||||
let options = { classes: ["rdd-roll-dialog"], width: 600, height: 'fit-content', 'z-index': 99999, close: html => {} };
|
let options = { classes: ["rdd-roll-dialog"], width: 650, height: 'fit-content', 'z-index': 99999, close: html => {} };
|
||||||
if (dialogConfig.close) {
|
if (dialogConfig.close) {
|
||||||
options.close = dialogConfig.close;
|
options.close = dialogConfig.close;
|
||||||
}
|
}
|
||||||
@@ -50,8 +50,6 @@ export class RdDRoll extends Dialog {
|
|||||||
encTotal: true
|
encTotal: true
|
||||||
},
|
},
|
||||||
isMalusEncombrementTotal: RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
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),
|
||||||
@@ -85,7 +83,7 @@ export class RdDRoll extends Dialog {
|
|||||||
if (RdDBonus.isDefenseAttaqueFinesse(rollData)) {
|
if (RdDBonus.isDefenseAttaqueFinesse(rollData)) {
|
||||||
facteurSign *= 2;
|
facteurSign *= 2;
|
||||||
}
|
}
|
||||||
if (!ReglesOptionelles.isUsing('tripleSignificative')) {
|
if (!ReglesOptionnelles.isUsing('tripleSignificative')) {
|
||||||
facteurSign = Math.min(facteurSign, 4);
|
facteurSign = Math.min(facteurSign, 4);
|
||||||
}
|
}
|
||||||
return facteurSign;
|
return facteurSign;
|
||||||
@@ -187,7 +185,7 @@ export class RdDRoll extends Dialog {
|
|||||||
console.log("RdDRollSelectDialog - Cout reve", ptreve);
|
console.log("RdDRollSelectDialog - Cout reve", ptreve);
|
||||||
this.updateRollResult(html);
|
this.updateRollResult(html);
|
||||||
});
|
});
|
||||||
this.html.find("[name='coupsNonMortels']").change((event) => {
|
this.html.find("input.check-mortalite").change((event) => {
|
||||||
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
|
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
|
||||||
this.updateRollResult(html);
|
this.updateRollResult(html);
|
||||||
});
|
});
|
||||||
@@ -291,22 +289,14 @@ export class RdDRoll extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async updateRollResult(html) {
|
async updateRollResult(html) {
|
||||||
let rollData = this.rollData;
|
const 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())
|
||||||
rollData.caracValue = parseInt(rollData.selectedCarac.value)
|
rollData.caracValue = parseInt(rollData.selectedCarac.value)
|
||||||
rollData.mortalite = rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite ?? 'mortel';
|
rollData.dmg.mortalite = rollData.dmg.mortalite ?? 'mortel';
|
||||||
rollData.coupsNonMortels = (rollData.attackerRoll?.dmg.mortalite ?? rollData.dmg.mortalite) == 'non-mortel';
|
|
||||||
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);
|
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);
|
||||||
let dmgText = Misc.toSignedString(rollData.dmg.total);
|
|
||||||
|
|
||||||
switch (rollData.mortalite) {
|
|
||||||
case 'non-mortel': dmgText = `(${dmgText}) non-mortel`; break;
|
|
||||||
case 'empoignade': dmgText = `empoignade`; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
RollDataAjustements.calcul(rollData, this.actor);
|
RollDataAjustements.calcul(rollData, this.actor);
|
||||||
rollData.finalLevel = this._computeFinalLevel(rollData);
|
|
||||||
|
|
||||||
const resolutionTable = await RdDResolutionTable.buildHTMLTable(RdDResolutionTable.subTable(rollData.caracValue, rollData.finalLevel))
|
const resolutionTable = await RdDResolutionTable.buildHTMLTable(RdDResolutionTable.subTable(rollData.caracValue, rollData.finalLevel))
|
||||||
const adjustements = await this.buildAjustements(rollData);
|
const adjustements = await this.buildAjustements(rollData);
|
||||||
@@ -314,13 +304,16 @@ export class RdDRoll extends Dialog {
|
|||||||
HtmlUtility.showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac));
|
HtmlUtility.showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac));
|
||||||
HtmlUtility.showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac));
|
HtmlUtility.showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac));
|
||||||
HtmlUtility.showControlWhen(this.html.find(".utilisation-moral"), rollData.use.appelAuMoral);
|
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);
|
HtmlUtility.showControlWhen(this.html.find(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
||||||
|
// HtmlUtility.showControlWhen(this.html.find(".diffMoral"), rollData.ajustements.moral.used);
|
||||||
|
|
||||||
// Mise à jour valeurs
|
// Mise à jour valeurs
|
||||||
this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
|
this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
|
||||||
this.html.find("[name='coupsNonMortels']").prop('checked', rollData.mortalite == 'non-mortel');
|
this.html.find("input.check-mortalite").prop('checked', rollData.dmg.mortalite == 'non-mortel');
|
||||||
this.html.find(".dmg-arme-actor").text(dmgText);
|
this.html.find("label.dmg-arme-actor").text(rollData.dmg.mortalite == 'empoignade'? 'empoignade': Misc.toSignedString(rollData.dmg.total) );
|
||||||
|
this.html.find("label.arme-mortalite").text(rollData.dmg.mortalite);
|
||||||
|
// this.html.find("[name='dmg-arme-actor']").text(rollData.dmg.mortalite == 'empoignade'? 'empoignade': Misc.toSignedString(rollData.dmg.total) );
|
||||||
|
// this.html.find("[name='arme-mortalite']").text(rollData.dmg.mortalite);
|
||||||
this.html.find("div.placeholder-ajustements").empty().append(adjustements);
|
this.html.find("div.placeholder-ajustements").empty().append(adjustements);
|
||||||
this.html.find("div.placeholder-resolution").empty().append(resolutionTable)
|
this.html.find("div.placeholder-resolution").empty().append(resolutionTable)
|
||||||
}
|
}
|
||||||
@@ -331,30 +324,6 @@ export class RdDRoll extends Dialog {
|
|||||||
return 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
_computeFinalLevel(rollData) {
|
|
||||||
return RollDataAjustements.sum(rollData.ajustements);
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
_computeDiffCompetence(rollData) {
|
|
||||||
if (rollData.competence) {
|
|
||||||
return Misc.toInt(rollData.competence.system.niveau);
|
|
||||||
}
|
|
||||||
if (rollData.draconicList) {
|
|
||||||
return Misc.toInt(rollData.competence.system.niveau);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
_computeMalusArmure(rollData) {
|
|
||||||
let malusArmureValue = 0;
|
|
||||||
if (rollData.malusArmureValue && (rollData.selectedCarac.label == "Agilité" || rollData.selectedCarac.label == "Dérobée")) {
|
|
||||||
malusArmureValue = rollData.malusArmureValue;
|
|
||||||
}
|
|
||||||
return malusArmureValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_getTitle(rollData) {
|
_getTitle(rollData) {
|
||||||
const carac = rollData.selectedCarac.label;
|
const carac = rollData.selectedCarac.label;
|
||||||
@@ -362,16 +331,19 @@ export class RdDRoll extends Dialog {
|
|||||||
return carac;
|
return carac;
|
||||||
}
|
}
|
||||||
const compName = rollData.competence.name;
|
const compName = rollData.competence.name;
|
||||||
if (rollData.draconicList && rollData.selectedSort) {
|
|
||||||
return compName + " - " + rollData.selectedSort.name;
|
|
||||||
}
|
|
||||||
// If a weapon is there, add it in the title
|
|
||||||
const niveau = Misc.toSignedString(rollData.competence.system.niveau)
|
const niveau = Misc.toSignedString(rollData.competence.system.niveau)
|
||||||
if (compName == carac) {
|
if (compName == carac) {
|
||||||
// cas des créatures
|
// cas des créatures
|
||||||
return carac + " Niveau " + niveau
|
return `${carac} Niveau ${niveau}`
|
||||||
}
|
}
|
||||||
const armeTitle = (rollData.arme) ? " (" + rollData.arme.name + ") " : "";
|
if (rollData.draconicList && rollData.selectedSort) {
|
||||||
return carac + "/" + compName + armeTitle + " Niveau " + niveau
|
// cas de lancer de sort
|
||||||
|
return `${rollData.competence.name} Niveau ${niveau} ${rollData.selectedSort.name}`
|
||||||
|
}
|
||||||
|
if (rollData.arme && rollData.arme.name != compName) {
|
||||||
|
// ajouter l'arme au titre si son nom n'est pas la compétence
|
||||||
|
return `${carac} / ${compName} (${rollData.arme.name}) Niveau ${niveau}`
|
||||||
|
}
|
||||||
|
return `${carac} / ${compName} Niveau ${niveau}`
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,6 @@ import { SHOW_DICE } from "./constants.js";
|
|||||||
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.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 { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
@@ -12,7 +11,7 @@ import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
|||||||
import { PixiTMR } from "./tmr/pixi-tmr.js";
|
import { PixiTMR } from "./tmr/pixi-tmr.js";
|
||||||
import { Draconique } from "./tmr/draconique.js";
|
import { Draconique } from "./tmr/draconique.js";
|
||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { STATUSES } from "./settings/status-effects.js";
|
import { STATUSES } from "./settings/status-effects.js";
|
||||||
import { RdDRencontre } from "./item/rencontre.js";
|
import { RdDRencontre } from "./item/rencontre.js";
|
||||||
@@ -39,14 +38,16 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
title: "Terres Médianes de Rêve",
|
title: "Terres Médianes de Rêve",
|
||||||
content: html,
|
content: html,
|
||||||
buttons: {
|
buttons: {
|
||||||
closeButton: { label: "Fermer", callback: html => this.close(html) }
|
closeButton: {
|
||||||
|
label: "Fermer", callback: html => this.close()
|
||||||
|
}
|
||||||
},
|
},
|
||||||
default: "closeButton"
|
default: "closeButton"
|
||||||
}
|
}
|
||||||
|
|
||||||
const dialogOptions = {
|
const dialogOptions = {
|
||||||
classes: ["tmrdialog"],
|
classes: ["tmrdialog"],
|
||||||
width: 920, height: 980,
|
width: 920, maxheight: 1024, height: 'fit-content',
|
||||||
'z-index': 40
|
'z-index': 40
|
||||||
}
|
}
|
||||||
super(dialogConf, dialogOptions);
|
super(dialogConf, dialogOptions);
|
||||||
@@ -55,15 +56,15 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
this.actor = actor;
|
this.actor = actor;
|
||||||
this.actor.tmrApp = this; // reference this app in the actor structure
|
this.actor.tmrApp = this; // reference this app in the actor structure
|
||||||
this.viewOnly = tmrData.mode == "visu"
|
this.viewOnly = tmrData.mode == "visu"
|
||||||
this.fatigueParCase = this.viewOnly || !ReglesOptionelles.isUsing("appliquer-fatigue") ? 0 : this.actor.getTMRFatigue();
|
this.fatigueParCase = this.viewOnly ? 0 : this.actor.getCoutFatigueTMR();
|
||||||
this.cumulFatigue = 0;
|
this.cumulFatigue = 0;
|
||||||
this.loadRencontres();
|
this.loadRencontres();
|
||||||
this.loadCasesSpeciales();
|
this.loadCasesSpeciales();
|
||||||
this.allTokens = [];
|
this.allTokens = [];
|
||||||
this.rencontreState = 'aucune';
|
this.rencontreState = 'aucune';
|
||||||
this.pixiApp = new PIXI.Application({ width: 720, height: 860 });
|
this.pixiTMR = new PixiTMR(this);
|
||||||
|
|
||||||
this.pixiTMR = new PixiTMR(this, this.pixiApp);
|
this.subdialog = undefined
|
||||||
|
|
||||||
this.callbacksOnAnimate = [];
|
this.callbacksOnAnimate = [];
|
||||||
if (!this.viewOnly) {
|
if (!this.viewOnly) {
|
||||||
@@ -74,6 +75,31 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
this.pixiTMR.load((loader, resources) => this.createPixiSprites());
|
this.pixiTMR.load((loader, resources) => this.createPixiSprites());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async forceTMRDisplay() {
|
||||||
|
this.bringToTop();
|
||||||
|
if (this.subdialog) {
|
||||||
|
this.subdialog.bringToTop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async restoreTMRAfterAction() {
|
||||||
|
this.subdialog = undefined
|
||||||
|
await this.maximize();
|
||||||
|
this.bringToTop();
|
||||||
|
}
|
||||||
|
|
||||||
|
forceTMRContinueAction() {
|
||||||
|
ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR');
|
||||||
|
this.subdialog.bringToTop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setTMRPendingAction(dialog) {
|
||||||
|
this.subdialog = dialog
|
||||||
|
if (dialog instanceof Application) {
|
||||||
|
dialog.bringToTop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
isDemiReveCache() {
|
isDemiReveCache() {
|
||||||
return !game.user.isGM && this.actor.isTMRCache();
|
return !game.user.isGM && this.actor.isTMRCache();
|
||||||
}
|
}
|
||||||
@@ -102,7 +128,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
createPixiSprites() {
|
createPixiSprites() {
|
||||||
EffetsDraconiques.carteTmr.createSprite(this.pixiTMR);
|
this.pixiTMR.setup()
|
||||||
this.updateTokens();
|
this.updateTokens();
|
||||||
this.forceDemiRevePositionView();
|
this.forceDemiRevePositionView();
|
||||||
}
|
}
|
||||||
@@ -113,13 +139,9 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
this.demiReve = this._tokenDemiReve();
|
this.demiReve = this._tokenDemiReve();
|
||||||
this._trackToken(this.demiReve);
|
this._trackToken(this.demiReve);
|
||||||
}
|
}
|
||||||
let tokens = this._getTokensCasesTmr()
|
this._getTokensCasesTmr().forEach(t => this._trackToken(t))
|
||||||
.concat(this._getTokensRencontres())
|
this._getTokensRencontres().forEach(t => this._trackToken(t))
|
||||||
.concat(this._getTokensSortsReserve());
|
this._getTokensSortsReserve().forEach(t => this._trackToken(t))
|
||||||
|
|
||||||
for (let t of tokens) {
|
|
||||||
this._trackToken(t);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -175,6 +197,10 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async moveFromKey(move) {
|
async moveFromKey(move) {
|
||||||
|
if (this.subdialog) {
|
||||||
|
return this.forceTMRContinueAction();
|
||||||
|
}
|
||||||
|
|
||||||
let oddq = TMRUtility.coordTMRToOddq(this._getActorCoord());
|
let oddq = TMRUtility.coordTMRToOddq(this._getActorCoord());
|
||||||
|
|
||||||
if (move == 'top') oddq.row -= 1;
|
if (move == 'top') oddq.row -= 1;
|
||||||
@@ -199,7 +225,10 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
this.html = html;
|
this.html = html;
|
||||||
|
|
||||||
document.getElementById("tmrrow1").insertCell(0).append(this.pixiApp.view);
|
document.getElementsByClassName("tmr-row")
|
||||||
|
.item(0)
|
||||||
|
.insertCell(0)
|
||||||
|
.append(this.pixiTMR.view);
|
||||||
|
|
||||||
if (this.viewOnly) {
|
if (this.viewOnly) {
|
||||||
this.html.find('.lancer-sort').remove();
|
this.html.find('.lancer-sort').remove();
|
||||||
@@ -207,31 +236,25 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue"));
|
||||||
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord()));
|
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord()));
|
||||||
|
|
||||||
// Roll Sort
|
this.html.find('tr.tmr-row *').click(event => this.subdialog?.bringToTop());
|
||||||
this.html.find('.lancer-sort').click((event) => {
|
|
||||||
this.actor.rollUnSort(this._getActorCoord());
|
|
||||||
});
|
|
||||||
this.html.find('.lire-signe-draconique').click((event) => {
|
|
||||||
this.actor.rollLireSigneDraconique(this._getActorCoord());
|
|
||||||
});
|
|
||||||
|
|
||||||
this.html.find('#dir-top').click((event) => this.moveFromKey("top"));
|
// Roll Sort
|
||||||
this.html.find('#dir-top-left').click((event) => this.moveFromKey("top-left"));
|
this.html.find('.lancer-sort').click(event => this.actor.rollUnSort(this._getActorCoord()));
|
||||||
this.html.find('#dir-top-right').click((event) => this.moveFromKey("top-right"));
|
this.html.find('.lire-signe-draconique').click(event => this.actor.rollLireSigneDraconique(this._getActorCoord()));
|
||||||
this.html.find('#dir-bottom-left').click((event) => this.moveFromKey("bottom-left"));
|
this.html.find('#dir-top').click(event=> this.moveFromKey("top"));
|
||||||
this.html.find('#dir-bottom-right').click((event) => this.moveFromKey("bottom-right"));
|
this.html.find('#dir-top-left').click(event=> this.moveFromKey("top-left"));
|
||||||
this.html.find('#dir-bottom').click((event) => this.moveFromKey("bottom"));
|
this.html.find('#dir-top-right').click(event=> this.moveFromKey("top-right"));
|
||||||
|
this.html.find('#dir-bottom-left').click(event=> this.moveFromKey("bottom-left"));
|
||||||
|
this.html.find('#dir-bottom-right').click(event=> this.moveFromKey("bottom-right"));
|
||||||
|
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();
|
||||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
|
||||||
this.cumulFatigue += this.fatigueParCase;
|
|
||||||
}
|
|
||||||
await this.actor.reveActuelIncDec(reveCout);
|
await this.actor.reveActuelIncDec(reveCout);
|
||||||
|
this.cumulFatigue += this.fatigueParCase;
|
||||||
// Le reste...
|
// Le reste...
|
||||||
this.updateValuesDisplay();
|
this.updateValuesDisplay();
|
||||||
let tmr = TMRUtility.getTMR(this._getActorCoord());
|
let tmr = TMRUtility.getTMR(this._getActorCoord());
|
||||||
@@ -263,7 +286,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
let refoulement = document.getElementById("tmr-refoulement-value");
|
let refoulement = document.getElementById("tmr-refoulement-value");
|
||||||
refoulement.innerHTML = this.actor.system.reve.refoulement.value;
|
refoulement.innerHTML = this.actor.system.reve.refoulement.value;
|
||||||
|
|
||||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||||
let fatigueItem = document.getElementById("tmr-fatigue-table");
|
let fatigueItem = document.getElementById("tmr-fatigue-table");
|
||||||
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(this.actor.system.sante.fatigue.value, this.actor.system.sante.endurance.max).html() + "</table>";
|
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(this.actor.system.sante.fatigue.value, this.actor.system.sante.endurance.max).html() + "</table>";
|
||||||
}
|
}
|
||||||
@@ -271,6 +294,10 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async close() {
|
async close() {
|
||||||
|
if (this.subdialog) {
|
||||||
|
return this.forceTMRContinueAction()
|
||||||
|
}
|
||||||
|
|
||||||
this.descenteTMR = true;
|
this.descenteTMR = true;
|
||||||
if (this.actor.tmrApp) {
|
if (this.actor.tmrApp) {
|
||||||
this.actor.tmrApp = undefined; // Cleanup reference
|
this.actor.tmrApp = undefined; // Cleanup reference
|
||||||
@@ -278,7 +305,8 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
await this.actor.setEffect(STATUSES.StatusDemiReve, false)
|
await this.actor.setEffect(STATUSES.StatusDemiReve, false)
|
||||||
this._tellToGM(this.actor.name + " a quitté les terres médianes");
|
this._tellToGM(this.actor.name + " a quitté les terres médianes");
|
||||||
}
|
}
|
||||||
await this.actor.santeIncDec("fatigue", this.cumulFatigue)
|
await this.actor.santeIncDec((ReglesOptionnelles.isUsing("appliquer-fatigue") ? "fatigue" : "endurance"),
|
||||||
|
this.cumulFatigue)
|
||||||
}
|
}
|
||||||
await super.close();
|
await super.close();
|
||||||
}
|
}
|
||||||
@@ -293,6 +321,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
switch (action) {
|
switch (action) {
|
||||||
case 'derober':
|
case 'derober':
|
||||||
await this.derober();
|
await this.derober();
|
||||||
|
this.restoreTMRAfterAction();
|
||||||
return;
|
return;
|
||||||
case 'refouler':
|
case 'refouler':
|
||||||
await this.refouler();
|
await this.refouler();
|
||||||
@@ -305,6 +334,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
await this.postRencontre(tmr);
|
await this.postRencontre(tmr);
|
||||||
|
this.restoreTMRAfterAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
async derober() {
|
async derober() {
|
||||||
@@ -343,35 +373,27 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
$marquerCasesTMR(listCoordTMR) {
|
$marquerCasesTMR(listCoordTMR) {
|
||||||
this.currentRencontre.graphics = []; // Keep track of rectangles to delete it
|
|
||||||
this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location
|
this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location
|
||||||
for (let coordTMR of listCoordTMR) {
|
this.currentRencontre.graphics = listCoordTMR.map(coordTMR => this.pixiTMR.addMarkTMR(coordTMR))
|
||||||
const rect = this._getCaseRectangleCoord(coordTMR);
|
|
||||||
const rectDraw = new PIXI.Graphics();
|
|
||||||
rectDraw.beginFill(0xffff00, 0.3);
|
|
||||||
// set the line style to have a width of 5 and set the color to red
|
|
||||||
rectDraw.lineStyle(5, 0xff0000);
|
|
||||||
// draw a rectangle
|
|
||||||
rectDraw.drawRect(rect.x, rect.y, rect.w, rect.h);
|
|
||||||
this.pixiApp.stage.addChild(rectDraw);
|
|
||||||
this.currentRencontre.graphics.push(rectDraw); // garder les objets pour gestion post-click
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
checkQuitterTMR() {
|
checkQuitterTMR() {
|
||||||
|
|
||||||
if (this.actor.isDead()) {
|
if (this.actor.isDead()) {
|
||||||
this._tellToGM("Vous êtes mort : vous quittez les Terres médianes !");
|
this._tellToGM("Vous êtes mort : vous quittez les Terres médianes !");
|
||||||
this.close();
|
this.close();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
const resteAvantInconscience = this.actor.getFatigueMax() - this.actor.getFatigueActuelle() - this.cumulFatigue;
|
|
||||||
if (ReglesOptionelles.isUsing("appliquer-fatigue") && resteAvantInconscience <= 0) {
|
if (ReglesOptionnelles.isUsing("appliquer-fatigue")
|
||||||
|
? (this.actor.getFatigueRestante() <= this.cumulFatigue)
|
||||||
|
: (this.actor.getEnduranceActuelle() <= this.cumulFatigue)
|
||||||
|
) {
|
||||||
this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !");
|
this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !");
|
||||||
this.quitterLesTMRInconscient();
|
this.quitterLesTMRInconscient();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.actor.getReveActuel() == 0) {
|
if (this.actor.getReveActuel() == 0) {
|
||||||
this._tellToGM("Vos Points de Rêve sont à 0 : vous quittez les Terres médianes !");
|
this._tellToGM("Vos Points de Rêve sont à 0 : vous quittez les Terres médianes !");
|
||||||
this.quitterLesTMRInconscient();
|
this.quitterLesTMRInconscient();
|
||||||
@@ -451,7 +473,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
// TODO: remplacer par une boucle while(this.currentRencontre) ?
|
// TODO: remplacer par une boucle while(this.currentRencontre) ?
|
||||||
rencData.nbRounds++;
|
rencData.nbRounds++;
|
||||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||||
this.cumulFatigue += this.fatigueParCase;
|
this.cumulFatigue += this.fatigueParCase;
|
||||||
}
|
}
|
||||||
this._tentativeMaitrise(rencData);
|
this._tentativeMaitrise(rencData);
|
||||||
@@ -531,8 +553,9 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
await this.maitriserRencontre();
|
await this.maitriserRencontre();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let dialog = new RdDTMRRencontreDialog(this, this.currentRencontre, tmr);
|
const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr);
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
|
this.setTMRPendingAction(dialog);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -544,9 +567,12 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
_presentCite(tmr) {
|
_presentCite(tmr) {
|
||||||
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
|
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
|
||||||
if (presentCite) {
|
if (presentCite) {
|
||||||
this.minimize();
|
|
||||||
const caseData = presentCite;
|
const caseData = presentCite;
|
||||||
EffetsDraconiques.presentCites.choisirUnPresent(caseData, (present => this._utiliserPresentCite(presentCite, present, tmr)));
|
const dialog = EffetsDraconiques.presentCites.choisirUnPresent(caseData, present => {
|
||||||
|
this._utiliserPresentCite(presentCite, present, tmr)
|
||||||
|
this.restoreTMRAfterAction();
|
||||||
|
});
|
||||||
|
this.setTMRPendingAction(dialog);
|
||||||
}
|
}
|
||||||
return presentCite;
|
return presentCite;
|
||||||
}
|
}
|
||||||
@@ -572,8 +598,6 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
presentCite: presentCite
|
presentCite: presentCite
|
||||||
};
|
};
|
||||||
await this._tentativeMaitrise(rencontreData);
|
await this._tentativeMaitrise(rencontreData);
|
||||||
|
|
||||||
this.maximize();
|
|
||||||
this.postRencontre(tmr);
|
this.postRencontre(tmr);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -587,7 +611,10 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
? TMRUtility.getTMRType(tmr.coord) + " ??"
|
? TMRUtility.getTMRType(tmr.coord) + " ??"
|
||||||
: tmr.label + " (" + tmr.coord + ")");
|
: tmr.label + " (" + tmr.coord + ")");
|
||||||
|
|
||||||
|
const fakeDialogRencontre = { bringToTop: () => { } };
|
||||||
|
this.setTMRPendingAction(fakeDialogRencontre)
|
||||||
let myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
|
let myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
|
||||||
|
this.restoreTMRAfterAction()
|
||||||
if (myRoll == 7) {
|
if (myRoll == 7) {
|
||||||
this._tellToUser(myRoll + ": Rencontre en " + locTMR);
|
this._tellToUser(myRoll + ": Rencontre en " + locTMR);
|
||||||
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
|
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
|
||||||
@@ -777,22 +804,22 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _maitriserTMR(rollData, callbackMaitrise) {
|
async _maitriserTMR(rollData, callbackMaitrise) {
|
||||||
this.minimize(); // Hide
|
|
||||||
rollData.isTMRCache = rollData.actor.isTMRCache();
|
rollData.isTMRCache = rollData.actor.isTMRCache();
|
||||||
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',
|
||||||
close: html => { this.maximize(); } // Re-display TMR
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: rollData.maitrise.verbe, label: rollData.maitrise.action,
|
name: rollData.maitrise.verbe, label: rollData.maitrise.action,
|
||||||
callbacks: [
|
callbacks: [
|
||||||
this.actor.createCallbackExperience(),
|
this.actor.createCallbackExperience(),
|
||||||
|
{ action: r => { this.restoreTMRAfterAction() } },
|
||||||
{ action: callbackMaitrise }
|
{ action: callbackMaitrise }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
|
this.setTMRPendingAction(dialog);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -860,14 +887,11 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
nettoyerRencontre() {
|
nettoyerRencontre() {
|
||||||
if (!this.currentRencontre) return; // Sanity check
|
// Suppression des dessins des zones possibles
|
||||||
if (this.currentRencontre.graphics) {
|
this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic))
|
||||||
for (let drawRect of this.currentRencontre.graphics) { // Suppression des dessins des zones possibles
|
// Nettoyage de la structureet de l'état
|
||||||
this.pixiApp.stage.removeChild(drawRect);
|
this.currentRencontre = undefined;
|
||||||
}
|
this.rencontreState = 'aucune';
|
||||||
}
|
|
||||||
this.currentRencontre = undefined; // Nettoyage de la structure
|
|
||||||
this.rencontreState = 'aucune'; // Et de l'état
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -895,8 +919,8 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
isConnaissanceFleuve(currentTMR, nextTMR) {
|
isConnaissanceFleuve(tmrApp, nextTMR) {
|
||||||
return TMRUtility.getTMR(currentTMR).type == 'fleuve' &&
|
return TMRUtility.getTMR(tmrApp).type == 'fleuve' &&
|
||||||
TMRUtility.getTMR(nextTMR).type == 'fleuve' &&
|
TMRUtility.getTMR(nextTMR).type == 'fleuve' &&
|
||||||
EffetsDraconiques.isConnaissanceFleuve(this.actor);
|
EffetsDraconiques.isConnaissanceFleuve(this.actor);
|
||||||
}
|
}
|
||||||
@@ -906,15 +930,15 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
if (this.viewOnly) {
|
if (this.viewOnly) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let clickOddq = RdDTMRDialog._computeEventOddq(event.data.originalEvent);
|
if (this.subdialog) {
|
||||||
await this._onClickTMRPos(clickOddq); // Vérifier l'état des compteurs reve/fatigue/vie
|
return this.forceTMRContinueAction()
|
||||||
}
|
}
|
||||||
|
let clickOddq = TMRUtility.computeEventOddq(event);
|
||||||
/* -------------------------------------------- */
|
|
||||||
async _onClickTMRPos(clickOddq) {
|
|
||||||
let currentOddq = TMRUtility.coordTMRToOddq(this._getActorCoord());
|
let currentOddq = TMRUtility.coordTMRToOddq(this._getActorCoord());
|
||||||
|
|
||||||
let targetCoord = TMRUtility.oddqToCoordTMR(clickOddq);
|
let targetCoord = TMRUtility.oddqToCoordTMR(clickOddq);
|
||||||
let currentCoord = TMRUtility.oddqToCoordTMR(currentOddq);
|
let currentCoord = TMRUtility.oddqToCoordTMR(currentOddq);
|
||||||
|
|
||||||
// Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter)
|
// Validation de la case de destination (gestion du cas des rencontres qui peuvent téléporter)
|
||||||
let deplacementType = this._calculDeplacement(targetCoord, currentCoord, currentOddq, clickOddq);
|
let deplacementType = this._calculDeplacement(targetCoord, currentCoord, currentOddq, clickOddq);
|
||||||
|
|
||||||
@@ -946,7 +970,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
await this._messagerDemiReve(targetCoord);
|
await this._messagerDemiReve(targetCoord);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ui.notifications.error("Vous ne pouvez pas vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre");
|
ui.notifications.error("Vous ne pouvez vous déplacer que sur des cases adjacentes à votre position ou valides dans le cas d'une rencontre");
|
||||||
console.log("STATUS :", this.rencontreState, this.currentRencontre);
|
console.log("STATUS :", this.rencontreState, this.currentRencontre);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -975,9 +999,11 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _messagerDemiReve(targetCoord) {
|
async _messagerDemiReve(targetCoord) {
|
||||||
/*
|
/*
|
||||||
TODO: si la case a un sort en réserve, lancer ce sort.
|
TODO:
|
||||||
|
Si la case a un sort en réserve, lancer ce sort.
|
||||||
Si la case est le demi-rêve, ne pas lancer de sort.
|
Si la case est le demi-rêve, ne pas lancer de sort.
|
||||||
Si un lancement de sort est en cours, trouver un moyen de réafficher cette fenêtre si on essaie de lancer un sort (ou bloquer le lancer de sort)
|
Si un lancement de sort est en cours, trouver un moyen de réafficher cette fenêtre
|
||||||
|
si on essaie de lancer un sort (ou bloquer le lancer de sort)
|
||||||
*/
|
*/
|
||||||
this.notifierResonanceSigneDraconique(targetCoord);
|
this.notifierResonanceSigneDraconique(targetCoord);
|
||||||
await this.actor.rollUnSort(targetCoord);
|
await this.actor.rollUnSort(targetCoord);
|
||||||
@@ -994,6 +1020,9 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _deplacerDemiReve(targetCoord, deplacementType) {
|
async _deplacerDemiReve(targetCoord, deplacementType) {
|
||||||
|
if (this.subdialog) {
|
||||||
|
return this.forceTMRContinueAction()
|
||||||
|
}
|
||||||
if (this.currentRencontre != 'normal') {
|
if (this.currentRencontre != 'normal') {
|
||||||
this.nettoyerRencontre();
|
this.nettoyerRencontre();
|
||||||
}
|
}
|
||||||
@@ -1004,7 +1033,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
await this.actor.updateCoordTMR(tmr.coord);
|
await this.actor.updateCoordTMR(tmr.coord);
|
||||||
|
|
||||||
this.forceDemiRevePositionView();
|
this.forceDemiRevePositionView();
|
||||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
|
||||||
this.cumulFatigue += this.fatigueParCase;
|
this.cumulFatigue += this.fatigueParCase;
|
||||||
}
|
}
|
||||||
this.updateValuesDisplay();
|
this.updateValuesDisplay();
|
||||||
@@ -1043,6 +1072,10 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async positionnerDemiReve(coord) {
|
async positionnerDemiReve(coord) {
|
||||||
|
if (this.subdialog) {
|
||||||
|
return this.forceTMRContinueAction()
|
||||||
|
}
|
||||||
|
|
||||||
await this.actor.updateCoordTMR(coord);
|
await this.actor.updateCoordTMR(coord);
|
||||||
this.forceDemiRevePositionView();
|
this.forceDemiRevePositionView();
|
||||||
let tmr = TMRUtility.getTMR(coord);
|
let tmr = TMRUtility.getTMR(coord);
|
||||||
@@ -1050,30 +1083,9 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
return tmr;
|
return tmr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static _computeEventOddq(origEvent) {
|
|
||||||
console.log("EVENT", origEvent)
|
|
||||||
let canvasRect = origEvent.target.getBoundingClientRect();
|
|
||||||
let x = origEvent.clientX - canvasRect.left;
|
|
||||||
let y = origEvent.clientY - canvasRect.top;
|
|
||||||
let col = Math.floor(x / tmrConstants.cellw); // [From 0 -> 12]
|
|
||||||
y -= col % 2 == 0 ? tmrConstants.col1_y : tmrConstants.col2_y;
|
|
||||||
let row = Math.floor(y / tmrConstants.cellh); // [From 0 -> 14]
|
|
||||||
return { col: col, row: row };
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** Retourne les coordonnées x, h, w, h du rectangle d'une case donnée */
|
|
||||||
_getCaseRectangleCoord(coord) {
|
|
||||||
return this.pixiTMR.getCaseRectangle(TMRUtility.coordTMRToOddq(coord));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_removeTokens(filter) {
|
_removeTokens(filter) {
|
||||||
const tokensToRemove = this.allTokens.filter(filter);
|
this.allTokens.filter(filter).forEach(token => this.pixiTMR.removeToken(token))
|
||||||
for (let token of tokensToRemove) {
|
|
||||||
this.pixiApp.stage.removeChild(token.sprite);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -1081,7 +1093,9 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
if (this.demiReve === token && this.isDemiReveCache()) {
|
if (this.demiReve === token && this.isDemiReveCache()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.pixiTMR.setPosition(token.sprite, TMRUtility.coordTMRToOddq(token.coordTMR()));
|
this.pixiTMR.positionToken(token);
|
||||||
this.allTokens.push(token);
|
if (!this.allTokens.includes(token)) {
|
||||||
|
this.allTokens.push(token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
export class RdDTMRRencontreDialog extends Dialog {
|
export class RdDTMRRencontreDialog extends Dialog {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(tmrApp, rencontre, tmr) {
|
constructor(actor, rencontre, tmr) {
|
||||||
const dialogConf = {
|
const dialogConf = {
|
||||||
title: "Rencontre en TMR!",
|
title: "Rencontre en TMR!",
|
||||||
content: "Vous rencontrez un " + rencontre.name + " de force " + rencontre.system.force + "<br>",
|
content: "Vous rencontrez un " + rencontre.name + " de force " + rencontre.system.force + "<br>",
|
||||||
@@ -28,23 +28,30 @@ export class RdDTMRRencontreDialog extends Dialog {
|
|||||||
|
|
||||||
this.toClose = false;
|
this.toClose = false;
|
||||||
this.tmr = tmr;
|
this.tmr = tmr;
|
||||||
this.tmrApp = tmrApp;
|
this.actor = actor;
|
||||||
this.rencontre = rencontre;
|
this.rencontre = rencontre;
|
||||||
this.tmrApp.minimize();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onButtonAction(action) {
|
async onButtonAction(action) {
|
||||||
this.toClose = true;
|
this.toClose = true;
|
||||||
this.tmrApp.onActionRencontre(action, this.tmr, this.rencontre)
|
await this.actor.tmrApp?.restoreTMRAfterAction();
|
||||||
|
this.actor.tmrApp?.onActionRencontre(action, this.tmr, this.rencontre)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
close() {
|
async close() {
|
||||||
if (this.toClose) {
|
if (this.actor.tmrApp){
|
||||||
this.tmrApp.maximize();
|
if (this.toClose) {
|
||||||
return super.close();
|
return await super.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.info("Vous devez résoudre la rencontre.");
|
||||||
|
return this.actor.tmrApp.forceTMRContinueAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return await super.close();
|
||||||
}
|
}
|
||||||
ui.notifications.info("Vous devez résoudre la rencontre.");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -75,8 +75,8 @@ export class RdDTokenHud {
|
|||||||
(event) => {
|
(event) => {
|
||||||
const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
|
const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
|
||||||
const action = hudData.actions[actionIndex];
|
const action = hudData.actions[actionIndex];
|
||||||
if (action.action == 'conjurer') {
|
const possession = action.action == 'possession' ? combatant.actor.getPossession(action.system.possessionid) : undefined;
|
||||||
const possession = combatant.actor.getPossession(action.system.possessionid);
|
if (possession) {
|
||||||
combatant.actor.conjurerPossession(possession);
|
combatant.actor.conjurerPossession(possession);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@@ -5,7 +5,7 @@ import { Misc } from "./misc.js";
|
|||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
import { DialogItemAchat } from "./dialog-item-achat.js";
|
import { DialogItemAchat } from "./dialog-item-achat.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { RdDItem } from "./item.js";
|
import { RdDItem } from "./item.js";
|
||||||
import { RdDPossession } from "./rdd-possession.js";
|
import { RdDPossession } from "./rdd-possession.js";
|
||||||
@@ -28,7 +28,7 @@ const ajustementsEncaissement = Misc.intArray(-10, 26);
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
function _buildAllSegmentsFatigue(max) {
|
function _buildAllSegmentsFatigue(max) {
|
||||||
const cycle = [5, 2, 4, 1, 3, 0];
|
const cycle = [5, 2, 4, 1, 3, 0];
|
||||||
let fatigue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
|
const fatigue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
|
||||||
for (let i = 0; i <= max; i++) {
|
for (let i = 0; i <= max; i++) {
|
||||||
const ligneFatigue = duplicate(fatigue[i]);
|
const ligneFatigue = duplicate(fatigue[i]);
|
||||||
const caseIncrementee = cycle[i % 6];
|
const caseIncrementee = cycle[i % 6];
|
||||||
@@ -55,7 +55,8 @@ function _cumulSegmentsFatigue(matrix) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const fatigueMatrix = _buildAllSegmentsFatigue(60);
|
export const MAX_ENDURANCE_FATIGUE = 60;
|
||||||
|
const fatigueMatrix = _buildAllSegmentsFatigue(MAX_ENDURANCE_FATIGUE);
|
||||||
const cumulFatigueMatrix = _cumulSegmentsFatigue(fatigueMatrix);
|
const cumulFatigueMatrix = _cumulSegmentsFatigue(fatigueMatrix);
|
||||||
|
|
||||||
const fatigueMalus = [0, 0, 0, -1, -1, -1, -2, -3, -4, -5, -6, -7]; // Provides the malus for each segment of fatigue
|
const fatigueMalus = [0, 0, 0, -1, -1, -1, -2, -3, -4, -5, -6, -7]; // Provides the malus for each segment of fatigue
|
||||||
@@ -121,6 +122,7 @@ export class RdDUtility {
|
|||||||
'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/header-hautreve.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/actor/archetype.hbs',
|
||||||
'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',
|
||||||
@@ -179,24 +181,25 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
|
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
|
||||||
// partial enums
|
// partial enums
|
||||||
'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-aspect-tarot.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-competence.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categories.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html',
|
||||||
'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-mortalite.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-categorie-queue.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-periode.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-periode.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
|
||||||
// Partials
|
// Partials
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/time/horloge.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/time/horloge.hbs',
|
||||||
@@ -243,7 +246,8 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-description.html',
|
'systems/foundryvtt-reve-de-dragon/templates/chat-description.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html',
|
'systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.html',
|
'systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html',
|
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-acteur.hbs',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html',
|
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html',
|
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-potionenchantee-chateaudormant.html',
|
'systems/foundryvtt-reve-de-dragon/templates/chat-potionenchantee-chateaudormant.html',
|
||||||
@@ -278,7 +282,7 @@ export class RdDUtility {
|
|||||||
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());
|
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());
|
||||||
|
|
||||||
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) => ReglesOptionnelles.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 => RdDItemCompetence.triVisible(competences));
|
Handlebars.registerHelper('filtreTriCompetences', competences => RdDItemCompetence.triVisible(competences));
|
||||||
Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name));
|
Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name));
|
||||||
@@ -286,6 +290,7 @@ export class RdDUtility {
|
|||||||
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
|
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
|
||||||
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
|
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
|
||||||
|
|
||||||
|
Handlebars.registerHelper('plusMoins', diff => (diff > 0 ? '+' : '') + Math.round(diff))
|
||||||
Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic));
|
Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic));
|
||||||
|
|
||||||
return loadTemplates(templatePaths);
|
return loadTemplates(templatePaths);
|
||||||
@@ -339,13 +344,13 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static buildArbreDeConteneurs(conteneurs, objets) {
|
static buildArbreDeConteneurs(conteneurs, inventaires) {
|
||||||
let objetVersConteneur = {};
|
let objetVersConteneur = {};
|
||||||
// Attribution des objets aux conteneurs
|
// Attribution des objets aux conteneurs
|
||||||
for (let conteneur of conteneurs) {
|
for (let conteneur of conteneurs) {
|
||||||
conteneur.subItems = [];
|
conteneur.subItems = [];
|
||||||
for (let id of conteneur.system.contenu ?? []) {
|
for (let id of conteneur.system.contenu ?? []) {
|
||||||
let objet = objets.find(objet => (id == objet._id));
|
let objet = inventaires.find(objet => (id == objet._id));
|
||||||
if (objet) {
|
if (objet) {
|
||||||
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template
|
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template
|
||||||
objetVersConteneur[id] = conteneur._id;
|
objetVersConteneur[id] = conteneur._id;
|
||||||
@@ -354,20 +359,20 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let conteneur of conteneurs) {
|
for (let conteneur of conteneurs) {
|
||||||
conteneur.system.encTotal = RdDUtility.calculEncContenu(conteneur, objets);
|
conteneur.system.encTotal = RdDUtility.calculEncContenu(conteneur, inventaires);
|
||||||
}
|
}
|
||||||
return objetVersConteneur;
|
return objetVersConteneur;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static calculEncContenu(conteneur, objets) {
|
static calculEncContenu(conteneur, inventaires) {
|
||||||
const contenus = (conteneur.system.contenu ?? []).filter(id => id != undefined)
|
const contenus = (conteneur.system.contenu ?? []).filter(id => id != undefined)
|
||||||
.map(id => objets.find(it => (id == it.id)))
|
.map(id => inventaires.find(it => (id == it.id)))
|
||||||
.filter(it => it);
|
.filter(it => it);
|
||||||
let enc = Number(conteneur.system.encombrement ?? 0) * Number(conteneur.system.quantite ?? 1);
|
let enc = Number(conteneur.system.encombrement ?? 0) * Number(conteneur.system.quantite ?? 1);
|
||||||
for (let contenu of contenus) {
|
for (let contenu of contenus) {
|
||||||
if (contenu.type == 'conteneur') {
|
if (contenu.type == 'conteneur') {
|
||||||
enc += RdDUtility.calculEncContenu(contenu, objets);
|
enc += RdDUtility.calculEncContenu(contenu, inventaires);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
enc += Number(contenu.system.encombrement ?? 0) * Number(contenu.system.quantite ?? 1)
|
enc += Number(contenu.system.encombrement ?? 0) * Number(contenu.system.quantite ?? 1)
|
||||||
@@ -457,18 +462,15 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getSegmentsFatigue(maxEnd) {
|
static getSegmentsFatigue(maxEndurance) {
|
||||||
maxEnd = Math.max(maxEnd, 1);
|
return fatigueMatrix[Math.min(Math.max(maxEndurance, 1), fatigueMatrix.length)];
|
||||||
maxEnd = Math.min(maxEnd, fatigueMatrix.length);
|
|
||||||
return fatigueMatrix[maxEnd];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static calculMalusFatigue(fatigue, maxEnd) {
|
static calculMalusFatigue(fatigue, endurance) {
|
||||||
maxEnd = Math.max(maxEnd, 1);
|
endurance = Math.min(Math.max(endurance, 1), cumulFatigueMatrix.length);
|
||||||
maxEnd = Math.min(maxEnd, cumulFatigueMatrix.length);
|
let segments = cumulFatigueMatrix[endurance];
|
||||||
let segments = cumulFatigueMatrix[maxEnd];
|
for (let i = 0; i < segments.length; i++) {
|
||||||
for (let i = 0; i < 12; i++) {
|
|
||||||
if (fatigue <= segments[i]) {
|
if (fatigue <= segments[i]) {
|
||||||
return fatigueMalus[i]
|
return fatigueMalus[i]
|
||||||
}
|
}
|
||||||
@@ -478,7 +480,7 @@ export class RdDUtility {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static calculFatigueHtml(fatigue, endurance) {
|
static calculFatigueHtml(fatigue, endurance) {
|
||||||
return ReglesOptionelles.isUsing("appliquer-fatigue") ? {
|
return ReglesOptionnelles.isUsing("appliquer-fatigue") ? {
|
||||||
malus: RdDUtility.calculMalusFatigue(fatigue, endurance),
|
malus: RdDUtility.calculMalusFatigue(fatigue, endurance),
|
||||||
html: "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(fatigue, endurance).html() + "</table>"
|
html: "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(fatigue, endurance).html() + "</table>"
|
||||||
} : { malus: 0, html: '' };
|
} : { malus: 0, html: '' };
|
||||||
@@ -488,7 +490,7 @@ export class RdDUtility {
|
|||||||
// Build the nice (?) html table used to manage fatigue.
|
// Build the nice (?) html table used to manage fatigue.
|
||||||
// max should be the endurance max value
|
// max should be the endurance max value
|
||||||
static makeHTMLfatigueMatrix(fatigue, maxEndurance) {
|
static makeHTMLfatigueMatrix(fatigue, maxEndurance) {
|
||||||
let segments = this.getSegmentsFatigue(maxEndurance);
|
const segments = this.getSegmentsFatigue(maxEndurance);
|
||||||
return this.makeHTMLfatigueMatrixForSegment(fatigue, segments);
|
return this.makeHTMLfatigueMatrixForSegment(fatigue, segments);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -554,14 +556,14 @@ export class RdDUtility {
|
|||||||
let formula = "2d10";
|
let formula = "2d10";
|
||||||
|
|
||||||
// Chaque dé fait au minmum la difficulté libre
|
// Chaque dé fait au minmum la difficulté libre
|
||||||
if (ReglesOptionelles.isUsing('degat-minimum-malus-libre')) {
|
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre')) {
|
||||||
if (rollData.diffLibre < 0) {
|
if (rollData.diffLibre < 0) {
|
||||||
let valeurMin = Math.abs(rollData.diffLibre);
|
let valeurMin = Math.abs(rollData.diffLibre);
|
||||||
formula += "min" + valeurMin;
|
formula += "min" + valeurMin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Chaque dé fait au minmum la difficulté libre
|
// Chaque dé fait au minmum la difficulté libre
|
||||||
if (ReglesOptionelles.isUsing('degat-ajout-malus-libre')) {
|
if (ReglesOptionnelles.isUsing('degat-ajout-malus-libre')) {
|
||||||
if (rollData.diffLibre < 0) {
|
if (rollData.diffLibre < 0) {
|
||||||
let valeurMin = Math.abs(rollData.diffLibre);
|
let valeurMin = Math.abs(rollData.diffLibre);
|
||||||
formula += "+" + valeurMin;
|
formula += "+" + valeurMin;
|
||||||
@@ -571,7 +573,7 @@ export class RdDUtility {
|
|||||||
let roll = await RdDDice.roll(formula, options);
|
let roll = await RdDDice.roll(formula, options);
|
||||||
|
|
||||||
// 1 dé fait au minmum la difficulté libre
|
// 1 dé fait au minmum la difficulté libre
|
||||||
if (ReglesOptionelles.isUsing('degat-minimum-malus-libre-simple')) {
|
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre-simple')) {
|
||||||
if (rollData.diffLibre < 0) {
|
if (rollData.diffLibre < 0) {
|
||||||
let valeurMin = Math.abs(rollData.diffLibre);
|
let valeurMin = Math.abs(rollData.diffLibre);
|
||||||
if (roll.terms[0].results[0].result < valeurMin) {
|
if (roll.terms[0].results[0].result < valeurMin) {
|
||||||
@@ -622,25 +624,6 @@ export class RdDUtility {
|
|||||||
return perte.total;
|
return perte.total;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static currentFatigueMalus(value, max) {
|
|
||||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
|
||||||
max = Math.max(1, Math.min(max, 60));
|
|
||||||
value = Math.min(max * 2, Math.max(0, value));
|
|
||||||
|
|
||||||
let fatigueTab = fatigueMatrix[max];
|
|
||||||
let fatigueRem = value;
|
|
||||||
for (let idx = 0; idx < fatigueTab.length; idx++) {
|
|
||||||
fatigueRem -= fatigueTab[idx];
|
|
||||||
if (fatigueRem <= 0) {
|
|
||||||
return fatigueMalus[idx];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -7; // This is the max !
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async responseNombreAstral(callData) {
|
static async responseNombreAstral(callData) {
|
||||||
let actor = game.actors.get(callData.id);
|
let actor = game.actors.get(callData.id);
|
||||||
@@ -668,6 +651,7 @@ export class RdDUtility {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async chatListeners(html) {
|
static async chatListeners(html) {
|
||||||
RdDCombat.registerChatCallbacks(html);
|
RdDCombat.registerChatCallbacks(html);
|
||||||
|
RdDEmpoignade.registerChatCallbacks(html);
|
||||||
|
|
||||||
// Gestion spécifique message passeurs
|
// Gestion spécifique message passeurs
|
||||||
html.on("click", '.tmr-passeur-coord a', event => {
|
html.on("click", '.tmr-passeur-coord a', event => {
|
||||||
@@ -694,44 +678,6 @@ export class RdDUtility {
|
|||||||
RdDPossession.onDefensePossession(attackerId, defenderId, possessionId)
|
RdDPossession.onDefensePossession(attackerId, defenderId, possessionId)
|
||||||
});
|
});
|
||||||
|
|
||||||
html.on("click", '.defense-empoignade-cac', event => {
|
|
||||||
const chatMessage = ChatUtility.getChatMessage(event);
|
|
||||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
|
||||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
|
||||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee")
|
|
||||||
});
|
|
||||||
html.on("click", '.defense-empoignade-esquive', event => {
|
|
||||||
const chatMessage = ChatUtility.getChatMessage(event);
|
|
||||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
|
||||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
|
||||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee")
|
|
||||||
});
|
|
||||||
html.on("click", '.empoignade-poursuivre', event => {
|
|
||||||
let attackerId = event.currentTarget.attributes['data-attackerId'].value
|
|
||||||
let defenderId = event.currentTarget.attributes['data-defenderId'].value
|
|
||||||
RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId))
|
|
||||||
});
|
|
||||||
html.on("click", '.empoignade-entrainer-sol', event => {
|
|
||||||
const chatMessage = ChatUtility.getChatMessage(event);
|
|
||||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
|
||||||
RdDEmpoignade.entrainerAuSol(rollData)
|
|
||||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
|
||||||
});
|
|
||||||
html.on("click", '.empoignade-projeter-sol', event => {
|
|
||||||
const chatMessage = ChatUtility.getChatMessage(event);
|
|
||||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
|
||||||
RdDEmpoignade.projeterAuSol(rollData)
|
|
||||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
|
||||||
});
|
|
||||||
html.on("change", '.empoignade-perte-endurance', event => {
|
|
||||||
const chatMessage = ChatUtility.getChatMessage(event);
|
|
||||||
const rollData = ChatUtility.getMessageData(chatMessage, 'empoignade-roll-data');
|
|
||||||
if (event.currentTarget.value && event.currentTarget.value != "none") {
|
|
||||||
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
|
|
||||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// gestion bouton tchat Acheter
|
// gestion bouton tchat Acheter
|
||||||
html.on("click", '.button-acheter', event => {
|
html.on("click", '.button-acheter', event => {
|
||||||
const venteData = DialogItemAchat.preparerAchat(event.currentTarget);
|
const venteData = DialogItemAchat.preparerAchat(event.currentTarget);
|
||||||
|
@@ -5,8 +5,9 @@ import { RdDItemSort } from "./item-sort.js";
|
|||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDBonus } from "./rdd-bonus.js";
|
import { RdDBonus } from "./rdd-bonus.js";
|
||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
|
import { RdDPossession } from "./rdd-possession.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* tous les ajustements pouvant s'appliquer.
|
* tous les ajustements pouvant s'appliquer.
|
||||||
@@ -30,7 +31,7 @@ export const referenceAjustements = {
|
|||||||
},
|
},
|
||||||
diffLibre: {
|
diffLibre: {
|
||||||
isUsed: (rollData, actor) => rollData.diffLibre != undefined,
|
isUsed: (rollData, actor) => rollData.diffLibre != undefined,
|
||||||
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ? 'Imposée' : 'Libre',
|
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ?? RdDPossession.isDefensePossession(rollData) ? 'Imposée' : 'Libre',
|
||||||
getValue: (rollData, actor) => rollData.selectedSort
|
getValue: (rollData, actor) => rollData.selectedSort
|
||||||
? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre)
|
? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre)
|
||||||
: rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0
|
: rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0
|
||||||
@@ -51,7 +52,7 @@ export const referenceAjustements = {
|
|||||||
getValue: (rollData, actor) => RdDBonus.find(rollData.surpriseDefenseur).attaque,
|
getValue: (rollData, actor) => RdDBonus.find(rollData.surpriseDefenseur).attaque,
|
||||||
},
|
},
|
||||||
etat: {
|
etat: {
|
||||||
isUsed: (rollData, actor) => !RdDCarac.isIgnoreEtatGeneral(rollData),
|
isUsed: (rollData, actor) => !RollDataAjustements.isIgnoreEtatGeneral(rollData),
|
||||||
getLabel: (rollData, actor) => 'Etat général',
|
getLabel: (rollData, actor) => 'Etat général',
|
||||||
getValue: (rollData, actor) => actor.getEtatGeneral({ ethylisme: rollData.forceAlcool != undefined })
|
getValue: (rollData, actor) => actor.getEtatGeneral({ ethylisme: rollData.forceAlcool != undefined })
|
||||||
},
|
},
|
||||||
@@ -68,8 +69,8 @@ export const referenceAjustements = {
|
|||||||
getValue: (rollData, actor) => -actor.getEncTotal()
|
getValue: (rollData, actor) => -actor.getEncTotal()
|
||||||
},
|
},
|
||||||
surenc: {
|
surenc: {
|
||||||
isVisible: (rollData, actor) => actor.isSurenc(),
|
isVisible: (rollData, actor) => RdDCarac.isActionPhysique(rollData.selectedCarac) && actor.isSurenc(),
|
||||||
isUsed: (rollData, actor) => rollData.use?.surenc,
|
isUsed: (rollData, actor) => rollData.use?.surenc && RdDCarac.isActionPhysique(rollData.selectedCarac),
|
||||||
getLabel: (rollData, actor) => 'Sur-encombrement',
|
getLabel: (rollData, actor) => 'Sur-encombrement',
|
||||||
getValue: (rollData, actor) => actor.computeMalusSurEncombrement()
|
getValue: (rollData, actor) => actor.computeMalusSurEncombrement()
|
||||||
},
|
},
|
||||||
@@ -85,7 +86,7 @@ export const referenceAjustements = {
|
|||||||
getValue: (rollData, actor) => actor.getMoralTotal()
|
getValue: (rollData, actor) => actor.getMoralTotal()
|
||||||
},
|
},
|
||||||
astrologique: {
|
astrologique: {
|
||||||
isUsed: (rollData, actor) => ReglesOptionelles.isUsing("astrologie") && RdDBonus.isAjustementAstrologique(rollData),
|
isUsed: (rollData, actor) => ReglesOptionnelles.isUsing("astrologie") && RdDBonus.isAjustementAstrologique(rollData),
|
||||||
getLabel: (rollData, actor) => 'Astrologique',
|
getLabel: (rollData, actor) => 'Astrologique',
|
||||||
getValue: (rollData, actor) => actor.ajustementAstrologique()
|
getValue: (rollData, actor) => actor.ajustementAstrologique()
|
||||||
},
|
},
|
||||||
@@ -163,7 +164,7 @@ export class RollDataAjustements {
|
|||||||
descr: reference.getDescr && reference.getDescr(rollData, actor)
|
descr: reference.getDescr && reference.getDescr(rollData, actor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rollData.finalLevel = RollDataAjustements.sum(rollData.ajustements);
|
rollData.finalLevel = RollDataAjustements.sum(rollData.ajustements)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -177,4 +178,11 @@ export class RollDataAjustements {
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static isIgnoreEtatGeneral(rollData) {
|
||||||
|
const selectedCarac = rollData.selectedCarac;
|
||||||
|
return !selectedCarac ||
|
||||||
|
rollData.ethylisme ||
|
||||||
|
RdDCarac.isChance(selectedCarac) ||
|
||||||
|
(RdDCarac.isReve(selectedCarac) && !rollData.competence);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,119 +0,0 @@
|
|||||||
import { SYSTEM_RDD } from "../constants.js";
|
|
||||||
import { Misc } from "../misc.js";
|
|
||||||
|
|
||||||
const listeReglesOptionelles = [
|
|
||||||
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
|
|
||||||
{ group: 'Règles de combat', name: 'resistanceArmeParade', descr: "Faire le jet de résistance des armes lors de parades pouvant les endommager" },
|
|
||||||
{ group: 'Règles de combat', name: 'deteriorationArmure', descr: "Tenir compte de la détérioration des armures" },
|
|
||||||
{ group: 'Règles de combat', name: 'defenseurDesarme', descr: "Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier" },
|
|
||||||
{ group: 'Règles de combat', name: 'categorieParade', descr: "Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes" },
|
|
||||||
{ group: 'Règles de combat', name: 'tripleSignificative', descr: "En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès" },
|
|
||||||
{ group: 'Règles de combat', name: 'degat-minimum-malus-libre-simple', descr: "Le malus libre d'attaque remplace une des valeurs de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, si le plus petit dé est inférieur à 4, alors il devient 4.", default: false },
|
|
||||||
{ group: 'Règles de combat', name: 'degat-minimum-malus-libre', descr: "Le malus libre d'attaque remplace une valeur de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, tout résultat inférieur à 4 devient 4.", default: false },
|
|
||||||
{ group: 'Règles de combat', name: 'degat-ajout-malus-libre', descr: "Le malus libre d'attaque s'ajoute au jet d'encaissement et aux autres bonus. Exemple : la difficulté libre de l'attaquant est de -4. Le jet d'encaissement est effectué à 2d10+4, plus les bonus de situation et d'armes.", default: false },
|
|
||||||
{ group: 'Règles de combat', name: 'validation-encaissement-gr', descr: "Le Gardien des Rêves doit valider les jets d'encaissement et peut les changer.", default: false },
|
|
||||||
|
|
||||||
{ group: 'Règles générales', name: 'astrologie', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels"},
|
|
||||||
{ group: 'Règles générales', name: 'afficher-prix-joueurs', descr: "Afficher le prix de l'équipement des joueurs", uniquementJoueur: true},
|
|
||||||
{ 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: 'chateau-dormant-gardien', descr: "Saisie des heures de sommeil/jets de moral par le gardien des rêves", default: true },
|
|
||||||
|
|
||||||
{ 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-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-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"},
|
|
||||||
{ group: 'Confirmations', name: 'confirmation-supprimer-equipement', descr: "Confirmer la suppression des équipements", scope: "client"},
|
|
||||||
{ group: 'Confirmations', name: 'confirmation-supprimer-oeuvre', descr: "Confirmer la suppression des oeuvres", scope: "client"},
|
|
||||||
{ group: 'Confirmations', name: 'confirmation-supprimer-connaissance', descr: "Confirmer la suppression des connaissances", scope: "client"},
|
|
||||||
{ group: 'Confirmations', name: 'confirmation-supprimer-draconique', descr: "Confirmer la suppression des queues, souffles, têtes", scope: "client"},
|
|
||||||
{ group: 'Confirmations', name: 'confirmation-supprimer-effet', descr: "Confirmer la suppression des effets", scope: "client"},
|
|
||||||
{ group: 'Confirmations', name: 'confirmation-supprimer-competence', descr: "Confirmer la suppression des compétences", scope: "client"},
|
|
||||||
{ group: 'Confirmations', name: 'confirmation-supprimer-autres', descr: "Confirmer la suppression des autres types d'Objets", scope: "client"},
|
|
||||||
];
|
|
||||||
|
|
||||||
const uniquementJoueur = listeReglesOptionelles.filter(it => it.uniquementJoueur).map(it=>it.name);
|
|
||||||
|
|
||||||
export class ReglesOptionelles extends FormApplication {
|
|
||||||
static init() {
|
|
||||||
for (const regle of listeReglesOptionelles) {
|
|
||||||
const name = regle.name;
|
|
||||||
const id = ReglesOptionelles._getIdRegle(name);
|
|
||||||
game.settings.register(SYSTEM_RDD, id, { name: id, scope: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean });
|
|
||||||
}
|
|
||||||
|
|
||||||
game.settings.registerMenu(SYSTEM_RDD, "rdd-options-regles", {
|
|
||||||
name: "Choisir les règles optionelles",
|
|
||||||
label: "Règles optionelles",
|
|
||||||
hint: "Ouvre la fenêtre de sélection des règles optionelles",
|
|
||||||
icon: "fas fa-bars",
|
|
||||||
type: ReglesOptionelles
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(...args) {
|
|
||||||
super(...args);
|
|
||||||
}
|
|
||||||
|
|
||||||
static _getIdRegle(name) {
|
|
||||||
return `rdd-option-${name}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
const options = super.defaultOptions;
|
|
||||||
mergeObject(options, {
|
|
||||||
id: "regles-optionelles",
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionelles.html",
|
|
||||||
height: 600,
|
|
||||||
width: 450,
|
|
||||||
minimizable: false,
|
|
||||||
closeOnSubmit: true,
|
|
||||||
title: "Règles optionnelles"
|
|
||||||
});
|
|
||||||
return options;
|
|
||||||
}
|
|
||||||
|
|
||||||
getData() {
|
|
||||||
let formData = super.getData();
|
|
||||||
const regles = listeReglesOptionelles.filter(it => game.user.isGM || it.scope == "client").map(it => {
|
|
||||||
it = duplicate(it);
|
|
||||||
it.id = ReglesOptionelles._getIdRegle(it.name);
|
|
||||||
it.active = ReglesOptionelles.isSet(it.name);
|
|
||||||
return it;
|
|
||||||
});
|
|
||||||
formData.regles = regles;
|
|
||||||
formData.groups = Misc.classify(regles, it => it.group);
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
static isUsing(name) {
|
|
||||||
if (game.user.isGM && uniquementJoueur.includes(name)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return ReglesOptionelles.isSet(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
static isSet(name) {
|
|
||||||
return game.settings.get(SYSTEM_RDD, ReglesOptionelles._getIdRegle(name));
|
|
||||||
}
|
|
||||||
|
|
||||||
static set(name, value) {
|
|
||||||
return game.settings.set(SYSTEM_RDD, ReglesOptionelles._getIdRegle(name), value ? true: false);
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
html.find(".select-option").click((event) => {
|
|
||||||
if (event.currentTarget.attributes.name) {
|
|
||||||
let id = event.currentTarget.attributes.name.value;
|
|
||||||
let isChecked = event.currentTarget.checked;
|
|
||||||
game.settings.set(SYSTEM_RDD, id, isChecked);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async _updateObject(event, formData) {
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
128
module/settings/regles-optionnelles.js
Normal file
128
module/settings/regles-optionnelles.js
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
import { SYSTEM_RDD } from "../constants.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
|
||||||
|
const listeReglesOptionnelles = [
|
||||||
|
{ group: 'Règles générales', name: 'appliquer-fatigue', descr: "Appliquer les règles de fatigue"},
|
||||||
|
{ group: 'Règles générales', name: 'astrologie', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels"},
|
||||||
|
{ group: 'Récupération', name: 'transformation-stress', descr: "Transformer le stress durant Château Dormant"},
|
||||||
|
{ group: 'Récupération', name: 'recuperation-chance', descr: "Récupérer la chance durant Château Dormant"},
|
||||||
|
{ group: 'Récupération', name: 'recuperation-ethylisme', descr: "Récupérer l'éthylisme"},
|
||||||
|
{ group: 'Récupération', name: 'recuperation-reve', descr: "Récupérer le rêve pendant la nuit (les jets sont toujours faits pour les Rêves de Dragons)"},
|
||||||
|
{ group: 'Récupération', name: 'recuperation-moral', descr: "Le moral revient vers 0 durant Château Dormant"},
|
||||||
|
|
||||||
|
|
||||||
|
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
|
||||||
|
{ group: 'Règles de combat', name: 'resistanceArmeParade', descr: "Faire le jet de résistance des armes lors de parades pouvant les endommager" },
|
||||||
|
{ group: 'Règles de combat', name: 'deteriorationArmure', descr: "Tenir compte de la détérioration des armures" },
|
||||||
|
{ group: 'Règles de combat', name: 'defenseurDesarme', descr: "Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier" },
|
||||||
|
{ group: 'Règles de combat', name: 'categorieParade', descr: "Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes" },
|
||||||
|
{ group: 'Règles de combat', name: 'tripleSignificative', descr: "En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès" },
|
||||||
|
{ group: 'Règles de combat', name: 'validation-encaissement-gr', descr: "Le Gardien des Rêves doit valider les jets d'encaissement et peut les changer.", default: false },
|
||||||
|
|
||||||
|
{ group: 'Automatisation', name: 'chateau-dormant-gardien', descr: "Saisie des heures de sommeil/jets de moral par le gardien des rêves", default: true },
|
||||||
|
|
||||||
|
{ group: 'Affichage', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false },
|
||||||
|
{ group: 'Affichage', name: 'afficher-prix-joueurs', descr: "Afficher le prix de l'équipement des joueurs", uniquementJoueur: true},
|
||||||
|
|
||||||
|
{ 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-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-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"},
|
||||||
|
{ group: 'Confirmations', name: 'confirmation-supprimer-equipement', descr: "Confirmer la suppression des équipements", scope: "client"},
|
||||||
|
{ group: 'Confirmations', name: 'confirmation-supprimer-oeuvre', descr: "Confirmer la suppression des oeuvres", scope: "client"},
|
||||||
|
{ group: 'Confirmations', name: 'confirmation-supprimer-connaissance', descr: "Confirmer la suppression des connaissances", scope: "client"},
|
||||||
|
{ group: 'Confirmations', name: 'confirmation-supprimer-draconique', descr: "Confirmer la suppression des queues, souffles, têtes", scope: "client"},
|
||||||
|
{ group: 'Confirmations', name: 'confirmation-supprimer-effet', descr: "Confirmer la suppression des effets", scope: "client"},
|
||||||
|
{ group: 'Confirmations', name: 'confirmation-supprimer-competence', descr: "Confirmer la suppression des compétences", scope: "client"},
|
||||||
|
{ group: 'Confirmations', name: 'confirmation-supprimer-autres', descr: "Confirmer la suppression des autres types d'Objets", scope: "client"},
|
||||||
|
|
||||||
|
{ group: 'Options alternatives', name: 'degat-minimum-malus-libre-simple', descr: "Le malus libre d'attaque remplace une des valeurs de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, si le plus petit dé est inférieur à 4, alors il devient 4.", default: false },
|
||||||
|
{ group: 'Options alternatives', name: 'degat-minimum-malus-libre', descr: "Le malus libre d'attaque remplace une valeur de dés d'encaissement si elle est plus petite. Exemple : la difficulté libre de l'attaquant est de -4. Sur le jet d'encaissement, tout résultat inférieur à 4 devient 4.", default: false },
|
||||||
|
{ group: 'Options alternatives', name: 'degat-ajout-malus-libre', descr: "Le malus libre d'attaque s'ajoute au jet d'encaissement et aux autres bonus. Exemple : la difficulté libre de l'attaquant est de -4. Le jet d'encaissement est effectué à 2d10+4, plus les bonus de situation et d'armes.", default: false },
|
||||||
|
];
|
||||||
|
|
||||||
|
const uniquementJoueur = listeReglesOptionnelles.filter(it => it.uniquementJoueur).map(it=>it.name);
|
||||||
|
|
||||||
|
export class ReglesOptionnelles extends FormApplication {
|
||||||
|
static init() {
|
||||||
|
for (const regle of listeReglesOptionnelles) {
|
||||||
|
const name = regle.name;
|
||||||
|
const id = ReglesOptionnelles._getIdRegle(name);
|
||||||
|
game.settings.register(SYSTEM_RDD, id, { name: id, scope: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean });
|
||||||
|
}
|
||||||
|
|
||||||
|
game.settings.registerMenu(SYSTEM_RDD, "rdd-options-regles", {
|
||||||
|
name: "Choisir les règles optionnelles",
|
||||||
|
label: "Règles optionnelles",
|
||||||
|
hint: "Ouvre la fenêtre de sélection des règles optionnelles",
|
||||||
|
icon: "fas fa-bars",
|
||||||
|
type: ReglesOptionnelles
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(...args) {
|
||||||
|
super(...args);
|
||||||
|
}
|
||||||
|
|
||||||
|
static _getIdRegle(name) {
|
||||||
|
return `rdd-option-${name}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
static get defaultOptions() {
|
||||||
|
const options = super.defaultOptions;
|
||||||
|
mergeObject(options, {
|
||||||
|
id: "regles-optionnelles",
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.html",
|
||||||
|
height: 600,
|
||||||
|
width: 450,
|
||||||
|
minimizable: false,
|
||||||
|
closeOnSubmit: true,
|
||||||
|
title: "Règles optionnelles"
|
||||||
|
});
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
let formData = super.getData();
|
||||||
|
const regles = listeReglesOptionnelles.filter(it => game.user.isGM || it.scope == "client").map(it => {
|
||||||
|
it = duplicate(it);
|
||||||
|
it.id = ReglesOptionnelles._getIdRegle(it.name);
|
||||||
|
it.active = ReglesOptionnelles.isSet(it.name);
|
||||||
|
return it;
|
||||||
|
});
|
||||||
|
formData.regles = regles;
|
||||||
|
formData.groups = Misc.classify(regles, it => it.group);
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
static isUsing(name) {
|
||||||
|
if (game.user.isGM && uniquementJoueur.includes(name)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return ReglesOptionnelles.isSet(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static isSet(name) {
|
||||||
|
return game.settings.get(SYSTEM_RDD, ReglesOptionnelles._getIdRegle(name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static set(name, value) {
|
||||||
|
return game.settings.set(SYSTEM_RDD, ReglesOptionnelles._getIdRegle(name), value ? true: false);
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
html.find(".select-option").click((event) => {
|
||||||
|
if (event.currentTarget.attributes.name) {
|
||||||
|
let id = event.currentTarget.attributes.name.value;
|
||||||
|
let isChecked = event.currentTarget.checked;
|
||||||
|
game.settings.set(SYSTEM_RDD, id, isChecked);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async _updateObject(event, formData) {
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@@ -47,6 +47,7 @@ export class SystemCompendiums extends FormApplication {
|
|||||||
label: "Compendiums système",
|
label: "Compendiums système",
|
||||||
hint: "Ouvre la fenêtre de sélection des compendiums système",
|
hint: "Ouvre la fenêtre de sélection des compendiums système",
|
||||||
icon: "fas fa-bars",
|
icon: "fas fa-bars",
|
||||||
|
restricted: true,
|
||||||
type: SystemCompendiums
|
type: SystemCompendiums
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@@ -128,7 +128,7 @@ export class AppAstrologie extends Application {
|
|||||||
this.selectHeureNaissance(event.currentTarget.attributes['data-heure-naissance'].value);
|
this.selectHeureNaissance(event.currentTarget.attributes['data-heure-naissance'].value);
|
||||||
})
|
})
|
||||||
this.html.find('[name="jet-astrologie"]').click(event => this.requestJetAstrologie());
|
this.html.find('[name="jet-astrologie"]').click(event => this.requestJetAstrologie());
|
||||||
this.html.find('[name="rebuild-nombres-astraux"]').click(event => this.rebuildNombresAstraux());
|
this.html.find('[name="rebuild-nombres-astraux"]').click(event => this.onRebuild());
|
||||||
|
|
||||||
this.onCalculThemeAstral();
|
this.onCalculThemeAstral();
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ export class AppAstrologie extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async rebuildNombresAstraux() {
|
async onRebuild() {
|
||||||
game.system.rdd.calendrier.resetNombresAstraux();
|
game.system.rdd.calendrier.resetNombresAstraux();
|
||||||
|
|
||||||
await game.system.rdd.calendrier.rebuildNombresAstraux();
|
await game.system.rdd.calendrier.rebuildNombresAstraux();
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { ReglesOptionelles } from "../settings/regles-optionelles.js";
|
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||||
import { EffetsDraconiques } from "../tmr/effets-draconiques.js";
|
import { EffetsDraconiques } from "../tmr/effets-draconiques.js";
|
||||||
|
|
||||||
export class DialogRepos extends Dialog {
|
export class DialogRepos extends Dialog {
|
||||||
@@ -7,7 +7,7 @@ export class DialogRepos extends Dialog {
|
|||||||
if (!actor.isPersonnage()) {
|
if (!actor.isPersonnage()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (!ReglesOptionelles.isUsing("chateau-dormant-gardien") || !actor.hasPlayerOwner) {
|
if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !actor.hasPlayerOwner) {
|
||||||
actor.system.sommeil = {
|
actor.system.sommeil = {
|
||||||
"nouveaujour": true,
|
"nouveaujour": true,
|
||||||
"insomnie": EffetsDraconiques.isSujetInsomnie(actor),
|
"insomnie": EffetsDraconiques.isSujetInsomnie(actor),
|
||||||
|
34
module/time/auto-adjust-darkness.js
Normal file
34
module/time/auto-adjust-darkness.js
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import { SYSTEM_RDD } from "../constants.js";
|
||||||
|
|
||||||
|
export const AUTO_ADJUST_DARKNESS = "auto-adjust-darkness";
|
||||||
|
|
||||||
|
export class AutoAdjustDarkness {
|
||||||
|
|
||||||
|
static init() {
|
||||||
|
game.settings.register(SYSTEM_RDD, AUTO_ADJUST_DARKNESS, {
|
||||||
|
name: AUTO_ADJUST_DARKNESS,
|
||||||
|
scope: "world",
|
||||||
|
config: false,
|
||||||
|
default: true,
|
||||||
|
type: Boolean
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static async adjust(darkness) {
|
||||||
|
if (AutoAdjustDarkness.isAuto()) {
|
||||||
|
const scene = game.scenes.viewed;
|
||||||
|
if (scene?.globalLight && scene?.tokenVision) {
|
||||||
|
await scene.update({ darkness });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static isAuto() {
|
||||||
|
return game.settings.get(SYSTEM_RDD, AUTO_ADJUST_DARKNESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async toggle() {
|
||||||
|
const previous = AutoAdjustDarkness.isAuto();
|
||||||
|
await game.settings.set(SYSTEM_RDD, AUTO_ADJUST_DARKNESS, !previous)
|
||||||
|
}
|
||||||
|
}
|
@@ -5,10 +5,11 @@ import { RdDUtility } from "../rdd-utility.js";
|
|||||||
import { RdDDice } from "../rdd-dice.js";
|
import { RdDDice } from "../rdd-dice.js";
|
||||||
import { Misc } from "../misc.js";
|
import { Misc } from "../misc.js";
|
||||||
import { DialogChronologie } from "../dialog-chronologie.js";
|
import { DialogChronologie } from "../dialog-chronologie.js";
|
||||||
import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "../constants.js";
|
import { HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "../constants.js";
|
||||||
import { ReglesOptionelles } from "../settings/regles-optionelles.js";
|
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||||
import { DialogChateauDormant } from "../sommeil/dialog-chateau-dormant.js";
|
import { DialogChateauDormant } from "../sommeil/dialog-chateau-dormant.js";
|
||||||
import { APP_ASTROLOGIE_REFRESH, AppAstrologie } from "../sommeil/app-astrologie.js";
|
import { APP_ASTROLOGIE_REFRESH, AppAstrologie } from "../sommeil/app-astrologie.js";
|
||||||
|
import { AutoAdjustDarkness } from "./auto-adjust-darkness.js";
|
||||||
|
|
||||||
const TEMPLATE_CALENDRIER = "systems/foundryvtt-reve-de-dragon/templates/time/calendar.hbs";
|
const TEMPLATE_CALENDRIER = "systems/foundryvtt-reve-de-dragon/templates/time/calendar.hbs";
|
||||||
|
|
||||||
@@ -51,7 +52,7 @@ export class RdDCalendrier extends Application {
|
|||||||
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
|
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
|
||||||
RdDTimestamp.setWorldTime(this.timestamp);
|
RdDTimestamp.setWorldTime(this.timestamp);
|
||||||
this.nombresAstraux = this.getNombresAstraux();
|
this.nombresAstraux = this.getNombresAstraux();
|
||||||
this.rebuildNombresAstraux(HIDE_DICE); // Ensure always up-to-date
|
this.rebuildNombresAstraux(); // Ensure always up-to-date
|
||||||
}
|
}
|
||||||
Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id));
|
Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id));
|
||||||
}
|
}
|
||||||
@@ -84,33 +85,22 @@ export class RdDCalendrier extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
display() {
|
display() {
|
||||||
|
AutoAdjustDarkness.adjust(RdDTimestamp.getWorldTime().darkness);
|
||||||
const pos = this.getSavePosition()
|
const pos = this.getSavePosition()
|
||||||
this.render(true, { left: pos.left, top: pos.top });
|
this.render(true, { left: pos.left, top: pos.top });
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
_getHeaderButtons() {
|
_getHeaderButtons() {
|
||||||
const buttons = [];
|
|
||||||
if (game.user.isGM) {
|
if (game.user.isGM) {
|
||||||
buttons.unshift({
|
return [
|
||||||
class: "calendar-astrologie",
|
{ class: "calendar-astrologie", icon: "fa-solid fa-moon-over-sun", onclick: ev => this.showAstrologieEditor() },
|
||||||
icon: "fa-solid fa-moon-over-sun",
|
{ class: "calendar-set-datetime", icon: "fa-solid fa-calendar-pen", onclick: ev => this.showCalendarEditor() },
|
||||||
onclick: ev => this.showAstrologieEditor()
|
]
|
||||||
},
|
|
||||||
{
|
|
||||||
class: "calendar-set-datetime",
|
|
||||||
icon: "fa-solid fa-calendar-pen",
|
|
||||||
onclick: ev => this.showCalendarEditor()
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
return buttons
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
/*async maximize() {
|
|
||||||
await super.maximize()
|
|
||||||
this.render(true)
|
|
||||||
}*/
|
|
||||||
|
|
||||||
async close() { }
|
async close() { }
|
||||||
|
|
||||||
async onUpdateSetting(setting, update, options, id) {
|
async onUpdateSetting(setting, update, options, id) {
|
||||||
@@ -134,6 +124,7 @@ export class RdDCalendrier extends Application {
|
|||||||
formData.isGM = game.user.isGM;
|
formData.isGM = game.user.isGM;
|
||||||
formData.heures = RdDTimestamp.definitions()
|
formData.heures = RdDTimestamp.definitions()
|
||||||
formData.horlogeAnalogique = this.horlogeAnalogique;
|
formData.horlogeAnalogique = this.horlogeAnalogique;
|
||||||
|
formData.autoDarkness = AutoAdjustDarkness.isAuto()
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +135,7 @@ export class RdDCalendrier extends Application {
|
|||||||
this.html = html;
|
this.html = html;
|
||||||
this.html.find('.ajout-chronologie').click(ev => DialogChronologie.create());
|
this.html.find('.ajout-chronologie').click(ev => DialogChronologie.create());
|
||||||
this.html.find('.toggle-horloge-analogique').click(ev => this.onToggleHorlogeAnalogique())
|
this.html.find('.toggle-horloge-analogique').click(ev => this.onToggleHorlogeAnalogique())
|
||||||
|
this.html.find('.toggle-auto-darkness').click(ev => this.onToggleAutoDarkness())
|
||||||
this.html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));
|
this.html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));
|
||||||
this.html.find('.horloge-roue .horloge-heure').click(event => {
|
this.html.find('.horloge-roue .horloge-heure').click(event => {
|
||||||
const h = this.html.find(event.currentTarget)?.data('heure');
|
const h = this.html.find(event.currentTarget)?.data('heure');
|
||||||
@@ -229,15 +221,8 @@ export class RdDCalendrier extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async ajouterNombreAstral(indexDate, showDice = SHOW_DICE) {
|
async ajouterNombreAstral(indexDate) {
|
||||||
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: showDice, rollMode: "selfroll" });
|
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: HIDE_DICE, rollMode: "selfroll" });
|
||||||
const dateFuture = RdDTimestamp.formatIndexDate(indexDate);
|
|
||||||
if (showDice != HIDE_DICE) {
|
|
||||||
ChatMessage.create({
|
|
||||||
whisper: ChatMessage.getWhisperRecipients("GM"),
|
|
||||||
content: `Le chiffre astrologique du ${dateFuture} sera le ${nombreAstral}`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return {
|
return {
|
||||||
nombreAstral: nombreAstral,
|
nombreAstral: nombreAstral,
|
||||||
valeursFausses: [],
|
valeursFausses: [],
|
||||||
@@ -272,9 +257,8 @@ export class RdDCalendrier extends Application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async rebuildNombresAstraux(showDice = HIDE_DICE) {
|
async rebuildNombresAstraux() {
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
console.log("Astral rebuild")
|
|
||||||
let newList = [];
|
let newList = [];
|
||||||
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
|
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
|
||||||
let dayIndex = this.timestamp.indexDate + i;
|
let dayIndex = this.timestamp.indexDate + i;
|
||||||
@@ -282,7 +266,7 @@ export class RdDCalendrier extends Application {
|
|||||||
if (na) {
|
if (na) {
|
||||||
newList[i] = na;
|
newList[i] = na;
|
||||||
} else {
|
} else {
|
||||||
newList[i] = await this.ajouterNombreAstral(dayIndex, showDice);
|
newList[i] = await this.ajouterNombreAstral(dayIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.nombresAstraux = newList;
|
this.nombresAstraux = newList;
|
||||||
@@ -305,7 +289,7 @@ export class RdDCalendrier extends Application {
|
|||||||
const oldTimestamp = this.timestamp;
|
const oldTimestamp = this.timestamp;
|
||||||
await Promise.all(game.actors.map(async actor => await actor.onTimeChanging(oldTimestamp, newTimestamp)));
|
await Promise.all(game.actors.map(async actor => await actor.onTimeChanging(oldTimestamp, newTimestamp)));
|
||||||
RdDTimestamp.setWorldTime(newTimestamp);
|
RdDTimestamp.setWorldTime(newTimestamp);
|
||||||
if (oldTimestamp.indexDate + 1 == newTimestamp.indexDate && ReglesOptionelles.isUsing("chateau-dormant-gardien")) {
|
if (oldTimestamp.indexDate + 1 == newTimestamp.indexDate && ReglesOptionnelles.isUsing("chateau-dormant-gardien")) {
|
||||||
await DialogChateauDormant.create();
|
await DialogChateauDormant.create();
|
||||||
}
|
}
|
||||||
this.timestamp = newTimestamp;
|
this.timestamp = newTimestamp;
|
||||||
@@ -380,7 +364,7 @@ export class RdDCalendrier extends Application {
|
|||||||
if (request.rolled.isSuccess) {
|
if (request.rolled.isSuccess) {
|
||||||
if (request.rolled.isPart) {
|
if (request.rolled.isPart) {
|
||||||
// Gestion expérience (si existante)
|
// Gestion expérience (si existante)
|
||||||
request.competence = actor.getCompetence("astrologie")
|
request.competence = actor.getCompetence('Astrologie')
|
||||||
request.selectedCarac = actor.system.carac["vue"];
|
request.selectedCarac = actor.system.carac["vue"];
|
||||||
actor.appliquerAjoutExperience(request, 'hide');
|
actor.appliquerAjoutExperience(request, 'hide');
|
||||||
}
|
}
|
||||||
@@ -452,4 +436,9 @@ export class RdDCalendrier extends Application {
|
|||||||
async showAstrologieEditor() {
|
async showAstrologieEditor() {
|
||||||
await AppAstrologie.create();
|
await AppAstrologie.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async onToggleAutoDarkness() {
|
||||||
|
await AutoAdjustDarkness.toggle()
|
||||||
|
this.display()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ import { SHOW_DICE, SYSTEM_RDD } from "../constants.js";
|
|||||||
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 { AutoAdjustDarkness } from "./auto-adjust-darkness.js";
|
||||||
|
|
||||||
export const WORLD_TIMESTAMP_SETTING = "calendrier";
|
export const WORLD_TIMESTAMP_SETTING = "calendrier";
|
||||||
|
|
||||||
@@ -15,18 +16,18 @@ export const RDD_MINUTES_PAR_JOUR = 1440; //RDD_HEURES_PAR_JOUR * RDD_MINUTES_PA
|
|||||||
const ROUNDS_PAR_MINUTE = 10;
|
const ROUNDS_PAR_MINUTE = 10;
|
||||||
|
|
||||||
const DEFINITION_HEURES = [
|
const DEFINITION_HEURES = [
|
||||||
{ key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "Printemps" },
|
{ key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "Printemps" , darkness: 0.7},
|
||||||
{ key: "sirene", label: "Sirène", lettreFont: 'i', saison: "Printemps" },
|
{ key: "sirene", label: "Sirène", lettreFont: 'i', saison: "Printemps" , darkness: 0.4},
|
||||||
{ key: "faucon", label: "Faucon", lettreFont: 'f', saison: "Printemps" },
|
{ key: "faucon", label: "Faucon", lettreFont: 'f', saison: "Printemps" , darkness: 0},
|
||||||
{ key: "couronne", label: "Couronne", lettreFont: '', saison: "Eté" },
|
{ key: "couronne", label: "Couronne", lettreFont: '', saison: "Eté" , darkness: 0},
|
||||||
{ key: "dragon", label: "Dragon", lettreFont: 'd', saison: "Eté" },
|
{ key: "dragon", label: "Dragon", lettreFont: 'd', saison: "Eté", darkness: 0 },
|
||||||
{ key: "epees", label: "Epées", lettreFont: 'e', saison: "Eté" },
|
{ key: "epees", label: "Epées", lettreFont: 'e', saison: "Eté", darkness: 0},
|
||||||
{ key: "lyre", label: "Lyre", lettreFont: 'l', saison: "Automne" },
|
{ key: "lyre", label: "Lyre", lettreFont: 'l', saison: "Automne", darkness: 0.4 },
|
||||||
{ key: "serpent", label: "Serpent", lettreFont: 's', saison: "Automne" },
|
{ key: "serpent", label: "Serpent", lettreFont: 's', saison: "Automne", darkness: 0.7 },
|
||||||
{ key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne" },
|
{ key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne", darkness: 1 },
|
||||||
{ key: "araignee", label: "Araignée", lettreFont: 'a', saison: "Hiver" },
|
{ key: "araignee", label: "Araignée", lettreFont: 'a', saison: "Hiver", darkness: 1 },
|
||||||
{ key: "roseau", label: "Roseau", lettreFont: 'r', saison: "Hiver" },
|
{ key: "roseau", label: "Roseau", lettreFont: 'r', saison: "Hiver", darkness: 1 },
|
||||||
{ key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "Hiver" },
|
{ key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "Hiver", darkness: 1 },
|
||||||
]
|
]
|
||||||
|
|
||||||
const FORMULES_DUREE = [
|
const FORMULES_DUREE = [
|
||||||
@@ -58,6 +59,7 @@ export class RdDTimestamp {
|
|||||||
type: Object
|
type: Object
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
for (let i = 0; i < DEFINITION_HEURES.length; i++) {
|
for (let i = 0; i < DEFINITION_HEURES.length; i++) {
|
||||||
DEFINITION_HEURES[i].heure = i;
|
DEFINITION_HEURES[i].heure = i;
|
||||||
DEFINITION_HEURES[i].hh = RdDTimestamp.hh(i);
|
DEFINITION_HEURES[i].hh = RdDTimestamp.hh(i);
|
||||||
@@ -66,7 +68,6 @@ export class RdDTimestamp {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static hh(heure) {
|
static hh(heure) {
|
||||||
return heure < 9 ? `0${heure + 1}` : `${heure + 1}`;
|
return heure < 9 ? `0${heure + 1}` : `${heure + 1}`;
|
||||||
}
|
}
|
||||||
@@ -156,7 +157,9 @@ export class RdDTimestamp {
|
|||||||
fields.minute.change(async (event) => await onChangeTimestamp(fields, path));
|
fields.minute.change(async (event) => await onChangeTimestamp(fields, path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static defHeure(heure) {
|
||||||
|
return DEFINITION_HEURES.find(it => (it.heure) == heure % RDD_HEURES_PAR_JOUR);
|
||||||
|
}
|
||||||
static findHeure(heure) {
|
static findHeure(heure) {
|
||||||
heure = Grammar.toLowerCaseNoAccentNoSpace(heure);
|
heure = Grammar.toLowerCaseNoAccentNoSpace(heure);
|
||||||
let parHeureOuLabel = DEFINITION_HEURES.filter(it => (it.heure) == parseInt(heure) % RDD_HEURES_PAR_JOUR || Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure);
|
let parHeureOuLabel = DEFINITION_HEURES.filter(it => (it.heure) == parseInt(heure) % RDD_HEURES_PAR_JOUR || Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure);
|
||||||
@@ -237,6 +240,13 @@ export class RdDTimestamp {
|
|||||||
get angleHeure() { return this.indexMinute / RDD_MINUTES_PAR_JOUR * 360 - 45 }
|
get angleHeure() { return this.indexMinute / RDD_MINUTES_PAR_JOUR * 360 - 45 }
|
||||||
get angleMinute() { return this.indexMinute / RDD_MINUTES_PAR_HEURES * 360 + 45 }
|
get angleMinute() { return this.indexMinute / RDD_MINUTES_PAR_HEURES * 360 + 45 }
|
||||||
|
|
||||||
|
get darkness() {
|
||||||
|
const darknessDebut = RdDTimestamp.definition(this.heure).darkness *100
|
||||||
|
const darknessFin = RdDTimestamp.definition(this.heure + 1).darkness *100
|
||||||
|
const darknessMinute = Math.round((darknessFin - darknessDebut) * this.minute / RDD_MINUTES_PAR_HEURES);
|
||||||
|
return (darknessDebut + darknessMinute)/100
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convertit le timestamp en une structure avec les informations utiles
|
* Convertit le timestamp en une structure avec les informations utiles
|
||||||
* pour afficher la date et l'heure
|
* pour afficher la date et l'heure
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
|
import { tmrConstants } from "./tmr-constants.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const TMRMapping = {
|
const TMRMapping = {
|
||||||
@@ -163,7 +164,7 @@ const TMRMapping = {
|
|||||||
C12: { type: "lac", label: "Lac de Fricassa" },
|
C12: { type: "lac", label: "Lac de Fricassa" },
|
||||||
D12: { type: "collines", label: "Collines d’Huaï" },
|
D12: { type: "collines", label: "Collines d’Huaï" },
|
||||||
E12: { type: "monts", label: "Monts Ajourés" },
|
E12: { type: "monts", label: "Monts Ajourés" },
|
||||||
F12: { type: "necropole", label: "Nécropole de Troat" },
|
F12: { type: "necropole", label: "Nécropole de Throat" },
|
||||||
G12: { type: "plaines", label: "Plaines de Lufmil" },
|
G12: { type: "plaines", label: "Plaines de Lufmil" },
|
||||||
H12: { type: "collines", label: "Collines de Tooth" },
|
H12: { type: "collines", label: "Collines de Tooth" },
|
||||||
I12: { type: "gouffre", label: "Gouffre Abimeux" },
|
I12: { type: "gouffre", label: "Gouffre Abimeux" },
|
||||||
@@ -275,10 +276,10 @@ export class TMRUtility {
|
|||||||
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label;
|
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
static findTMRLike(type, options = {inclusMauvaise:true}) {
|
static findTMRLike(type, options = { inclusMauvaise: true }) {
|
||||||
const choix = [...Object.values(TMRType)]
|
const choix = [...Object.values(TMRType)]
|
||||||
if (options.inclusMauvaise){
|
if (options.inclusMauvaise) {
|
||||||
choix.push({name: 'Mauvaise'});
|
choix.push({ name: 'Mauvaise' });
|
||||||
}
|
}
|
||||||
const selection = Misc.findAllLike(type, choix).map(it => it.name);
|
const selection = Misc.findAllLike(type, choix).map(it => it.name);
|
||||||
if (selection.length == 0) {
|
if (selection.length == 0) {
|
||||||
@@ -297,7 +298,7 @@ export class TMRUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static buildSelectionTypesTMR(typesTMR) {
|
static buildSelectionTypesTMR(typesTMR) {
|
||||||
typesTMR = typesTMR?? [];
|
typesTMR = typesTMR ?? [];
|
||||||
return Object.values(TMRType).map(value => Misc.upperFirst(value.name))
|
return Object.values(TMRType).map(value => Misc.upperFirst(value.name))
|
||||||
.sort()
|
.sort()
|
||||||
.map(name => { return { name: name, selected: typesTMR.includes(name) } });
|
.map(name => { return { name: name, selected: typesTMR.includes(name) } });
|
||||||
@@ -375,6 +376,36 @@ export class TMRUtility {
|
|||||||
return caseList;
|
return caseList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// /* -------------------------------------------- */
|
||||||
|
static computeEventPosition(event) {
|
||||||
|
if (!event.nativeEvent.target.getBoundingClientRect) {
|
||||||
|
return { x: 0, y: 0 }
|
||||||
|
}
|
||||||
|
const canvasRect = event.nativeEvent.target.getBoundingClientRect();
|
||||||
|
return {
|
||||||
|
x: event.nativeEvent.clientX - canvasRect.left,
|
||||||
|
y: event.nativeEvent.clientY - canvasRect.top
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static computeEventOddq(event) {
|
||||||
|
var { x, y } = TMRUtility.computeEventPosition(event);
|
||||||
|
return TMRUtility.computeOddq(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static computeOddq(x, y) {
|
||||||
|
const col = Math.floor(x / tmrConstants.cellw); // [From 0 -> 12]
|
||||||
|
const decallageColonne = col % 2 == 0 ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||||
|
const row = Math.floor((y - decallageColonne) / tmrConstants.cellh); // [From 0 -> 14]
|
||||||
|
return { col, row };
|
||||||
|
}
|
||||||
|
|
||||||
|
static computeEventCoord(event) {
|
||||||
|
const oddq = TMRUtility.computeEventOddq(event);
|
||||||
|
return TMRUtility.oddqToCoordTMR(oddq);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// https://www.redblobgames.com/grids/hexagons/#distances
|
// https://www.redblobgames.com/grids/hexagons/#distances
|
||||||
// TMR Letter-row correspond to "odd-q" grid (letter => col, numeric => row )
|
// TMR Letter-row correspond to "odd-q" grid (letter => col, numeric => row )
|
||||||
@@ -400,7 +431,7 @@ export class TMRUtility {
|
|||||||
col >= 0 && col < 13 &&
|
col >= 0 && col < 13 &&
|
||||||
row >= 0 &&
|
row >= 0 &&
|
||||||
(row + col % 2 <= 14)
|
(row + col % 2 <= 14)
|
||||||
);
|
);
|
||||||
// if (x >= 0 && x < 13 && y >= 0 && y < 14) return true;
|
// if (x >= 0 && x < 13 && y >= 0 && y < 14) return true;
|
||||||
// if (x >= 0 && x < 13 && x % 2 == 0 && y == 14) return true;
|
// if (x >= 0 && x < 13 && x % 2 == 0 && y == 14) return true;
|
||||||
// return false;
|
// return false;
|
||||||
@@ -444,7 +475,7 @@ export class TMRUtility {
|
|||||||
|
|
||||||
static axial_subtract(a, b) {
|
static axial_subtract(a, b) {
|
||||||
return {
|
return {
|
||||||
q: a.q- b.q,
|
q: a.q - b.q,
|
||||||
r: a.r - b.r
|
r: a.r - b.r
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
|
import { TMRUtility } from "../tmr-utility.js";
|
||||||
import { Draconique } from "./draconique.js";
|
import { Draconique } from "./draconique.js";
|
||||||
import { PixiTMR } from "./pixi-tmr.js";
|
import { PixiTMR } from "./pixi-tmr.js";
|
||||||
|
|
||||||
export class CarteTmr extends Draconique {
|
export class CarteTmr extends Draconique {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
console.log("Sprite create 1!!!!")
|
|
||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -14,9 +14,26 @@ export class CarteTmr extends Draconique {
|
|||||||
async onActorCreateOwned(actor, item) { }
|
async onActorCreateOwned(actor, item) { }
|
||||||
|
|
||||||
code() { return 'tmr' }
|
code() { return 'tmr' }
|
||||||
img() { return 'systems/foundryvtt-reve-de-dragon/styles/img/ui/tmp_main_r1.webp' }
|
img() { return 'systems/foundryvtt-reve-de-dragon/styles/img/ui/tmr.webp' }
|
||||||
|
|
||||||
createSprite(pixiTMR) {
|
createSprite(pixiTMR) {
|
||||||
return pixiTMR.carteTmr(this.code());
|
const img = PixiTMR.getImgFromCode(this.code())
|
||||||
|
const sprite = new PIXI.Sprite(PIXI.utils.TextureCache[img]);
|
||||||
|
// Setup the position of the TMR
|
||||||
|
sprite.x = 0;
|
||||||
|
sprite.y = 0;
|
||||||
|
sprite.width = 722;
|
||||||
|
sprite.height = 860;
|
||||||
|
// Rotate around the center
|
||||||
|
sprite.anchor.set(0);
|
||||||
|
sprite.buttonMode = true;
|
||||||
|
sprite.tmrObject = pixiTMR;
|
||||||
|
return sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
computeTooltip(coordTMR) {
|
||||||
|
const tmr = TMRUtility.getTMR(coordTMR)
|
||||||
|
return tmr? TMRUtility.getTMRLabel(coordTMR) : '';
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -11,7 +11,7 @@ const registeredEffects = [
|
|||||||
export class Draconique {
|
export class Draconique {
|
||||||
static isCaseTMR(item) { return item.type == TYPES.casetmr; }
|
static isCaseTMR(item) { return item.type == TYPES.casetmr; }
|
||||||
static isQueueDragon(item) { return item.isQueueDragon(); }
|
static isQueueDragon(item) { return item.isQueueDragon(); }
|
||||||
static isSouffleDragon(item) {return item.type == TYPES.souffle; }
|
static isSouffleDragon(item) { return item.type == TYPES.souffle; }
|
||||||
static isTeteDragon(item) { return item.type == TYPES.tete; }
|
static isTeteDragon(item) { return item.type == TYPES.tete; }
|
||||||
static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); }
|
static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); }
|
||||||
|
|
||||||
@@ -78,25 +78,43 @@ export class Draconique {
|
|||||||
/**
|
/**
|
||||||
* @param {*} img l'url du fichier image à utiliser pour le token. Si indéfini (et si createSprite n'est pas surchargé),
|
* @param {*} img l'url du fichier image à utiliser pour le token. Si indéfini (et si createSprite n'est pas surchargé),
|
||||||
* un disque est utilisé.
|
* un disque est utilisé.
|
||||||
*/
|
*/
|
||||||
img() { return undefined }
|
img() { return undefined }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* factory d'élément graphique PIXI correpsondant à l'objet draconique
|
* factory d'élément graphique PIXI correspondant à l'objet draconique
|
||||||
* @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks.
|
* @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks.
|
||||||
*/
|
*/
|
||||||
token(pixiTMR, linkData, coordTMR, type = undefined) {
|
token(pixiTMR, linkData, coordTMR, type = undefined) {
|
||||||
|
const tooltip = this.tooltip(linkData);
|
||||||
const token = {
|
const token = {
|
||||||
sprite: this.createSprite(pixiTMR),
|
sprite: this.createSprite(pixiTMR),
|
||||||
coordTMR: coordTMR
|
coordTMR: coordTMR,
|
||||||
|
tooltip: tooltip
|
||||||
};
|
};
|
||||||
token[type ?? this.code()] = linkData;
|
token[type ?? this.code()] = linkData;
|
||||||
console.log("SPRITE: ", token.sprite)
|
|
||||||
//PixiTMR.getImgFromCode()
|
|
||||||
pixiTMR.addTooltip(token.sprite, this.tooltip(linkData));
|
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* methode en charge de recalculer le tooltip lorsque la souris bouge
|
||||||
|
* @param {*} event evenement contenant les coordonnées
|
||||||
|
* @param {*} sprite sprite pour laquelle calculer le tooltip
|
||||||
|
*/
|
||||||
|
computeTooltip(event, sprite) {
|
||||||
|
if (sprite.isOver) {
|
||||||
|
const oddq = TMRUtility.computeEventOddq(event);
|
||||||
|
const coord = TMRUtility.oddqToCoordTMR(oddq);
|
||||||
|
const tmr = TMRUtility.getTMR(coord)
|
||||||
|
if (tmr){
|
||||||
|
const label = TMRUtility.getTMRLabel(coord);
|
||||||
|
const text = this.tooltip(this.linkData);
|
||||||
|
return text ? `${coord}: ${label}\n${text}` : `${coord}: ${label}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* factory d'élément graphique PIXI correpsondant à l'objet draconique
|
* factory d'élément graphique PIXI correpsondant à l'objet draconique
|
||||||
* @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks.
|
* @param {*} pixiTMR instance de PixiTMR qui gère les tooltips, les méthodes de création de sprite standard, les clicks.
|
||||||
|
@@ -2,6 +2,7 @@ import { ExperienceLog, XP_TOPIC } from "../actor/experience-log.js";
|
|||||||
import { ChatUtility } from "../chat-utility.js";
|
import { ChatUtility } from "../chat-utility.js";
|
||||||
import { Poetique } from "../poetique.js";
|
import { Poetique } from "../poetique.js";
|
||||||
import { RdDDice } from "../rdd-dice.js";
|
import { RdDDice } from "../rdd-dice.js";
|
||||||
|
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||||
import { TMRUtility } from "../tmr-utility.js";
|
import { TMRUtility } from "../tmr-utility.js";
|
||||||
|
|
||||||
export class EffetsRencontre {
|
export class EffetsRencontre {
|
||||||
@@ -26,7 +27,16 @@ export class EffetsRencontre {
|
|||||||
static reve_plus_1 = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, 1) }
|
static reve_plus_1 = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, 1) }
|
||||||
static reve_moins_force = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, -context.rencontre.system.force) }
|
static reve_moins_force = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, -context.rencontre.system.force) }
|
||||||
static reve_moins_1 = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, -1) }
|
static reve_moins_1 = async (dialog, context) => { await EffetsRencontre.$reve_plus(context.actor, -1) }
|
||||||
static $reve_plus = async (actor, valeur) => { await actor.reveActuelIncDec(valeur) }
|
static $reve_plus = async (actor, reve) => {
|
||||||
|
if (!ReglesOptionnelles.isUsing("recuperation-reve") && reve < 0) {
|
||||||
|
ChatMessage.create({
|
||||||
|
whisper: ChatUtility.getWhisperRecipientsAndGMs(actor.name),
|
||||||
|
content: `Pas de récupération de rêve (${reve} points ignorés)`
|
||||||
|
});
|
||||||
|
return
|
||||||
|
}
|
||||||
|
await actor.reveActuelIncDec(reve)
|
||||||
|
}
|
||||||
|
|
||||||
static vie_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
|
static vie_moins_1 = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -1) }
|
||||||
static vie_moins_force = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -context.rencontre.system.force) }
|
static vie_moins_force = async (dialog, context) => { await EffetsRencontre.$vie_plus(context.actor, -context.rencontre.system.force) }
|
||||||
@@ -75,7 +85,7 @@ export class EffetsRencontre {
|
|||||||
|
|
||||||
static demireve_rompu = async (dialog, context) => {
|
static demireve_rompu = async (dialog, context) => {
|
||||||
dialog.close()
|
dialog.close()
|
||||||
}
|
}
|
||||||
|
|
||||||
static sort_aleatoire = async (dialog, context) => {
|
static sort_aleatoire = async (dialog, context) => {
|
||||||
context.sortReserve = await RdDDice.rollOneOf(context.actor.itemTypes['sortreserve']);
|
context.sortReserve = await RdDDice.rollOneOf(context.actor.itemTypes['sortreserve']);
|
||||||
@@ -128,7 +138,7 @@ export class EffetsRencontre {
|
|||||||
|
|
||||||
static regain_seuil = async (dialog, context) => {
|
static regain_seuil = async (dialog, context) => {
|
||||||
await context.actor.regainPointDeSeuil()
|
await context.actor.regainPointDeSeuil()
|
||||||
}
|
}
|
||||||
|
|
||||||
static async $reinsertion(dialog, actor, filter) {
|
static async $reinsertion(dialog, actor, filter) {
|
||||||
const newTMR = await TMRUtility.getTMRAleatoire(filter);
|
const newTMR = await TMRUtility.getTMRAleatoire(filter);
|
||||||
|
@@ -1,6 +1,10 @@
|
|||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { RdDTMRDialog } from "../rdd-tmr-dialog.js";
|
||||||
import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js";
|
import { tmrConstants, tmrTokenZIndex } from "../tmr-constants.js";
|
||||||
|
import { TMRUtility } from "../tmr-utility.js";
|
||||||
|
import { EffetsDraconiques } from "./effets-draconiques.js";
|
||||||
|
|
||||||
const tooltipStyle = new PIXI.TextStyle({
|
export const tooltipStyle = new PIXI.TextStyle({
|
||||||
fontFamily: 'CaslonAntique',
|
fontFamily: 'CaslonAntique',
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fill: '#FFFFFF',
|
fill: '#FFFFFF',
|
||||||
@@ -13,14 +17,38 @@ export class PixiTMR {
|
|||||||
|
|
||||||
static textures = []
|
static textures = []
|
||||||
|
|
||||||
constructor(tmrObject, pixiApp) {
|
constructor(tmrDialog) {
|
||||||
this.tmrObject = tmrObject;
|
this.tmrDialog = tmrDialog;
|
||||||
this.pixiApp = pixiApp ?? tmrObject.pixiApp;
|
|
||||||
this.pixiApp.stage.sortableChildren = true;
|
|
||||||
this.callbacksOnAnimate = [];
|
this.callbacksOnAnimate = [];
|
||||||
|
|
||||||
|
this.pixiApp = new PIXI.Application({ width: 720, height: 860 });
|
||||||
|
this.pixiApp.eventMode = 'static';
|
||||||
|
this.pixiApp.stage.sortableChildren = true;
|
||||||
|
this.tooltip = new PIXI.Text('', tooltipStyle);
|
||||||
|
this.tooltip.zIndex = 1000
|
||||||
|
|
||||||
|
this.pixiApp.stage.addChild(this.tooltip);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async load( onLoad = (loader, resources) => {} ) {
|
get view() {
|
||||||
|
return this.pixiApp.view
|
||||||
|
}
|
||||||
|
|
||||||
|
setup() {
|
||||||
|
this.carteTMR = EffetsDraconiques.carteTmr.createSprite(this);
|
||||||
|
this.pixiApp.stage.addChild(this.carteTMR);
|
||||||
|
this.carteTMR.isOver = false;
|
||||||
|
this.carteTMR.eventMode = 'static';
|
||||||
|
this.carteTMR
|
||||||
|
.on('pointermove', event => this.onPointerMove(event))
|
||||||
|
.on('pointerdown', event => this.onClickBackground(event))
|
||||||
|
.on('pointerover', event => this.onShowTooltip(event))
|
||||||
|
.on('pointerout', event => this.onHideTooltip(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
async load(onLoad = (loader, resources) => { }) {
|
||||||
// WIP - Deprecated since v7 : let loader = new PIXI.Loader();
|
// WIP - Deprecated since v7 : let loader = new PIXI.Loader();
|
||||||
for (const [name, img] of Object.entries(PixiTMR.textures)) {
|
for (const [name, img] of Object.entries(PixiTMR.textures)) {
|
||||||
const texture = await PIXI.Assets.load(img);
|
const texture = await PIXI.Assets.load(img);
|
||||||
@@ -40,31 +68,24 @@ export class PixiTMR {
|
|||||||
PixiTMR.textures[name] = img;
|
PixiTMR.textures[name] = img;
|
||||||
}
|
}
|
||||||
|
|
||||||
animate(animation = pixiApp=>{})
|
animate(animation = pixiApp => { }) {
|
||||||
{
|
|
||||||
this.callbacksOnAnimate.push(() => animation(this.pixiApp));
|
this.callbacksOnAnimate.push(() => animation(this.pixiApp));
|
||||||
}
|
}
|
||||||
|
|
||||||
carteTmr(code) {
|
addMarkTMR(coordTMR) {
|
||||||
let img = PixiTMR.getImgFromCode(code)
|
const rect = this.getCaseRectangle(TMRUtility.coordTMRToOddq(coordTMR))
|
||||||
const carteTmr = new PIXI.Sprite(PIXI.utils.TextureCache[img]);
|
const markTMR = new PIXI.Graphics();
|
||||||
console.log(code, carteTmr)
|
markTMR.beginFill(0xffff00, 0.3);
|
||||||
// Setup the position of the TMR
|
// set the line style to have a width of 5 and set the color to red
|
||||||
carteTmr.x = 0;
|
markTMR.lineStyle(5, 0xff0000);
|
||||||
carteTmr.y = 0;
|
// draw a rectangle
|
||||||
carteTmr.width = 720;
|
markTMR.drawRect(rect.x, rect.y, rect.w, rect.h);
|
||||||
carteTmr.height = 860;
|
this.pixiApp.stage.addChild(markTMR);
|
||||||
// Rotate around the center
|
return markTMR
|
||||||
carteTmr.anchor.set(0);
|
}
|
||||||
carteTmr.eventMode = 'dynamic'; // PIXI 7 : Not sure ..
|
|
||||||
// This one is deprecated ; carteTmr.interactive = true;
|
removeGraphic(graphic) {
|
||||||
carteTmr.buttonMode = true;
|
this.pixiApp.stage.removeChild(graphic);
|
||||||
carteTmr.tmrObject = this;
|
|
||||||
if (!this.tmrObject.viewOnly) {
|
|
||||||
carteTmr.on('pointerdown', event => this.onClickBackground(event));
|
|
||||||
}
|
|
||||||
this.pixiApp.stage.addChild(carteTmr);
|
|
||||||
return carteTmr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sprite(code, options = {}) {
|
sprite(code, options = {}) {
|
||||||
@@ -81,14 +102,14 @@ export class PixiTMR {
|
|||||||
if (options.color) {
|
if (options.color) {
|
||||||
sprite.tint = options.color;
|
sprite.tint = options.color;
|
||||||
}
|
}
|
||||||
sprite.zIndex = options.zIndex ?? tmrTokenZIndex.casehumide+1;
|
sprite.zIndex = options.zIndex ?? tmrTokenZIndex.casehumide + 1;
|
||||||
sprite.alpha = options.alpha ?? 0.75;
|
sprite.alpha = options.alpha ?? 0.75;
|
||||||
sprite.decallage = options.decallage ?? tmrConstants.center;
|
sprite.decallage = options.decallage ?? tmrConstants.center;
|
||||||
this.pixiApp.stage.addChild(sprite);
|
this.pixiApp.stage.addChild(sprite);
|
||||||
return sprite;
|
return sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
circle(name, options = {}) {
|
circle(code, options = {}) {
|
||||||
let sprite = new PIXI.Graphics();
|
let sprite = new PIXI.Graphics();
|
||||||
sprite.beginFill(options.color, options.opacity);
|
sprite.beginFill(options.color, options.opacity);
|
||||||
sprite.drawCircle(0, 0, (options.taille ?? 12) / 2);
|
sprite.drawCircle(0, 0, (options.taille ?? 12) / 2);
|
||||||
@@ -98,51 +119,74 @@ export class PixiTMR {
|
|||||||
return sprite;
|
return sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
addTooltip(sprite, text) {
|
|
||||||
if (text) {
|
|
||||||
sprite.tooltip = new PIXI.Text(text, tooltipStyle);
|
|
||||||
sprite.tooltip.zIndex = tmrTokenZIndex.tooltip;
|
|
||||||
sprite.isOver = false;
|
|
||||||
// Deprecated : sprite.interactive = true;
|
|
||||||
sprite.eventMode = 'dynamic'; // PIXI 7 To be checked
|
|
||||||
sprite.on('pointerdown', event => this.onClickBackground(event))
|
|
||||||
.on('pointerover', () => this.onShowTooltip(sprite))
|
|
||||||
.on('pointerout', () => this.onHideTooltip(sprite));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
onClickBackground(event) {
|
onClickBackground(event) {
|
||||||
this.tmrObject.onClickTMR(event)
|
if (!this.viewOnly) {
|
||||||
}
|
this.tmrDialog.onClickTMR(event)
|
||||||
|
|
||||||
onShowTooltip(sprite) {
|
|
||||||
if (sprite.tooltip) {
|
|
||||||
|
|
||||||
if (!sprite.isOver) {
|
|
||||||
sprite.tooltip.x = sprite.x;
|
|
||||||
sprite.tooltip.y = sprite.y;
|
|
||||||
this.pixiApp.stage.addChild(sprite.tooltip);
|
|
||||||
}
|
|
||||||
sprite.isOver = true;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onHideTooltip(sprite) {
|
onPointerMove(event) {
|
||||||
if (sprite.tooltip) {
|
if (this.carteTMR.isOver) {
|
||||||
if (sprite.isOver) {
|
this.setTooltipPosition(event);
|
||||||
this.pixiApp.stage.removeChild(sprite.tooltip);
|
this.tooltip.text = this.computeTooltip(event);
|
||||||
}
|
|
||||||
sprite.isOver = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setPosition( sprite, oddq) {
|
onShowTooltip(event) {
|
||||||
let decallagePairImpair = (oddq.col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
|
if (!this.carteTMR.isOver) {
|
||||||
let dx = (sprite.decallage == undefined) ? 0 : sprite.decallage.x;
|
this.setTooltipPosition(event);
|
||||||
let dy = (sprite.decallage == undefined) ? 0 : sprite.decallage.y;
|
this.pixiApp.stage.addChild(this.tooltip);
|
||||||
sprite.x = tmrConstants.gridx + (oddq.col * tmrConstants.cellw) + dx;
|
this.tooltip.text = this.computeTooltip(event);
|
||||||
sprite.y = tmrConstants.gridy + (oddq.row * tmrConstants.cellh) + dy + decallagePairImpair;
|
}
|
||||||
|
this.carteTMR.isOver = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
onHideTooltip(event) {
|
||||||
|
if (this.carteTMR.isOver) {
|
||||||
|
this.pixiApp.stage.removeChild(this.tooltip);
|
||||||
|
}
|
||||||
|
this.carteTMR.isOver = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
computeTooltip(event) {
|
||||||
|
const oddq = TMRUtility.computeEventOddq(event);
|
||||||
|
const coordTMR = TMRUtility.oddqToCoordTMR(oddq);
|
||||||
|
const tmr = TMRUtility.getTMR(coordTMR)
|
||||||
|
if (tmr) {
|
||||||
|
const labelTMR = TMRUtility.getTMRLabel(coordTMR);
|
||||||
|
const tokenTooltips = this.tmrDialog.allTokens
|
||||||
|
.filter(token => token.coordTMR() == coordTMR)
|
||||||
|
.map(token => token.tooltip);
|
||||||
|
const tmrTooltip = `${coordTMR}: ${labelTMR}`;
|
||||||
|
return [tmrTooltip, ...tokenTooltips].reduce(Misc.joining('\n'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setTooltipPosition(event) {
|
||||||
|
var { x, y } = TMRUtility.computeEventPosition(event);
|
||||||
|
const oddq = TMRUtility.computeOddq(x, y);
|
||||||
|
|
||||||
|
this.tooltip.x = x + (oddq.col > 8 ? -3 * tmrConstants.full : tmrConstants.half);
|
||||||
|
this.tooltip.y = y + (oddq.row > 10 ? -tmrConstants.half : tmrConstants.half);
|
||||||
|
}
|
||||||
|
|
||||||
|
positionToken(token) {
|
||||||
|
if (token.sprite) {
|
||||||
|
const sprite = token.sprite;
|
||||||
|
const oddq = TMRUtility.coordTMRToOddq(token.coordTMR());
|
||||||
|
|
||||||
|
const decallagePairImpair = (oddq.col % 2 == 0) ? tmrConstants.col1_y : tmrConstants.col2_y;
|
||||||
|
const dx = (sprite.decallage == undefined) ? 0 : sprite.decallage.x;
|
||||||
|
const dy = (sprite.decallage == undefined) ? 0 : sprite.decallage.y;
|
||||||
|
sprite.x = tmrConstants.gridx + (oddq.col * tmrConstants.cellw) + dx;
|
||||||
|
sprite.y = tmrConstants.gridy + (oddq.row * tmrConstants.cellh) + dy + decallagePairImpair;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
removeToken(token) {
|
||||||
|
if (token.sprite) {
|
||||||
|
this.pixiApp.stage.removeChild(token.sprite)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getCaseRectangle(oddq) {
|
getCaseRectangle(oddq) {
|
||||||
|
@@ -49,12 +49,13 @@ export class PresentCites extends Draconique {
|
|||||||
const presents = await game.system.rdd.rencontresTMR.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 dialog = new Dialog({
|
||||||
title: "Présent des cités",
|
title: "Présent des cités",
|
||||||
content: `La ${this.tmrLabel(casetmr)} vous offre un présent, faites votre choix`,
|
content: `La ${this.tmrLabel(casetmr)} vous offre un présent, faites votre choix`,
|
||||||
buttons: buttons
|
buttons: buttons
|
||||||
});
|
});
|
||||||
d.render(true);
|
dialog.render(true);
|
||||||
|
return dialog
|
||||||
}
|
}
|
||||||
|
|
||||||
async ouvrirLePresent(actor, casetmr) {
|
async ouvrirLePresent(actor, casetmr) {
|
||||||
|
@@ -13,8 +13,8 @@ export class ReserveExtensible extends Draconique {
|
|||||||
manualMessage() { return "Vous pouvez re-configurer votre Réserve extensible" }
|
manualMessage() { return "Vous pouvez re-configurer votre Réserve extensible" }
|
||||||
async onActorCreateOwned(actor, tete) {
|
async onActorCreateOwned(actor, tete) {
|
||||||
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
||||||
const tmr = await TMRUtility.getTMRAleatoire(it => !(it.type == 'fleuve' || existants.includes(it.system.coord)));
|
const selectedTMR = await TMRUtility.getTMRAleatoire(tmr => !(tmr.type == 'fleuve' || existants.includes(tmr.coord)));
|
||||||
await this.createCaseTmr(actor, "Nouvelle Réserve extensible", tmr, tete.id);
|
await this.createCaseTmr(actor, "Nouvelle Réserve extensible", selectedTMR, tete.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
code() { return 'reserve_extensible' }
|
code() { return 'reserve_extensible' }
|
||||||
|
@@ -14,8 +14,8 @@ export class TrouNoir extends Draconique {
|
|||||||
|
|
||||||
async onActorCreateOwned(actor, souffle) {
|
async onActorCreateOwned(actor, souffle) {
|
||||||
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
const existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
|
||||||
const tmr = await TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.system.coord)));
|
const selectedTMR = await TMRUtility.getTMRAleatoire(tmr => !(TMRUtility.isCaseHumide(tmr) || existants.includes(tmr.coord)));
|
||||||
await this.createCaseTmr(actor, 'Trou noir: ' + tmr.label, tmr, souffle.id);
|
await this.createCaseTmr(actor, 'Trou noir: ' + selectedTMR.label, selectedTMR, souffle.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
code() { return 'trounoir' }
|
code() { return 'trounoir' }
|
||||||
|
@@ -8,15 +8,11 @@ import { Draconique } from "./draconique.js";
|
|||||||
|
|
||||||
export class UrgenceDraconique extends Draconique {
|
export class UrgenceDraconique extends Draconique {
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
type() { return 'queue' }
|
type() { return 'queue' }
|
||||||
match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); }
|
match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); }
|
||||||
manualMessage() { return false }
|
manualMessage() { return false }
|
||||||
async onActorCreateOwned(actor, queue) {
|
async onActorCreateOwned(actor, queue) {
|
||||||
const coordSortsReserve = (actor.system.reve.reserve?.list.map(it => it.coord)) ?? [];
|
const coordSortsReserve = actor.itemTypes[TYPES.sortreserve].map(it => it.system.coord) ?? [];
|
||||||
if (coordSortsReserve.length == 0) {
|
if (coordSortsReserve.length == 0) {
|
||||||
// La queue se transforme en idée fixe
|
// La queue se transforme en idée fixe
|
||||||
const ideeFixe = await RdDRollTables.getIdeeFixe();
|
const ideeFixe = await RdDRollTables.getIdeeFixe();
|
||||||
@@ -26,7 +22,6 @@ export class UrgenceDraconique extends Draconique {
|
|||||||
});
|
});
|
||||||
await actor.createEmbeddedDocuments('Item', [ideeFixe]);
|
await actor.createEmbeddedDocuments('Item', [ideeFixe]);
|
||||||
await actor.deleteEmbeddedDocuments('Item', [queue.id]);
|
await actor.deleteEmbeddedDocuments('Item', [queue.id]);
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const demiReve = actor.getDemiReve();
|
const demiReve = actor.getDemiReve();
|
||||||
|
39
packs/animaux.db
Normal file
39
packs/animaux.db
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
MANIFEST-000045
|
|
@@ -1,7 +0,0 @@
|
|||||||
2023/05/29-08:40:34.656615 7fca067fc6c0 Recovering log #43
|
|
||||||
2023/05/29-08:40:34.674483 7fca067fc6c0 Delete type=3 #41
|
|
||||||
2023/05/29-08:40:34.674520 7fca067fc6c0 Delete type=0 #43
|
|
||||||
2023/05/29-08:50:04.296687 7fca04ff96c0 Level-0 table #48: started
|
|
||||||
2023/05/29-08:50:04.296723 7fca04ff96c0 Level-0 table #48: 0 bytes OK
|
|
||||||
2023/05/29-08:50:04.302846 7fca04ff96c0 Delete type=0 #46
|
|
||||||
2023/05/29-08:50:04.323728 7fca04ff96c0 Manual compaction at level-0 from '!actors!0ogeNTXl7IwYfWZR' @ 72057594037927935 : 1 .. '!actors.items!zMvyRrp10dkfcS43.shsUV8UpU18c0RJK' @ 0 : 0; will stop at (end)
|
|
@@ -1,7 +0,0 @@
|
|||||||
2023/05/29-08:00:37.697935 7fca067fc6c0 Recovering log #39
|
|
||||||
2023/05/29-08:00:37.713407 7fca067fc6c0 Delete type=3 #37
|
|
||||||
2023/05/29-08:00:37.713452 7fca067fc6c0 Delete type=0 #39
|
|
||||||
2023/05/29-08:38:02.219865 7fca04ff96c0 Level-0 table #44: started
|
|
||||||
2023/05/29-08:38:02.219887 7fca04ff96c0 Level-0 table #44: 0 bytes OK
|
|
||||||
2023/05/29-08:38:02.226757 7fca04ff96c0 Delete type=0 #42
|
|
||||||
2023/05/29-08:38:02.239623 7fca04ff96c0 Manual compaction at level-0 from '!actors!0ogeNTXl7IwYfWZR' @ 72057594037927935 : 1 .. '!actors.items!zMvyRrp10dkfcS43.shsUV8UpU18c0RJK' @ 0 : 0; will stop at (end)
|
|
Binary file not shown.
21
packs/archetypes.db
Normal file
21
packs/archetypes.db
Normal file
File diff suppressed because one or more lines are too long
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
MANIFEST-000044
|
|
@@ -1,7 +0,0 @@
|
|||||||
2023/05/29-08:40:34.682366 7fca057fa6c0 Recovering log #42
|
|
||||||
2023/05/29-08:40:34.699920 7fca057fa6c0 Delete type=3 #40
|
|
||||||
2023/05/29-08:40:34.699959 7fca057fa6c0 Delete type=0 #42
|
|
||||||
2023/05/29-08:50:04.323849 7fca04ff96c0 Level-0 table #47: started
|
|
||||||
2023/05/29-08:50:04.323886 7fca04ff96c0 Level-0 table #47: 0 bytes OK
|
|
||||||
2023/05/29-08:50:04.330053 7fca04ff96c0 Delete type=0 #45
|
|
||||||
2023/05/29-08:50:04.352593 7fca04ff96c0 Manual compaction at level-0 from '!actors!1Nng9d8r6lrPHCaJ' @ 72057594037927935 : 1 .. '!actors.items!ryUZTa17LzNv25UY.zyNYa3hYtrOcF2jA' @ 0 : 0; will stop at (end)
|
|
@@ -1,7 +0,0 @@
|
|||||||
2023/05/29-08:00:37.736173 7fca05ffb6c0 Recovering log #38
|
|
||||||
2023/05/29-08:00:37.750924 7fca05ffb6c0 Delete type=3 #36
|
|
||||||
2023/05/29-08:00:37.750965 7fca05ffb6c0 Delete type=0 #38
|
|
||||||
2023/05/29-08:38:02.239711 7fca04ff96c0 Level-0 table #43: started
|
|
||||||
2023/05/29-08:38:02.239732 7fca04ff96c0 Level-0 table #43: 0 bytes OK
|
|
||||||
2023/05/29-08:38:02.246710 7fca04ff96c0 Delete type=0 #41
|
|
||||||
2023/05/29-08:38:02.253050 7fca04ff96c0 Manual compaction at level-0 from '!actors!1Nng9d8r6lrPHCaJ' @ 72057594037927935 : 1 .. '!actors.items!ryUZTa17LzNv25UY.zyNYa3hYtrOcF2jA' @ 0 : 0; will stop at (end)
|
|
Binary file not shown.
49
packs/arts-et-divertissements.db
Normal file
49
packs/arts-et-divertissements.db
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
{"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ès abondant après la pluie (commun). Pratiquement, cette recette peut s’appliquer à tout gibier à plume préparé 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 échalotes</li>\n<li>1 racine de réfèble</li>\n<li>1 schouillat de miel</li>\n<li>10 schouillats de beurre</li>\n<li>2 doigts d’huile</li>\n<li>5 schouillats de farine de blédiè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è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","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é qui sépare deux amants et que seule la mort réunit.</p>\n<p>À la fin, la belle Panaris est transformée en carafe et le gentil Phlegmon en bouchon de cristal. L’empereur, à qui é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","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éritable ballet, la danse des sept rêves est une chorégraphie dramatique élaboré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","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’adresse consistant à viser une cible avec des fléchettes.</p>\n<p>Pour simuler une partie, faire tirer à chaque participant 5 jets de Lancer/Jeu à zéro et additionner les points de tâ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","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 à deux, comme la valse ou le tango. Plus lente et moins rythmée que les deux premiè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ée par celui ou celle qui a invité l’autre</p>\n<p>4) les deux visages doivent se rapprocher de façon à se toucher par le bout du nez à l’exclusion de toute autre partie du corps.</p>\n<p>Et l’on recommence.</p>\n<p>L’intérêt de cette danse réside dans sa figure libre, sobre ou osée, et sa difficulté dans le nez à nez.</p>\n<p>Il arrive lors de cette figure que, emporté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","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 échecs draconics.</p>\n<p>Plus complexes et soumis à beaucoup plus de variantes que nos échecs, les dragons se jouent sur un plateau de 7 x 7 cases. Chaque joueur possède 14 pièces : le voyageur, le haut-rêvant, la pucelle, le groin, le ménestrel, l’archer, la maison, et 7 arbres.</p>\n<p>Les arbres sont l’équivalent des pions et servent à constituer les forêts. Les joueurs ne jouent pas l’un en face de l’autre, mais côte à côte, avec l’échiquier devant eux. Il y a ainsi le joueur de droite qui plante la forêt dite dextriote, et le joueur de gauche qui plante la forêt sinistrante. Quelle que soit la variante jouée, l’échiquier commence vide, les joueurs introduisant leurs pièces, arbres ou autres, l’un après l’autre.</p>\n<p>Selon les variantes, les pièces ne se déplacent pas de la même façon. Les arbres ne prennent ni ne se déplacent jamais. Ils servent d’obstacle aux lignes de déplacement des autres pièces. Seuls les haut-rêvants peuvent les prendre dans certaines variantes.</p>\n<p>Les maisons, également fixes, ne peuvent être prises que quand elles sont vides. Selon les variantes, elles peuvent contenir de deux à quatre autres pièces (qui coexistent sur la même case), sauf des arbres. Dans la maison les pièces sont protégées, on ne peut les prendre. Une variante permet d’agrandir la maison en sacrifiant un arbre.</p>\n<p>Selon une autre, les archers peuvent augmenter leur nombre de flèches en sacrifiant également un arbre.</p>\n<p>Dans la variante traditionnelle, la plus ancienne, le but du jeu est d’investir la maison adverse. Cela suppose qu’elle soit vide. Il faut préalablement éliminer ou neutraliser les pièces en dehors, jusqu’à obliger les occupants de la maison à sortir (comme aux échecs, on ne peut passer son coup, on doit effectuer un mouvement).</p>\n<p>Dans des variantes plus récentes, plus faciles, le but est de capturer une certaine pièce adverse, généralement le groin ou la pucelle (qui joue l’équivalent du roi de nos échecs). Une variante très populaire oblige que ce soit le groin qui capture la pucelle.</p>\n<p>La durée d’une partie de dragons est en moyenne d’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 d’Amarak","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>Épopée à gros budget et effets spéciaux spectaculaires.</p>\n<p>Amarak, ayant bu une potion de gigantisme, meurt en se cognant la tê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","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ès longtemps suite à un maléfice.</p>\n<p>Les derniers couplets sont malheureusement oublié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é","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ée misérable d’un homme qui avait les oreilles à 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","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’adresse et de volonté, la plumette se joue à deux, chacun chatouillant le visage de l’autre avec une plume. Les visages doivent rester imperturbables.</p>\n<p>Le premier qui trahit un signe quelconque (rire, éternuement, grimace) a perdu.</p>\n<p>Pour simuler une partie, utiliser les règles de combat, chacun à tour de rôle attaquant ou tentant de parer l’adversaire.</p>\n<p>Pour attaquer, utiliser DEXTÉRITÉ/Jeu difficulté libre et pour parer VOLONTÉ/Jeu à la difficulté de l’attaque. Le vainqueur est le premier à réussir une attaque non paré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","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é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","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’est à-dire des petits cailloux, que l’on pose alternativement sur une surface grillée.</p>\n<p>La stratégie est à mi-chemin entre le go et le morpion.</p>\n<p>Très pratiqué, ce jeu peut être facilement improvisé en traçant la grille à la craie sur une table, ou à l’exté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","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","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écitatif, dont la moralité se résume ainsi : puisque tout n’est qu’un rê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","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été de bloutade au chou, cuite dans de la bière.</p>\n<p>Émincer finement le chou et le faire revenir dans l’huile.</p>\n<p>Ajouter la biè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 émincé</li>\n<li>2 doigts d’huile</li>\n<li>1 pinte de bière</li>\n<li>sel</li>\n<li>8 brins d’aromates (béjaune, luciane)</li>\n</ul>\n<p> </p>\n<p>Une variante appelée choucroume liquide utilise le double de biè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","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ée dansée par les villageois, moins lente et moins guindée que cette dernière.</p>\n<p>On danse tantôt en groupe, tantôt par couples, avec changements de partenaire.</p>\n<p>Au moment de la séparation pour reformer le groupe, les partenaires s’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","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ée où un grand nombre de danseurs évoluent en se tenant par la main. Les figures sont libres, l’essentiel é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","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é 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’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","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ès d’un feu.</p>\n<p>Lente, aux mouvements plus suggérés que marqué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","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ère libre, tantôt altière comme la souveraine ou déhanchée comme la callipyge, cette danse utilise un voile comme accessoire (pièce de tissu, châle, écharpe, etc.).</p>\n<p>Son intérêt réside dans les mouvements du voile avec lesquels s’harmonisent ceux de la danseuse.</p>\n<p>Peu pratiqué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","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 à l’eau de rose sur les malheurs d’une jeune haut-rê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","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ès lente, sobre, hiératique, plus caractérisé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","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é libre. Pour parer, l'opposant joue pareillement Force/Jeu à la difficulté de l’attaque.</p>\n<p>Le vainqueur est le premier à réussir une attaque non paré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","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èvre de la couleur en question, qui s’avère finalement être une princesse métamorphosée par un malé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","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égétarienne comprenant des légumes de chacune des trois sortes. Selon les légumes utilisés, la tripotée peut avoir de multiples variantes, la plus courante é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épins</li>\n<li>1/2 livre de racines</li>\n<li>eau</li>\n<li>5 schouillats de farine de blédièze</li>\n<li>3 schouillats de farine de bloute</li>\n<li>4 brins de béjaune</li>\n<li>2 brins de muscaline</li>\n<li>2 brins de pè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, v’là 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ée, comme en témoigne le refrain :</p>\n<blockquote>\n<p>« Tiens, v’là les Groins !</p>\n<p>Ça y’en a eux qui faire du foin !</p>\n<p>Quand y’en a près, y’en a pas loin !</p>\n<p>Tiens, v’là les Groins ! »</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","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ée est une farandole rapide incluant des sauts et des figures quasi acrobatiques, ainsi que des moments rapprochés à deux (comme la peccadille). Elle est évidemment réservée aux bons danseurs, et particulièrement exté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","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 à obtenir un double avec deux dés.</p>\n<p>Si plusieurs joueurs y parviennent, le plus haut gagne ; si aucun n’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 à zéro (ajustés astrologiquement), mais sans compétence, pas même Jeu, et comparer les résultats (échec, réussite normale, significative, etc.) : le meilleur gagne. À égalité de ré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 d’Ostarlath","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ù 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","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 épopée sur un thème identique* : maléfice, métamorphose et superbe vengeance finale.</p>\n<p> </p>\n<p><em>*voir \"La chè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","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épétitifs.</p>\n<blockquote>\n<p>« Une lieue sans cheval, ça use, ça use</p>\n<p>Une lieue sans cheval, ça use les sandales !»</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","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éminine, cette danse utilise un couteau (dague) comme accessoire.</p>\n<p>Elle est imitative d’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":"L’amour 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’une tristesse à 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","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érénade sur la légendaire cité d’Amandjara,</p>\n<p>« Perle du désert bleu, sur qui la lune fait les doux yeux ... »</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","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ée de farine de bloute.</p>\n<p> </p>\n<p><strong>Bloute</strong></p>\n<p>Avec le tomari ou le blédièze, la bloute est à la base de l’alimentation dans un grand nombre d’endroits. C’est un tubercule de forme et de couleur voisins de notre manioc, à la chair gélatineuse et fade. Totalement immangeables telles quelles, les bloutes sont mises à sécher sur des claies, puis broyées en farine. Ce n’est qu’ainsi qu’on peut les consommer. La farine de bloute entre dans la confection des brouets et des ragoûts, notamment de la bloutade. Ainsi cuite, elle ressemble à 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ée en petits morceaux</li>\n<li>2 doigts d’huile</li>\n<li>eau,</li>\n<li>sel</li>\n<li>8 brins d’aromates (bé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","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’accord sur la valeur hiérarchique des symboles et des combinaisons possibles, puis le jeu consiste, à chaque distribution de cartes, à miser selon un système de surenchères jusqu’à ce que les cartes soient dévoilé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 à long terme, mais tout autant de l’empathie pour bluffer lors des surenchères.</p>\n<p>Pour simuler une partie, jouer un jet de CHANCE à zéro (ajusté astrologiquement), suivi d’un jet d’EMPATHIE/Jeu à zéro, et additionner les points de tâ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","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érénade.</p>\n<p>Belle musique, mais paroles d’une rare stupidité :</p>\n<blockquote>\n<p>« Coin-coin, glou-glou, c’est qui ? c’est vous ? »</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":"L’auberge 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âpe à 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 !","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 à boire peu raffiné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","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és, essentiellement basée sur les mouvements du bassin. La callipyge n’est généralement dansé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","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é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","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ée de feuilles de mentharde fraîches, la trompe de padongre doit être cuite au four et arrosée régulièrement de lait. Toute la difficulté ré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","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és de combinaisons se jouant avec trois dés (sorte de 421).</p>\n<p>Pour simuler une partie de triplette, déterminer l’ordre dans lequel jouent les participants. Le premier à jouer peut tenter de un à trois jets de CHANCE à zéro (ajustés astrologiquement comme pour le doublon), et additionner les points de tâche obtenus.</p>\n<p>Attention aux échecs qui donnent des points négatifs ! Il peut être plus judicieux de se contenter d’un seul jet bien réussi.</p>\n<p>Les joueurs suivants, en effet, pourront à leur tour tenter le mê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","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’un voyageur.</p>\n<p>Interminable, cette chanson possède plus de cent couplets.</p>\n<p> </p>\n<p><em>Dé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","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’adresse combinant boules et quilles.</p>\n<p>Chaque joueur dispose de plusieurs quilles, appelées pétasses, et de boules de bois, appelées tronchets. Le jeu connaît de nombreuses variantes, mais le principe général est le même : culbuter les pétasses des adversaires en évitant de se faire troncher les siennes.</p>\n<p>Pour simuler une partie, faire tirer à chaque participant 5 jets de Lancer/Jeu à zéro et additionner les points de tâ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","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é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 «sérieuse».</p>\n<p>Les changements de partenaire s’accompagnent de profondes révé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","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>Épopée pleine de cavalcades, de trahisons, de batailles et de cervelles éclaté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":"L’heure 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è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","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>Épopée pleine de suspense et de terreur, où 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"}}
|
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
MANIFEST-000044
|
|
@@ -1,7 +0,0 @@
|
|||||||
2023/05/29-08:40:34.473425 7fca057fa6c0 Recovering log #42
|
|
||||||
2023/05/29-08:40:34.489629 7fca057fa6c0 Delete type=3 #40
|
|
||||||
2023/05/29-08:40:34.489672 7fca057fa6c0 Delete type=0 #42
|
|
||||||
2023/05/29-08:50:04.169228 7fca04ff96c0 Level-0 table #47: started
|
|
||||||
2023/05/29-08:50:04.169266 7fca04ff96c0 Level-0 table #47: 0 bytes OK
|
|
||||||
2023/05/29-08:50:04.176244 7fca04ff96c0 Delete type=0 #45
|
|
||||||
2023/05/29-08:50:04.189729 7fca04ff96c0 Manual compaction at level-0 from '!items!240HPtZsgZQERFMF' @ 72057594037927935 : 1 .. '!items!zRQ5WnPI483CKm9Q' @ 0 : 0; will stop at (end)
|
|
@@ -1,7 +0,0 @@
|
|||||||
2023/05/29-08:00:37.527199 7fca057fa6c0 Recovering log #38
|
|
||||||
2023/05/29-08:00:37.537455 7fca057fa6c0 Delete type=3 #36
|
|
||||||
2023/05/29-08:00:37.537507 7fca057fa6c0 Delete type=0 #38
|
|
||||||
2023/05/29-08:38:02.086958 7fca04ff96c0 Level-0 table #43: started
|
|
||||||
2023/05/29-08:38:02.086980 7fca04ff96c0 Level-0 table #43: 0 bytes OK
|
|
||||||
2023/05/29-08:38:02.093744 7fca04ff96c0 Delete type=0 #41
|
|
||||||
2023/05/29-08:38:02.107101 7fca04ff96c0 Manual compaction at level-0 from '!items!240HPtZsgZQERFMF' @ 72057594037927935 : 1 .. '!items!zRQ5WnPI483CKm9Q' @ 0 : 0; will stop at (end)
|
|
Binary file not shown.
29
packs/competences-creatures.db
Normal file
29
packs/competences-creatures.db
Normal file
@@ -0,0 +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":{"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":{"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":{"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":{"description":"<p>L'entité 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":{"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":{"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":{"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":{"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":{"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":{"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":{"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":{"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":{"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":{"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":{"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":{"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é 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":{"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":{"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":{"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":{"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":{"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":{"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":{"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":{"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":{"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":{"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":{"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":{"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"}}
|
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
MANIFEST-000044
|
|
@@ -1,7 +0,0 @@
|
|||||||
2023/05/29-08:40:34.473425 7fca06ffd6c0 Recovering log #42
|
|
||||||
2023/05/29-08:40:34.489628 7fca06ffd6c0 Delete type=3 #40
|
|
||||||
2023/05/29-08:40:34.489672 7fca06ffd6c0 Delete type=0 #42
|
|
||||||
2023/05/29-08:50:04.162334 7fca04ff96c0 Level-0 table #47: started
|
|
||||||
2023/05/29-08:50:04.162374 7fca04ff96c0 Level-0 table #47: 0 bytes OK
|
|
||||||
2023/05/29-08:50:04.169093 7fca04ff96c0 Delete type=0 #45
|
|
||||||
2023/05/29-08:50:04.189714 7fca04ff96c0 Manual compaction at level-0 from '!items!0zRL8bOpCXNQnIR4' @ 72057594037927935 : 1 .. '!items!yDHZfK4RmwQW4YaW' @ 0 : 0; will stop at (end)
|
|
@@ -1,7 +0,0 @@
|
|||||||
2023/05/29-08:00:37.527196 7fca05ffb6c0 Recovering log #38
|
|
||||||
2023/05/29-08:00:37.537511 7fca05ffb6c0 Delete type=3 #36
|
|
||||||
2023/05/29-08:00:37.537612 7fca05ffb6c0 Delete type=0 #38
|
|
||||||
2023/05/29-08:38:02.093873 7fca04ff96c0 Level-0 table #43: started
|
|
||||||
2023/05/29-08:38:02.093898 7fca04ff96c0 Level-0 table #43: 0 bytes OK
|
|
||||||
2023/05/29-08:38:02.100659 7fca04ff96c0 Delete type=0 #41
|
|
||||||
2023/05/29-08:38:02.114114 7fca04ff96c0 Manual compaction at level-0 from '!items!0zRL8bOpCXNQnIR4' @ 72057594037927935 : 1 .. '!items!yDHZfK4RmwQW4YaW' @ 0 : 0; will stop at (end)
|
|
Binary file not shown.
15
packs/competences-entites.db
Normal file
15
packs/competences-entites.db
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{"_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","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","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","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","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","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","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","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","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","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","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","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","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","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":{"description":"<p>L'entité 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"}
|
Binary file not shown.
@@ -1 +0,0 @@
|
|||||||
MANIFEST-000044
|
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user