forked from public/foundryvtt-reve-de-dragon
Compare commits
247 Commits
foundryvtt
...
foundryvtt
Author | SHA1 | Date | |
---|---|---|---|
18dfb36a78 | |||
febccd508f | |||
b147f8937b | |||
55a93b317a | |||
02a630152d | |||
ad8ac0de77 | |||
dceb6f026f | |||
ad37ee1b8e | |||
4d40e2fe59 | |||
9d7e57d9fb | |||
717029e572 | |||
d6f8976298 | |||
92e93cbbea | |||
994eaad9a9 | |||
cfed7e2afa | |||
436f9e6fa4 | |||
18a50197cd | |||
b6910612f8 | |||
4ba1ec8a2e | |||
75a0f7c322 | |||
e2a9f55740 | |||
1e0788cde8 | |||
c10195f753 | |||
4d7317b964 | |||
7b1fa009bb | |||
71bb8a14e1 | |||
5444bc7fd8 | |||
debaf1da34 | |||
69e2ab9000 | |||
24218ed062 | |||
da4e18dc3c | |||
154a9b7a37 | |||
fb8189606b | |||
cfbfad27bd | |||
f541849306 | |||
d2d1891838 | |||
5580b6d59c | |||
40c45c30de | |||
1b6c5256cc | |||
c0e6759164 | |||
a096590a07 | |||
9883048fb5 | |||
7bec42c4cf | |||
6708dc0da9 | |||
96c2da0d05 | |||
2b19250e8b | |||
957eabcac7 | |||
285937c201 | |||
93965ce91a | |||
18aba9adff | |||
0a5662ff71 | |||
bf98e4eae2 | |||
e32a1d25f6 | |||
327943c4aa | |||
de56fa909a | |||
2aa62cffe9 | |||
c57f140c54 | |||
9cf14f8b75 | |||
b8e7b21e14 | |||
c1d02d9fda | |||
23af30a538 | |||
4e1b663dec | |||
c9d98c57da | |||
0aef139cf8 | |||
9c85293714 | |||
ab1c04ae17 | |||
a585e0faba | |||
50c730ba72 | |||
928a60f092 | |||
e5c2f52b0e | |||
f9391523f8 | |||
55434762f4 | |||
5e6ffc7846 | |||
3344e20936 | |||
5a66e4e741 | |||
d329724d63 | |||
8a5405c9f5 | |||
ea992aae46 | |||
0bfcfec58f | |||
88e00c59bc | |||
d314dc39a0 | |||
30bb803da2 | |||
dd79e16ea5 | |||
83e2d56fd4 | |||
afc23dfa7b | |||
3e189cbe5f | |||
d0475e8677 | |||
a3694c1673 | |||
9e6d5856b1 | |||
acc880b53f | |||
2598ae3489 | |||
4f5fb63751 | |||
d739a7993a | |||
41335cd433 | |||
e470d76ea0 | |||
ffccc819f1 | |||
45bfc69b39 | |||
79e9358072 | |||
5cab418e62 | |||
7809f7c21a | |||
1bac204071 | |||
3bf5beb67b | |||
ac1da6e979 | |||
67735197bc | |||
f81dc9a5f5 | |||
a563233d6b | |||
0c11013694 | |||
77cf72a752 | |||
42ed5da2d4 | |||
5fd3a43b2a | |||
1bb710ce83 | |||
80579032ea | |||
a810e20eca | |||
c6f0aaeba0 | |||
3c3be7409d | |||
f97345e407 | |||
4cc50fc190 | |||
26967fe1cd | |||
b23dcaace5 | |||
045ee76013 | |||
7fed3844b5 | |||
b5571e6c7a | |||
b5eac8ccfa | |||
673196c644 | |||
9741028914 | |||
10daab2bcd | |||
99d2d38279 | |||
e30825db6b | |||
10ed4d9382 | |||
2ffa0d8dc7 | |||
f229537206 | |||
5c31c7bd7f | |||
4cf428f630 | |||
0c1b70f3f0 | |||
b7ea857bb4 | |||
0238976ce8 | |||
31fd91336a | |||
c70b6c9d5f | |||
07d0d92f57 | |||
a2968697f4 | |||
fb7dbe6ea0 | |||
59641bf5cf | |||
4ee4445836 | |||
1a346a21c3 | |||
c6c0dd43fd | |||
d69a07d4dd | |||
56379a9234 | |||
fbcc167272 | |||
703ab2579d | |||
6b7e881bf2 | |||
dc3ceb1732 | |||
7a0132cf8d | |||
ca1ea5a854 | |||
9bdde92d61 | |||
74313b7fd3 | |||
9a9399a581 | |||
95a7ac73d0 | |||
ab4c118d12 | |||
681358238d | |||
5511acc876 | |||
2e144851d4 | |||
9f24aee1f3 | |||
e605ab405a | |||
86f69566a6 | |||
2561a658f2 | |||
8a1d1fd253 | |||
e42f384d7f | |||
d381191692 | |||
53a7230f1d | |||
4d5651c2d3 | |||
61474172a7 | |||
083806612b | |||
1c417d02a1 | |||
ee9e7d2adb | |||
fa3334273d | |||
05b73a41a5 | |||
842243485a | |||
1e53f2d9e8 | |||
792fcc1b39 | |||
3d914a29c3 | |||
7fe7c1e9bd | |||
d86b81fbbc | |||
22da2807d8 | |||
76e03b07ed | |||
e4098c813b | |||
90aecd6cc0 | |||
254709f55b | |||
064472dc11 | |||
7a67cb7cea | |||
7f051e76be | |||
38db7fb7c8 | |||
c448f32bb8 | |||
e194514965 | |||
a790c36618 | |||
f221bb31eb | |||
bdc2d8db3a | |||
782dc38268 | |||
024e355586 | |||
37704558e0 | |||
d816490839 | |||
a4186da540 | |||
b8b4a1ff14 | |||
8925a4979d | |||
851a208aee | |||
4df04fe06f | |||
f4d074fa31 | |||
f7595a1bfe | |||
86feb12811 | |||
2383094254 | |||
2a72f6ffea | |||
3cc56c615c | |||
948309bb4f | |||
40fdff4057 | |||
c972913a67 | |||
0d5c8e5304 | |||
0aba6d2f0a | |||
df3e181d7f | |||
8877939b9f | |||
7334f2d8e6 | |||
ceff3d1b50 | |||
a4802d1113 | |||
162a6a04b8 | |||
0c36cf3c47 | |||
969e5f6b2d | |||
306ecacc98 | |||
2dc86e6679 | |||
484530d67d | |||
a08890dcb0 | |||
1956fdd755 | |||
651356159a | |||
ca304109d5 | |||
9c0d08cb6f | |||
f9fd8a1e24 | |||
03f84eb3f7 | |||
05e48b61ff | |||
f20788d6d9 | |||
009639dd5f | |||
14542cf7cd | |||
f4f2db68e0 | |||
7e75715d88 | |||
d62d1c45bc | |||
62914c343f | |||
9349e81580 | |||
404539a004 | |||
9eaeceafc4 | |||
1cd3bdef25 | |||
fa356bd7f8 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,5 +1,6 @@
|
|||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
.idea
|
.idea
|
||||||
|
.history
|
||||||
todo.md
|
todo.md
|
||||||
/.vscode
|
/.vscode
|
||||||
/ignored/
|
/ignored/
|
||||||
|
270
changelog.md
270
changelog.md
@@ -1,10 +1,266 @@
|
|||||||
==================================================================
|
---
|
||||||
v0.9.2 - 05/09/2020
|
|
||||||
|
|
||||||
Erreur de calcul sur points de vie
|
# v11.0
|
||||||
Gestion différente des compétences "troncs"
|
|
||||||
|
|
||||||
==================================================================
|
# v10.7 - L'os de Semolosse
|
||||||
v0.9.1 - 03/09/2020
|
|
||||||
|
|
||||||
Initial official release
|
## v10.7.14 - l'expérience de Semolosse
|
||||||
|
- Affichage des personnages accordés sur les fiches des entités
|
||||||
|
- Refonte du journal d'expérience
|
||||||
|
- 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
|
||||||
|
- Fix: en cas d'armure variable, la détérioration diminue le dé d'armure
|
||||||
|
|
||||||
|
## v10.7.12
|
||||||
|
- 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é
|
||||||
|
|
||||||
|
## v10.7.11 - Le Pugilat de Semolosse
|
||||||
|
- Fix sur la projection au sol.
|
||||||
|
|
||||||
|
## v10.7.10 - Le Pugilat de Semolosse
|
||||||
|
- Gestion de l'empoignade
|
||||||
|
- Corrections sur l'initiative
|
||||||
|
- Correction sur l'equipement des vêtements et bijoux
|
||||||
|
|
||||||
|
## v10.7.9 - Le Pugilat de Semolosse
|
||||||
|
|
||||||
|
- Gestion assistée de l'empoignade
|
||||||
|
1. On selectionne sa cible (ie le token qui va être empoigné)
|
||||||
|
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
|
||||||
|
gérés par le MJ au cas ou. Hors combat, penser à les supprimer (ou commencer et
|
||||||
|
arrêter un combat).
|
||||||
|
|
||||||
|
## v10.7.7 - Les bobos de Sémolosse
|
||||||
|
- Mise à jour du texte de l'heure pour les joueurs
|
||||||
|
- L'horloge n'empêche plus de sélectionner les tokens dessous
|
||||||
|
- _Lecture & Détection d'Aura_ sous Hypnos sont des rituels
|
||||||
|
- _Lire les étoiles_ pour les joueurs de nouveau fonctionnel
|
||||||
|
- Ajout de logs pour comprendre un cas d'échec des achatVente
|
||||||
|
|
||||||
|
## v10.7.6 - L'origine des maux de Sémolosse
|
||||||
|
- Calendrier
|
||||||
|
- 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
|
||||||
|
- correction des bonus de cases pour les sorts en Fleuve
|
||||||
|
|
||||||
|
## v10.7.5 - La montre-gousset de Sémolosse
|
||||||
|
- Amélioration de la fenêtre calendrier
|
||||||
|
* plus compacte
|
||||||
|
* horloge analogique (optionnelle)
|
||||||
|
* minimizable (juste la barre de titre)
|
||||||
|
* normalement compatible pop-out
|
||||||
|
|
||||||
|
## v10.7.4 - Les ligatures de Sémolosse
|
||||||
|
- Corrections diverses
|
||||||
|
- 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
|
||||||
|
- Soins
|
||||||
|
- 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
|
||||||
|
- 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
|
||||||
|
|
||||||
|
## v10.7.2 - les maux de dents de Semolosse
|
||||||
|
- correction des récupérations de blessures
|
||||||
|
- la fin de château dormant se passe normalement
|
||||||
|
|
||||||
|
## v10.7.1 - L'os de Semolosse
|
||||||
|
- Fix rapide sur les jets de carac qui n'étaient plus possibles
|
||||||
|
|
||||||
|
## v10.7.0 - L'os de Semolosse
|
||||||
|
- gestion des blessures en items
|
||||||
|
- soins du token ciblé par menu contextuel (comme le combat)
|
||||||
|
- automatisation des soins et de l'affichage de l'avancement des soins
|
||||||
|
- support des changements d'opérants
|
||||||
|
|
||||||
|
---
|
||||||
|
# v10.6 - Les recherches de Pralinor le Goûteux
|
||||||
|
|
||||||
|
## v10.6.25 - Fix sur l'astrologie
|
||||||
|
|
||||||
|
## v10.6.22 - le nuage de lait dans le thé de Pralinor
|
||||||
|
- 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
|
||||||
|
- Astrologie
|
||||||
|
- le thème astral est directement dans la fenêtre d'astrologie
|
||||||
|
- la roue des heures sert d'horloge
|
||||||
|
- sélectionner un personnage ajuste le thème astral pour son heure de naissance
|
||||||
|
- sélectionner le nombre astral d'un jour ajuste le thème astral
|
||||||
|
|
||||||
|
- Fix: les PNJs peuvent de nouveau dormir
|
||||||
|
|
||||||
|
## 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/sante/blessure-mort.webp
Normal file
BIN
icons/sante/blessure-mort.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.1 KiB |
BIN
icons/sante/blessure-soins.webp
Normal file
BIN
icons/sante/blessure-soins.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.5 KiB |
BIN
icons/sante/blessure.webp
Normal file
BIN
icons/sante/blessure.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 6.6 KiB |
BIN
icons/sante/eraflure.webp
Normal file
BIN
icons/sante/eraflure.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
BIN
icons/sante/mort.webp
Normal file
BIN
icons/sante/mort.webp
Normal file
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
98
lang/fr.json
98
lang/fr.json
@@ -1,52 +1,56 @@
|
|||||||
{
|
{
|
||||||
"ACTOR": {
|
"TYPES": {
|
||||||
"TypePersonnage": "Personnage",
|
"Actor": {
|
||||||
"TypeCreature": "Créature",
|
"Personnage": "Personnage",
|
||||||
"TypeEntite": "Entité de cauchemar",
|
"Creature": "Créature",
|
||||||
"TypeCommerce": "Commerce",
|
"Entite": "Entité de cauchemar",
|
||||||
"TypeVehicule": "Véhicule"
|
"Commerce": "Commerce",
|
||||||
|
"Vehicule": "Véhicule"
|
||||||
},
|
},
|
||||||
"ITEM": {
|
"Item": {
|
||||||
"TypeObjet": "Objet",
|
"Arme": "Arme",
|
||||||
"TypeGemme": "Gemme",
|
"Armure": "Armure",
|
||||||
"TypeCompetence": "Compétence",
|
"Blessure": "Blessure",
|
||||||
"TypeCompetencecreature": "Compétence de créature",
|
"Casetmr": "TMR spéciale",
|
||||||
"TypeMaladie": "Maladie",
|
"Chant": "Chant",
|
||||||
"TypePoison": "Poison",
|
"Competence": "Compétence",
|
||||||
"TypeNombreastral": "Nombre astral",
|
"Competencecreature": "Compétence de créature",
|
||||||
"TypeTarot": "Carte de tarot",
|
"Conteneur": "Conteneur",
|
||||||
"TypeCasetmr": "TMR spéciale",
|
"Danse": "Danse",
|
||||||
"TypeRencontre": "Rencontre TMR",
|
"Extraitpoetique": "Extrait poetique",
|
||||||
"TypeMunition": "Munition",
|
"Faune": "Faune",
|
||||||
"TypeMonnaie": "Monnaie",
|
"Gemme": "Gemme",
|
||||||
"TypeHerbe": "Herbe ou plante",
|
"Herbe": "Herbe",
|
||||||
"TypeIngredient": "Ingrédient",
|
"Ingredient": "Ingrédient",
|
||||||
"TypeFaune": "Faune",
|
"Jeu": "Jeu",
|
||||||
"TypeLivre": "Livre",
|
"Livre": "Livre",
|
||||||
"TypePotion": "Potion",
|
"Maladie": "Maladie",
|
||||||
"TypeArme": "Arme",
|
"Meditation": "Méditation",
|
||||||
"TypeArmure": "Armure",
|
"Monnaie": "Monnaie",
|
||||||
"TypeConteneur": "Conteneur",
|
"Munition": "Munition",
|
||||||
"TypeNourritureboisson": "Nourriture & boisson",
|
"Musique": "Musique",
|
||||||
"TypeService": "Service",
|
"Nombreastral": "Nombre astral",
|
||||||
"TypeChant": "Chant",
|
"Nourritureboisson": "Nourriture & boisson",
|
||||||
"TypeDanse": "Danse",
|
"Objet": "Objet",
|
||||||
"TypeMusique": "Musique",
|
"Oeuvre": "Oeuvre",
|
||||||
"TypeOeuvre": "Oeuvre",
|
"Ombre": "Ombre de Thanatos",
|
||||||
"TypeTache": "Tâche",
|
"Plante": "Plante",
|
||||||
"TypeJeu": "Jeu",
|
"Poison": "Poison",
|
||||||
"TypeRecettealchimique": "Recette alchimique",
|
"Possession": "Possession",
|
||||||
"TypeRecettecuisine": "Recette de cuisine",
|
"Potion": "Potion",
|
||||||
"TypeSort": "Sort",
|
"Queue": "Queue de Dragon",
|
||||||
"TypeMeditation": "Méditation",
|
"Recettealchimique": "Recette alchimique",
|
||||||
"TypeSignedraconique": "Signe draconique",
|
"Recettecuisine": "Recette de cuisine",
|
||||||
"TypeQueue": "Queue de Dragon",
|
"Rencontre": "Rencontre TMR",
|
||||||
"TypeOmbre": "Ombre de Thanatos",
|
"Service": "Service",
|
||||||
"TypeSouffle": "Souffle de Dragon",
|
"Signedraconique": "Signe draconique",
|
||||||
"TypeTete": "Tête de Dragon",
|
"Sort": "Sort",
|
||||||
"TypePossession": "Possession",
|
"Sortreserve": "Sort en réserve",
|
||||||
"TypeSortreserve": "Sort en réserve",
|
"Souffle": "Souffle de Dragon",
|
||||||
"TypeExtraitpoetique": "Extrait poetique"
|
"Tache": "Tâche",
|
||||||
|
"Tarot": "Carte de tarot",
|
||||||
|
"Tete": "Tête de Dragon"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"EFFECT": {
|
"EFFECT": {
|
||||||
"StatusStunned": "Sonné",
|
"StatusStunned": "Sonné",
|
||||||
|
@@ -1,4 +1,6 @@
|
|||||||
import { RdDActorSheet } from "./actor-sheet.js";
|
import { RdDActorSheet } from "./actor-sheet.js";
|
||||||
|
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||||
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
|
||||||
export class RdDActorEntiteSheet extends RdDActorSheet {
|
export class RdDActorEntiteSheet extends RdDActorSheet {
|
||||||
|
|
||||||
@@ -13,6 +15,12 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
|
|||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
async getData() {
|
||||||
|
let formData = await super.getData();
|
||||||
|
formData.resonances = this.actor.system.sante.resonnance.actors.map(actorId => game.actors.get(actorId))
|
||||||
|
.map(actor => { return { id: actor.id, name: actor.name, img: actor.img } })
|
||||||
|
return formData
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/** @override */
|
/** @override */
|
||||||
@@ -35,6 +43,23 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
|
|||||||
let compName = event.currentTarget.attributes.compname.value;
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value));
|
this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value));
|
||||||
});
|
});
|
||||||
|
this.html.find('.resonance-delete').click(async event => {
|
||||||
|
const li = RdDSheetUtility.getEventElement(event);
|
||||||
|
const actorId = li.data("actor-id");
|
||||||
|
if (actorId) {
|
||||||
|
const actorResonance = game.actors.get(actorId);
|
||||||
|
RdDUtility.confirmerSuppressionSubacteur(this, actorResonance, li, () => {
|
||||||
|
console.log('Delete : ', actorId);
|
||||||
|
this.removeSubacteur(actorId);
|
||||||
|
RdDUtility.slideOnDelete(this, li);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async removeSubacteur(actorId) {
|
||||||
|
let newResonances = this.actor.system.sante.resonnance.actors.filter(id => id != actorId);
|
||||||
|
await this.actor.update({ 'system.sante.resonnance.actors': newResonances }, { renderSheet: false });
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,8 @@ 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 { RdDBaseActorSheet } from "./actor/base-actor-sheet.js";
|
||||||
import { RdDItem } from "./item.js";
|
import { RdDItem } from "./item.js";
|
||||||
|
import { RdDItemBlessure } from "./item/blessure.js";
|
||||||
|
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/**
|
/**
|
||||||
@@ -66,9 +68,9 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
formData.calc.fatigue = RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max);
|
formData.calc.fatigue = RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max);
|
||||||
|
|
||||||
formData.competences.forEach(item => {
|
formData.competences.forEach(item => {
|
||||||
item.system.isVisible = this.options.recherche
|
item.system.isHidden = this.options.recherche
|
||||||
? RdDItemCompetence.nomContientTexte(item, this.options.recherche.text)
|
? !item.isNomLike(this.options.recherche.text)
|
||||||
: (!this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(item));
|
: (this.options.showCompNiveauBase && RdDItemCompetence.isNiveauBase(item));
|
||||||
RdDItemCompetence.levelUp(item, formData.system.compteurs.experience.value);
|
RdDItemCompetence.levelUp(item, formData.system.compteurs.experience.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -82,6 +84,7 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
RdDItemArme.ajoutCorpsACorps(formData.combat, formData.competences, formData.system.carac);
|
RdDItemArme.ajoutCorpsACorps(formData.combat, formData.competences, formData.system.carac);
|
||||||
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();
|
||||||
|
|
||||||
this.armesList = formData.combat;
|
this.armesList = formData.combat;
|
||||||
|
|
||||||
@@ -111,19 +114,26 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
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"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
||||||
|
|
||||||
// Everything below here is only needed if the sheet is editable
|
// Everything below here is only needed if the sheet is editable
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor));
|
this.html.find('.item-action').click(async event => {
|
||||||
|
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||||
|
item?.actionPrincipale(this.actor, async () => this.render())
|
||||||
|
});
|
||||||
|
|
||||||
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");
|
||||||
if (actorId) {
|
if (actorId) {
|
||||||
const subActor = game.actors.get(actorId);
|
const subActor = game.actors.get(actorId);
|
||||||
RdDUtility.confirmerSuppressionSubacteur(this, subActor, li);
|
RdDUtility.confirmerSuppressionSubacteur(this, subActor, li, () => {
|
||||||
|
console.log('Delete : ', subActor.id);
|
||||||
|
this.actor.removeSubacteur(subActor.id);
|
||||||
|
RdDUtility.slideOnDelete(this, li);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
this.html.find('.experiencelog-delete').click(async event => {
|
this.html.find('.experiencelog-delete').click(async event => {
|
||||||
@@ -136,6 +146,13 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
const key = Number(li.data("key") ?? -1);
|
const key = Number(li.data("key") ?? -1);
|
||||||
await this.actor.deleteExperienceLog(0, key + 1);
|
await this.actor.deleteExperienceLog(0, key + 1);
|
||||||
});
|
});
|
||||||
|
this.html.find("input.derivee-value[name='system.compteurs.stress.value']").change(async event => {
|
||||||
|
this.actor.updateCompteurValue("stress", parseInt(event.target.value));
|
||||||
|
});
|
||||||
|
this.html.find("input.derivee-value[name='system.compteurs.experience.value']").change(async event => {
|
||||||
|
this.actor.updateCompteurValue("experience", parseInt(event.target.value));
|
||||||
|
});
|
||||||
|
|
||||||
this.html.find('.encaisser-direct').click(async event => {
|
this.html.find('.encaisser-direct').click(async event => {
|
||||||
this.actor.encaisser();
|
this.actor.encaisser();
|
||||||
})
|
})
|
||||||
@@ -151,33 +168,31 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
this.html.find('.creer-tache').click(async event => {
|
this.html.find('.creer-tache').click(async event => {
|
||||||
this.createEmptyTache();
|
this.createEmptyTache();
|
||||||
});
|
});
|
||||||
|
this.html.find('.creer-tache-blessure-legere').click(async event => RdDItemBlessure.createTacheSoinBlessure(this.actor, 2));
|
||||||
|
this.html.find('.creer-tache-blessure-grave').click(async event => RdDItemBlessure.createTacheSoinBlessure(this.actor, 4));
|
||||||
|
this.html.find('.creer-tache-blessure-critique').click(async event => RdDItemBlessure.createTacheSoinBlessure(this.actor, 6));
|
||||||
|
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-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();
|
||||||
});
|
});
|
||||||
|
|
||||||
// Blessure control
|
this.html.find('.blessure-premierssoins-done').change(async event => {
|
||||||
this.html.find('.blessure-control').click(async event => {
|
const blessure = this.getBlessure(event);
|
||||||
const tr = this.html.find(event.currentTarget).parents(".item");
|
await blessure?.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } });
|
||||||
let btype = tr.data("blessure-type");
|
|
||||||
let index = tr.data('blessure-index');
|
|
||||||
let active = this.html.find(event.currentTarget).data('blessure-active');
|
|
||||||
//console.log(btype, index, active);
|
|
||||||
await this.actor.manageBlessureFromSheet(btype, index, active);
|
|
||||||
});
|
});
|
||||||
|
this.html.find('.blessure-soinscomplets-done').change(async event => {
|
||||||
// Blessure data
|
const blessure = this.getBlessure(event);
|
||||||
this.html.find('.blessure-soins').change(async event => {
|
await blessure?.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } })
|
||||||
const tr = this.html.find(event.currentTarget).parents(".item");
|
});
|
||||||
let btype = tr.data('blessure-type');
|
this.html.find('.blessure-premierssoins-bonus').change(async event => {
|
||||||
let index = tr.data('blessure-index');
|
const blessure = this.getBlessure(event);
|
||||||
let psoins = tr.find('.blessure-premiers_soins').val();
|
await blessure?.setSoinsBlessure({ premierssoins: { bonus: Number(event.currentTarget.value) } })
|
||||||
let pcomplets = tr.find('.blessure-soins_complets').val();
|
});
|
||||||
let jours = tr.find('.blessure-jours').val();
|
this.html.find('.blessure-soinscomplets-bonus').change(async event => {
|
||||||
let loc = tr.find('.blessure-localisation').val();
|
const blessure = this.getBlessure(event);
|
||||||
let psdone = tr.find('.blessure-psdone:checked').val();
|
await blessure?.setSoinsBlessure({ soinscomplets: { bonus: Number(event.currentTarget.value) } })
|
||||||
let scdone = tr.find('.blessure-scdone:checked').val();
|
|
||||||
console.log(btype, index, psoins, pcomplets, jours, loc, psdone, scdone);
|
|
||||||
await this.actor.setDataBlessureFromSheet(btype, index, psoins, pcomplets, jours, loc, psdone, scdone);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Equip Inventory Item
|
// Equip Inventory Item
|
||||||
@@ -249,9 +264,14 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
|
|
||||||
// Points de reve actuel
|
// Points de reve actuel
|
||||||
this.html.find('.ptreve-actuel a').click(async event => {
|
this.html.find('.ptreve-actuel a').click(async event => {
|
||||||
this.actor.rollCarac('reve-actuel');
|
this.actor.rollCarac('reve-actuel', true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Suite empoignade
|
||||||
|
this.html.find('.empoignade-label a').click(async event => {
|
||||||
|
let emp = RdDSheetUtility.getItem(event, this.actor)
|
||||||
|
RdDEmpoignade.onAttaqueEmpoignadeFromItem(emp)
|
||||||
|
});
|
||||||
// Roll Weapon1
|
// Roll Weapon1
|
||||||
this.html.find('.arme-label a').click(async event => {
|
this.html.find('.arme-label a').click(async event => {
|
||||||
let arme = this._getEventArmeCombat(event);
|
let arme = this._getEventArmeCombat(event);
|
||||||
@@ -345,29 +365,6 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
this.render(true);
|
this.render(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.recherche')
|
|
||||||
.each((index, field) => {
|
|
||||||
if (this.options.recherche) {
|
|
||||||
field.focus();
|
|
||||||
field.setSelectionRange(this.options.recherche.start, this.options.recherche.end);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.keyup(async event => {
|
|
||||||
const nouvelleRecherche = this._optionRecherche(event.currentTarget);
|
|
||||||
if (this.options.recherche?.text != nouvelleRecherche?.text) {
|
|
||||||
this.options.recherche = nouvelleRecherche;
|
|
||||||
if (this.timerRecherche) {
|
|
||||||
clearTimeout(this.timerRecherche);
|
|
||||||
}
|
|
||||||
this.timerRecherche = setTimeout(() => {
|
|
||||||
this.timerRecherche = undefined;
|
|
||||||
this.render(true);
|
|
||||||
}, 500);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.change(async event =>
|
|
||||||
this.options.recherche = this._optionRecherche(event.currentTarget)
|
|
||||||
);
|
|
||||||
this.html.find('.vue-detaillee').click(async event => {
|
this.html.find('.vue-detaillee').click(async event => {
|
||||||
this.options.vueDetaillee = !this.options.vueDetaillee;
|
this.options.vueDetaillee = !this.options.vueDetaillee;
|
||||||
this.render(true);
|
this.render(true);
|
||||||
@@ -440,6 +437,12 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getBlessure(event) {
|
||||||
|
const itemId = this.html.find(event.currentTarget).parents(".item-blessure").data('item-id');
|
||||||
|
const blessure = this.actor.getItem(itemId, 'blessure');
|
||||||
|
return blessure;
|
||||||
|
}
|
||||||
|
|
||||||
isCompetenceAffichable(competence) {
|
isCompetenceAffichable(competence) {
|
||||||
return !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(competence);
|
return !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(competence);
|
||||||
}
|
}
|
||||||
@@ -478,17 +481,6 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
await this.actor.createItem('tache', 'Nouvelle tache');
|
await this.actor.createItem('tache', 'Nouvelle tache');
|
||||||
}
|
}
|
||||||
|
|
||||||
_optionRecherche(target) {
|
|
||||||
if (!target.value?.length) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
text: target.value,
|
|
||||||
start: target.selectionStart,
|
|
||||||
end: target.selectionEnd,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
_getEventArmeCombat(event) {
|
_getEventArmeCombat(event) {
|
||||||
const li = this.html.find(event.currentTarget)?.parents(".item");
|
const li = this.html.find(event.currentTarget)?.parents(".item");
|
||||||
let armeName = li.data("arme-name");
|
let armeName = li.data("arme-name");
|
||||||
|
1340
module/actor.js
1340
module/actor.js
File diff suppressed because it is too large
Load Diff
@@ -31,52 +31,54 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
Monnaie.validerMonnaies(this.actor.itemTypes['monnaie']);
|
Monnaie.validerMonnaies(this.actor.itemTypes['monnaie']);
|
||||||
|
|
||||||
this.actor.recompute();
|
this.actor.recompute();
|
||||||
const userRightLevel = game.user.isGM ? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER : this.actor.getUserLevel(game.user)
|
|
||||||
const options = duplicate(this.options);
|
|
||||||
mergeObject(options, {
|
|
||||||
isGM: game.user.isGM,
|
|
||||||
editable: this.isEditable,
|
|
||||||
cssClass: this.isEditable ? "editable" : "locked",
|
|
||||||
isLimited: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED,
|
|
||||||
isObserver: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER,
|
|
||||||
isOwner: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER,
|
|
||||||
owner: this.actor.isOwner,
|
|
||||||
});
|
|
||||||
|
|
||||||
let formData = {
|
let formData = {
|
||||||
title: this.title,
|
title: this.title,
|
||||||
id: this.actor.id,
|
id: this.actor.id,
|
||||||
type: this.actor.type,
|
type: this.actor.type,
|
||||||
img: this.actor.img,
|
img: this.actor.img,
|
||||||
name: this.actor.name,
|
name: this.actor.name,
|
||||||
system: foundry.utils.deepClone(this.actor.system),
|
system: this.actor.system,
|
||||||
description: await TextEditor.enrichHTML(this.actor.system.description, { async: true }),
|
description: await TextEditor.enrichHTML(this.actor.system.description, { async: true }),
|
||||||
notesmj: await TextEditor.enrichHTML(this.actor.system.notesmj, { async: true }),
|
notesmj: await TextEditor.enrichHTML(this.actor.system.notesmj, { async: true }),
|
||||||
options: options,
|
options: RdDSheetUtility.mergeDocumentRights(this.options, this.actor, this.isEditable)
|
||||||
}
|
}
|
||||||
this.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
|
||||||
|
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
||||||
formData.calc = {
|
formData.calc = {
|
||||||
fortune: this.toSolsDeniers(this.actor.getFortune()),
|
fortune: Monnaie.toSolsDeniers(this.actor.getFortune()),
|
||||||
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
||||||
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.objets);
|
||||||
|
this._appliquerRechercheObjets(formData.objets, formData.conteneurs);
|
||||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||||
|
|
||||||
|
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
||||||
toSolsDeniers(fortune) {
|
_appliquerRechercheObjets(objets, conteneurs) {
|
||||||
return {
|
if (this.options.recherche?.text) {
|
||||||
sols: Math.floor(fortune),
|
const recherche = this.options.recherche;
|
||||||
deniers: Math.round(100 * (fortune - Math.floor(fortune)))
|
const allVisible = objets.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id);
|
||||||
};
|
let addVisible = conteneurs.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id)
|
||||||
|
do {
|
||||||
|
allVisible.push(...addVisible)
|
||||||
|
const parentsIds = conteneurs.filter(it => it.system.contenu.find(id => allVisible.includes(id))).map(it => it.id)
|
||||||
|
addVisible = parentsIds.filter(id => !allVisible.includes(id))
|
||||||
|
}
|
||||||
|
while (addVisible.length > 0)
|
||||||
|
objets.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
||||||
|
conteneurs.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
objets.forEach(it => it.system.isHidden = false)
|
||||||
|
conteneurs.forEach(it => it.system.isHidden = false)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
filterItemsPerTypeForSheet(formData, itemTypes) {
|
static filterItemsPerTypeForSheet(formData, itemTypes) {
|
||||||
|
formData.blessures = Misc.arrayOrEmpty(itemTypes['blessure']);
|
||||||
formData.recettescuisine = Misc.arrayOrEmpty(itemTypes['recettecuisine']);
|
formData.recettescuisine = Misc.arrayOrEmpty(itemTypes['recettecuisine']);
|
||||||
formData.recettesAlchimiques = Misc.arrayOrEmpty(itemTypes['recettealchimique']);
|
formData.recettesAlchimiques = Misc.arrayOrEmpty(itemTypes['recettealchimique']);
|
||||||
formData.maladies = Misc.arrayOrEmpty(itemTypes['maladie']);
|
formData.maladies = Misc.arrayOrEmpty(itemTypes['maladie']);
|
||||||
@@ -110,6 +112,7 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
formData.munitions = Misc.arrayOrEmpty(itemTypes['munition']);
|
formData.munitions = Misc.arrayOrEmpty(itemTypes['munition']);
|
||||||
formData.livres = Misc.arrayOrEmpty(itemTypes['livre']);
|
formData.livres = Misc.arrayOrEmpty(itemTypes['livre']);
|
||||||
formData.potions = Misc.arrayOrEmpty(itemTypes['potion']);
|
formData.potions = Misc.arrayOrEmpty(itemTypes['potion']);
|
||||||
|
formData.plantes = Misc.arrayOrEmpty(itemTypes['plante']);
|
||||||
formData.ingredients = Misc.arrayOrEmpty(itemTypes['ingredient']);
|
formData.ingredients = Misc.arrayOrEmpty(itemTypes['ingredient']);
|
||||||
formData.faunes = Misc.arrayOrEmpty(itemTypes['faune']);
|
formData.faunes = Misc.arrayOrEmpty(itemTypes['faune']);
|
||||||
formData.herbes = Misc.arrayOrEmpty(itemTypes['herbe']);
|
formData.herbes = Misc.arrayOrEmpty(itemTypes['herbe']);
|
||||||
@@ -135,7 +138,13 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
this.html.find('.item-edit').click(async event => this.getItem(event)?.sheet.render(true))
|
this.html.find('.item-edit').click(async event => this.getItem(event)?.sheet.render(true))
|
||||||
this.html.find('.item-montrer').click(async event => this.getItem(event)?.postItemToChat());
|
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('.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;
|
||||||
|
|
||||||
@@ -143,6 +152,8 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
const item = this.getItem(event);
|
const item = this.getItem(event);
|
||||||
RdDSheetUtility.splitItem(item, this.actor);
|
RdDSheetUtility.splitItem(item, this.actor);
|
||||||
});
|
});
|
||||||
|
this.html.find('.item-quantite-plus').click(async event => this.actor.itemQuantiteIncDec(this.getItemId(event), 1));
|
||||||
|
this.html.find('.item-quantite-moins').click(async event => this.actor.itemQuantiteIncDec(this.getItemId(event), -1));
|
||||||
this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, this.getItem(event)));
|
this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, this.getItem(event)));
|
||||||
this.html.find('.item-vendre').click(async event => this.vendre(this.getItem(event)));
|
this.html.find('.item-vendre').click(async event => this.vendre(this.getItem(event)));
|
||||||
|
|
||||||
@@ -152,12 +163,28 @@ 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('.monnaie-plus').click(async event => {
|
}
|
||||||
this.actor.monnaieIncDec(this.getItemId(event), 1);
|
|
||||||
});
|
_rechercherKeyup(event) {
|
||||||
this.html.find('.monnaie-moins').click(async event => {
|
const currentTarget = event.currentTarget;
|
||||||
this.actor.monnaieIncDec(this.getItemId(event), -1);
|
const nouvelleRecherche = this._optionRecherche(currentTarget);
|
||||||
});
|
if (this.options.recherche?.text != nouvelleRecherche?.text) {
|
||||||
|
this.options.recherche = nouvelleRecherche;
|
||||||
|
if (this.timerRecherche) {
|
||||||
|
clearTimeout(this.timerRecherche);
|
||||||
|
}
|
||||||
|
this.timerRecherche = setTimeout(() => {
|
||||||
|
this.timerRecherche = undefined;
|
||||||
|
this.render(true);
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_rechercheSelectArea(field) {
|
||||||
|
if (this.options.recherche) {
|
||||||
|
field.focus();
|
||||||
|
field.setSelectionRange(this.options.recherche.start, this.options.recherche.end);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getItemId(event) {
|
getItemId(event) {
|
||||||
@@ -168,6 +195,16 @@ export class RdDBaseActorSheet extends ActorSheet {
|
|||||||
return RdDSheetUtility.getItem(event, this.actor);
|
return RdDSheetUtility.getItem(event, this.actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_optionRecherche(target) {
|
||||||
|
if (!target.value?.length) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
text: target.value,
|
||||||
|
start: target.selectionStart,
|
||||||
|
end: target.selectionEnd,
|
||||||
|
};
|
||||||
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_getHeaderButtons() {
|
_getHeaderButtons() {
|
||||||
let buttons = super._getHeaderButtons();
|
let buttons = super._getHeaderButtons();
|
||||||
|
@@ -5,6 +5,7 @@ import { Misc } from "../misc.js";
|
|||||||
import { RdDAudio } from "../rdd-audio.js";
|
import { RdDAudio } from "../rdd-audio.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";
|
||||||
|
|
||||||
export class RdDBaseActor extends Actor {
|
export class RdDBaseActor extends Actor {
|
||||||
|
|
||||||
@@ -20,14 +21,16 @@ export class RdDBaseActor extends Actor {
|
|||||||
Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId));
|
Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static onSocketMessage(sockmsg) {
|
static onSocketMessage(sockmsg) {
|
||||||
switch (sockmsg.msg) {
|
switch (sockmsg.msg) {
|
||||||
case "msg_remote_actor_call":
|
case "msg_remote_actor_call":
|
||||||
return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId);
|
return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId);
|
||||||
case "msg_reset_nombre_astral":
|
case "msg_reset_nombre_astral":
|
||||||
console.log("RESET ASTRAL", game.user.character);
|
game.user.character.resetNombresAstraux();
|
||||||
game.user.character.resetNombreAstral();
|
game.system.rdd.calendrier.notifyChangeNombresAstraux();
|
||||||
|
return;
|
||||||
|
case "msg_refresh_nombre_astral":
|
||||||
|
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -106,7 +109,6 @@ export class RdDBaseActor extends Actor {
|
|||||||
isEntite() { return this.type == 'entite'; }
|
isEntite() { return this.type == 'entite'; }
|
||||||
isPersonnage() { return this.type == 'personnage'; }
|
isPersonnage() { return this.type == 'personnage'; }
|
||||||
isVehicule() { return this.type == 'vehicule'; }
|
isVehicule() { return this.type == 'vehicule'; }
|
||||||
|
|
||||||
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)) {
|
||||||
@@ -116,7 +118,7 @@ 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 this.listItems(type)?.filter(filter) ?? []; }
|
filterItems(filter, type = undefined) { return type ? this.itemTypes[type]?.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) });
|
||||||
@@ -147,11 +149,11 @@ export class RdDBaseActor extends Actor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async monnaieIncDec(id, value) {
|
async itemQuantiteIncDec(id, value) {
|
||||||
let monnaie = this.getMonnaie(id);
|
let item = this.getItem(id);
|
||||||
if (monnaie) {
|
if (item && item.isInventaire()) {
|
||||||
const quantite = Math.max(0, monnaie.system.quantite + value);
|
const quantite = Math.max(0, item.system.quantite + value);
|
||||||
await this.updateEmbeddedDocuments('Item', [{ _id: monnaie.id, 'system.quantite': quantite }]);
|
await this.updateEmbeddedDocuments('Item', [{ _id: item.id, 'system.quantite': quantite }]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,13 +243,16 @@ export class RdDBaseActor extends Actor {
|
|||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const cout = Number(achat.prixTotal ?? 0);
|
const cout = Number(achat.prixTotal ?? 0);
|
||||||
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 vente = achat.vente;
|
const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
|
||||||
const quantite = (achat.choix.nombreLots ?? 1) * (vente.tailleLot);
|
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id) ?? achat.vente.item;
|
||||||
const itemVendu = vendeur?.getItem(vente.item._id);
|
if (!itemVendu) {
|
||||||
|
ui.notifications.warn("Erreur sur achat: rien à acheter<br>Si possible, transmettez les logs de la console aux développeurs");
|
||||||
|
console.log('Erreur sur achat: rien à acheter', achat);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (!this.verifierQuantite(vendeur, itemVendu, quantite)) {
|
if (!this.verifierQuantite(vendeur, 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
|
||||||
@@ -259,13 +264,13 @@ 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(vente.item, quantite);
|
const createdItemId = await acheteur.creerQuantiteItem(achat.vente.item, quantite);
|
||||||
await acheteur.consommerNourritureAchetee(achat, vente, createdItemId);
|
await acheteur.consommerNourritureAchetee(achat, achat.vente, createdItemId);
|
||||||
}
|
}
|
||||||
if (cout > 0) {
|
if (cout > 0) {
|
||||||
RdDAudio.PlayContextAudio("argent");
|
RdDAudio.PlayContextAudio("argent");
|
||||||
}
|
}
|
||||||
const chatAchatItem = duplicate(vente);
|
const chatAchatItem = duplicate(achat.vente);
|
||||||
chatAchatItem.quantiteTotal = quantite;
|
chatAchatItem.quantiteTotal = quantite;
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
user: achat.userId,
|
user: achat.userId,
|
||||||
@@ -274,16 +279,16 @@ export class RdDBaseActor extends Actor {
|
|||||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.html', chatAchatItem)
|
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.html', chatAchatItem)
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!vente.quantiteIllimite) {
|
if (!achat.vente.quantiteIllimite) {
|
||||||
if (vente.quantiteNbLots <= achat.choix.nombreLots) {
|
if (achat.vente.quantiteNbLots <= achat.choix.nombreLots) {
|
||||||
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
|
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
|
||||||
}
|
}
|
||||||
else if (achat.chatMessageIdVente) {
|
else if (achat.chatMessageIdVente) {
|
||||||
vente["properties"] = itemVendu.getProprietes();
|
achat.vente.properties = itemVendu.getProprietes();
|
||||||
vente.quantiteNbLots -= achat.choix.nombreLots;
|
achat.vente.quantiteNbLots -= achat.choix.nombreLots;
|
||||||
vente.jsondata = JSON.stringify(vente.item);
|
achat.vente.jsondata = JSON.stringify(achat.vente.item);
|
||||||
const messageVente = game.messages.get(achat.chatMessageIdVente);
|
const messageVente = game.messages.get(achat.chatMessageIdVente);
|
||||||
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente) });
|
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', achat.vente) });
|
||||||
messageVente.render(true);
|
messageVente.render(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,6 +355,14 @@ 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);
|
||||||
|
@@ -22,7 +22,28 @@ export class RdDCommerceSheet extends RdDBaseActorSheet {
|
|||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
get title() {
|
||||||
|
if (this.actor.token && this.actor.token != this.actor.prototypeToken) {
|
||||||
|
return this.actor.token.name;
|
||||||
|
}
|
||||||
|
return super.title
|
||||||
|
}
|
||||||
|
|
||||||
|
async getData() {
|
||||||
|
const formData = await super.getData();
|
||||||
|
if (this.actor.token && this.actor.token != this.actor.prototypeToken) {
|
||||||
|
mergeObject(formData,
|
||||||
|
{
|
||||||
|
title: this.actor.token.name,
|
||||||
|
token: {
|
||||||
|
img: this.actor.token.texture.src
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ overwrite: true });
|
||||||
|
|
||||||
|
}
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/** @override */
|
/** @override */
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
|
39
module/actor/experience-log.js
Normal file
39
module/actor/experience-log.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
|
||||||
|
export const XP_TOPIC = {
|
||||||
|
XP: { code: 'xp', label: 'xp' },
|
||||||
|
XPSORT: { code: 'xpsort', label: 'xp sort' },
|
||||||
|
NIVEAU: { code: 'niveau', label: 'Niveau' },
|
||||||
|
XPCARAC: { code: 'xpcarac', label: 'xp carac' },
|
||||||
|
CARAC: { code: 'carac', label: 'Carac' },
|
||||||
|
STRESS: { code: 'stress', label: 'Stress' },
|
||||||
|
TRANSFORM: { code: 'xps', label: 'Transformé' },
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ExperienceLog {
|
||||||
|
|
||||||
|
static async add(actor, topic, from, to, raison, manuel = false) {
|
||||||
|
if (!actor.hasPlayerOwner || !actor.isPersonnage()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (from == to) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const newXpLog = {
|
||||||
|
mode: topic?.code ?? topic,
|
||||||
|
raison: (manuel ? '(manuel) ' : '') + raison,
|
||||||
|
from: from,
|
||||||
|
to: to,
|
||||||
|
valeur: to - from,
|
||||||
|
daterdd: game.system.rdd.calendrier.dateCourante(),
|
||||||
|
datereel: game.system.rdd.calendrier.dateReel().replace('T', ' ')
|
||||||
|
};
|
||||||
|
console.log('ExperienceLog.add', newXpLog)
|
||||||
|
const newExperienceLog = (actor.system.experiencelog ?? []).concat([newXpLog]);
|
||||||
|
await actor.update({ [`system.experiencelog`]: newExperienceLog });
|
||||||
|
}
|
||||||
|
|
||||||
|
static labelTopic(topic) {
|
||||||
|
const xpt = Object.values(XP_TOPIC).find(it => it.code == topic);
|
||||||
|
return xpt?.label ?? xpt?.code ?? topic;
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,7 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
import { SYSTEM_RDD } from "./constants.js";
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||||
|
|
||||||
|
|
||||||
const LATEST_USED_JOURNAL_ID = "chronologie-dernier-journal";
|
const LATEST_USED_JOURNAL_ID = "chronologie-dernier-journal";
|
||||||
@@ -24,52 +25,68 @@ export class DialogChronologie extends Dialog {
|
|||||||
journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID),
|
journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID),
|
||||||
journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)),
|
journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)),
|
||||||
timestamp: game.system.rdd.calendrier.timestamp,
|
timestamp: game.system.rdd.calendrier.timestamp,
|
||||||
dateReel: DialogChronologie.getCurrentDateTime()
|
dateReel: game.system.rdd.calendrier.dateReel()
|
||||||
};
|
};
|
||||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-chronologie.html", dialogData);
|
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-chronologie.html", dialogData);
|
||||||
const dialog = new DialogChronologie(html);
|
const dialog = new DialogChronologie(html, dialogData);
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(html) {
|
constructor(html, dialogData) {
|
||||||
const options = {
|
const options = {
|
||||||
classes: ["DialogChronologie"],
|
classes: ["DialogChronologie"],
|
||||||
width: 500,
|
width: 500,
|
||||||
height: 'fit-content',
|
height: 'fit-content',
|
||||||
'z-index': 99999
|
'z-index': 99999
|
||||||
};
|
};
|
||||||
|
const timeData = dialogData.timestamp.toCalendrier()
|
||||||
const conf = {
|
const conf = {
|
||||||
title: "Chronologie",
|
title: `Chronologie - ${timeData.jourDuMois} ${timeData.mois.label} - Heure ${timeData.heure.label}`,
|
||||||
content: html,
|
content: html,
|
||||||
buttons: {
|
buttons: {
|
||||||
ajout: { label: "Ajouter", callback: it => this.ajouter() },
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
super(conf, options);
|
super(conf, options);
|
||||||
}
|
this.dialogData = dialogData;
|
||||||
|
|
||||||
static getCurrentDateTime() {
|
|
||||||
return new Date().toLocaleString("sv-SE", {
|
|
||||||
year: "numeric",
|
|
||||||
month: "2-digit",
|
|
||||||
day: "2-digit",
|
|
||||||
hour: "2-digit",
|
|
||||||
minute: "2-digit"
|
|
||||||
}).replace(" ", "T");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
|
||||||
this.html = html;
|
this.html = html;
|
||||||
|
super.activateListeners(html);
|
||||||
|
const journalPrecedent = game.journal.get(this.dialogData.journalId);
|
||||||
|
this.showChronologiePreset(!(journalPrecedent?.canUserModify(game.user)))
|
||||||
|
|
||||||
|
this.html.find("a.chronologie-preset-show").click(event => this.showChronologiePreset(true));
|
||||||
|
this.html.find("a.chronologie-preset-hide").click(event => this.showChronologiePreset(false));
|
||||||
|
this.html.find("button.chronologie-ajouter").click(event => this.ajouter());
|
||||||
|
}
|
||||||
|
|
||||||
|
showChronologiePreset(showPreset) {
|
||||||
|
HtmlUtility.showControlWhen(this.html.find(".chronologie-preset-show"), !showPreset);
|
||||||
|
HtmlUtility.showControlWhen(this.html.find(".chronologie-preset-hide"), showPreset);
|
||||||
|
HtmlUtility.showControlWhen(this.html.find(".chronologie-preset"), showPreset);
|
||||||
}
|
}
|
||||||
|
|
||||||
async ajouter() {
|
async ajouter() {
|
||||||
await this.forceValidation();
|
await this.forceValidation();
|
||||||
const { journalId, journalEntry } = this.findJournal();
|
const { journalId, journalEntry } = this.findJournal();
|
||||||
// ajouter à la page ou créer une page
|
if (journalEntry?.canUserModify(game.user)) {
|
||||||
this.addContentToJournal(journalEntry, await this.prepareChronologieEntry());
|
const journalParameters = this.extractJournalParameters();
|
||||||
|
|
||||||
|
const jour = journalParameters.dateRdD.jour;
|
||||||
|
const mois = journalParameters.dateRdD.mois.label;
|
||||||
|
const annee = journalParameters.dateRdD.annee;
|
||||||
|
const section = `${jour} ${mois} ${annee}`
|
||||||
|
const content = await this.prepareChronologieEntry(journalParameters);
|
||||||
|
// ajouter à la page ou créer une page
|
||||||
|
this.addContentToJournal(journalEntry, section, content);
|
||||||
this.storeLatestUsedJournalEntry(journalId);
|
this.storeLatestUsedJournalEntry(journalId);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const journal = this.html.find("form.rdddialogchrono select[name='journalId']").val();
|
||||||
|
ui.notifications.warn(`Le journal ${journal} n'est pas accessible`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async forceValidation() {
|
async forceValidation() {
|
||||||
@@ -82,8 +99,8 @@ export class DialogChronologie extends Dialog {
|
|||||||
return { journalId, journalEntry };
|
return { journalId, journalEntry };
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepareChronologieEntry() {
|
async prepareChronologieEntry(journalParameters) {
|
||||||
return await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chronologie-entry.html", this.extractJournalParameters());
|
return await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chronologie-entry.html", journalParameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
extractJournalParameters() {
|
extractJournalParameters() {
|
||||||
@@ -97,23 +114,23 @@ 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().replace('T', ' ')
|
dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addContentToJournal(journalEntry, content) {
|
addContentToJournal(journalEntry, section, content) {
|
||||||
let page = journalEntry.pages.find(p => p.type == 'text' && Grammar.equalsInsensitive(p.name, 'Chronologie'));
|
let page = journalEntry.pages.find(p => p.type == 'text' && Grammar.equalsInsensitive(p.name, section));
|
||||||
if (page) {
|
if (page) {
|
||||||
page.update({ 'text.content': content + '\n' + page.text.content });
|
page.update({ 'text.content': page.text.content + '\n' + content });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
journalEntry.createEmbeddedDocuments('JournalEntryPage', [this.newPageChronologie(content)]);
|
journalEntry.createEmbeddedDocuments('JournalEntryPage', [this.newPageChronologie(section, content)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newPageChronologie(content) {
|
newPageChronologie(section, content) {
|
||||||
return new JournalEntryPage({
|
return new JournalEntryPage({
|
||||||
name: 'Chronologie',
|
name: section,
|
||||||
type: 'text',
|
type: 'text',
|
||||||
title: { show: true, level: 1 },
|
title: { show: true, level: 1 },
|
||||||
text: { content: content, format: 1 }
|
text: { content: content, format: 1 }
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
import { RdDItemSigneDraconique } from "./item/item-signedraconique.js";
|
import { RdDItemSigneDraconique } from "./item/signedraconique.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
|
||||||
export class DialogCreateSigneDraconique extends Dialog {
|
export class DialogCreateSigneDraconique extends Dialog {
|
||||||
@@ -98,7 +98,7 @@ export class DialogCreateSigneDraconique extends Dialog {
|
|||||||
|
|
||||||
async setEphemere(ephemere) {
|
async setEphemere(ephemere) {
|
||||||
this.dialogData.signe.system.ephemere = ephemere;
|
this.dialogData.signe.system.ephemere = ephemere;
|
||||||
HtmlUtility._showControlWhen(this.html.find(".signe-system-duree"), ephemere);
|
HtmlUtility.showControlWhen(this.html.find(".signe-system-duree"), ephemere);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSelectActor(event) {
|
async onSelectActor(event) {
|
||||||
|
@@ -5,7 +5,7 @@ import { RdDUtility } from "./rdd-utility.js";
|
|||||||
export class DialogFabriquerPotion extends Dialog {
|
export class DialogFabriquerPotion extends Dialog {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async create(actor, item, dialogConfig) {
|
static async create(actor, item, onActionItem) {
|
||||||
const min = DialogFabriquerPotion.nombreBrinsMinimum(item);
|
const min = DialogFabriquerPotion.nombreBrinsMinimum(item);
|
||||||
if (item.system.quantite < min) {
|
if (item.system.quantite < min) {
|
||||||
ui.notifications.warn(`Vous avez ${item.system.quantite} brins de ${item.name}, il en faut au moins ${min} pour faire une potion!`);
|
ui.notifications.warn(`Vous avez ${item.system.quantite} brins de ${item.name}, il en faut au moins ${min} pour faire une potion!`);
|
||||||
@@ -13,12 +13,10 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
}
|
}
|
||||||
let potionData = DialogFabriquerPotion.prepareData(actor, item);
|
let potionData = DialogFabriquerPotion.prepareData(actor, item);
|
||||||
|
|
||||||
const html = await renderTemplate(dialogConfig.html, potionData);
|
const html = await renderTemplate( 'systems/foundryvtt-reve-de-dragon/templates/dialog-fabriquer-potion-base.html', potionData);
|
||||||
|
|
||||||
let options = { classes: ["dialogfabriquerpotion"], width: 600, height: 160, 'z-index': 99999 };
|
let options = { classes: ["dialogfabriquerpotion"], width: 600, height: 160, 'z-index': 99999 };
|
||||||
mergeObject(options, dialogConfig.options ?? {}, { overwrite: true })
|
new DialogFabriquerPotion(actor, potionData, onActionItem, html, options).render(true);
|
||||||
|
|
||||||
new DialogFabriquerPotion(actor, potionData, html, options).render(true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -34,14 +32,14 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(actor, potionData, html, options) {
|
constructor(actor, potionData, onActionItem, html, options) {
|
||||||
const conf = {
|
const conf = {
|
||||||
title: `Fabriquer une potion de ${potionData.system.categorie}`,
|
title: `Fabriquer une potion de ${potionData.system.categorie}`,
|
||||||
content: html,
|
content: html,
|
||||||
default: 'fabriquer',
|
default: 'fabriquer',
|
||||||
buttons: {
|
buttons: {
|
||||||
'fabriquer': {
|
'fabriquer': {
|
||||||
label: potionData.buttonName, callback: it => this.onFabriquer(html)
|
label: potionData.buttonName, callback: it => this.onFabriquer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -50,6 +48,7 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
|
|
||||||
this.actor = actor;
|
this.actor = actor;
|
||||||
this.potionData = potionData;
|
this.potionData = potionData;
|
||||||
|
this.onActionItem = onActionItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -64,10 +63,11 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onFabriquer(html) {
|
async onFabriquer() {
|
||||||
await this.html.find("[name='nbBrins']").change();
|
await this.html.find("[name='nbBrins']").change();
|
||||||
this.actor.fabriquerPotion(this.potionData);
|
await this.actor.fabriquerPotion(this.potionData);
|
||||||
this.close();
|
this.close();
|
||||||
|
await this.onActionItem()
|
||||||
}
|
}
|
||||||
|
|
||||||
static nombreBrinsMinimum(herbeData) {
|
static nombreBrinsMinimum(herbeData) {
|
||||||
|
@@ -18,7 +18,7 @@ export class DialogItemAchat extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
item: (json ? JSON.parse(json) : undefined),
|
item: JSON.parse(json),
|
||||||
vendeur,
|
vendeur,
|
||||||
acheteur,
|
acheteur,
|
||||||
nbLots: parseInt(chatButton.attributes['data-quantiteNbLots']?.value),
|
nbLots: parseInt(chatButton.attributes['data-quantiteNbLots']?.value),
|
||||||
@@ -34,7 +34,6 @@ export class DialogItemAchat extends Dialog {
|
|||||||
const venteData = {
|
const venteData = {
|
||||||
item,
|
item,
|
||||||
actingUserId: game.user.id,
|
actingUserId: game.user.id,
|
||||||
vendeurId: vendeur?.id,
|
|
||||||
vendeur,
|
vendeur,
|
||||||
acheteur,
|
acheteur,
|
||||||
tailleLot,
|
tailleLot,
|
||||||
|
@@ -40,52 +40,63 @@ export class DialogItemVente extends Dialog {
|
|||||||
|
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
|
||||||
this.html = html;
|
this.html = html;
|
||||||
this.setQuantiteIllimite(this.venteData.quantiteIllimite);
|
|
||||||
this.html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value)));
|
this.html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value)));
|
||||||
this.html.find(".quantiteNbLots").change(event => this.setNbLots(Number(event.currentTarget.value)));
|
this.html.find(".quantiteNbLots").change(event => this.setNbLots(Number(event.currentTarget.value)));
|
||||||
this.html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked));
|
this.html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked));
|
||||||
this.html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value)));
|
this.html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value)));
|
||||||
|
|
||||||
|
this.setQuantiteIllimite(this.venteData.quantiteIllimite);
|
||||||
}
|
}
|
||||||
|
|
||||||
async onProposer(it) {
|
async onProposer(it) {
|
||||||
await this.html.find(".tailleLot").change();
|
this.updateVente(this.getChoixVente());
|
||||||
await this.html.find(".quantiteNbLots").change();
|
|
||||||
await this.html.find(".quantiteIllimite").change();
|
|
||||||
await this.html.find(".prixLot").change();
|
|
||||||
this.callback(this.venteData);
|
this.callback(this.venteData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateVente(update) {
|
||||||
|
mergeObject(this.venteData, update);
|
||||||
|
}
|
||||||
|
|
||||||
|
getChoixVente() {
|
||||||
|
return {
|
||||||
|
quantiteNbLots: Number(this.html.find(".quantiteNbLots").val()),
|
||||||
|
tailleLot: Number(this.html.find(".tailleLot").val()),
|
||||||
|
quantiteIllimite: this.html.find(".quantiteIllimite").is(':checked'),
|
||||||
|
prixLot: Number(this.html.find(".prixLot").val())
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
setPrixLot(prixLot) {
|
setPrixLot(prixLot) {
|
||||||
this.venteData.prixLot = prixLot;
|
this.venteData.prixLot = prixLot;
|
||||||
}
|
}
|
||||||
|
|
||||||
setTailleLot(tailleLot) {
|
setTailleLot(tailleLot) {
|
||||||
// recalculer le prix du lot
|
const maxLots = Math.floor(this.venteData.quantiteMax / tailleLot);
|
||||||
if (tailleLot != this.venteData.tailleLot) {
|
this.updateVente({
|
||||||
this.venteData.prixLot = (tailleLot * this.venteData.prixOrigine).toFixed(2);
|
tailleLot,
|
||||||
|
quantiteNbLots: Math.min(maxLots, this.venteData.quantiteNbLots),
|
||||||
|
quantiteMaxLots: maxLots,
|
||||||
|
prixLot: (tailleLot * this.venteData.prixOrigine).toFixed(2)
|
||||||
|
});
|
||||||
|
|
||||||
this.html.find(".prixLot").val(this.venteData.prixLot);
|
this.html.find(".prixLot").val(this.venteData.prixLot);
|
||||||
}
|
|
||||||
this.venteData.tailleLot = tailleLot;
|
|
||||||
// recalculer le nombre de lots max
|
|
||||||
this.venteData.quantiteMaxLots = Math.floor(this.venteData.quantiteMax / tailleLot);
|
|
||||||
this.venteData.quantiteNbLots = Math.min(this.venteData.quantiteMaxLots, this.venteData.quantiteNbLots);
|
|
||||||
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
|
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
|
||||||
this.html.find(".quantiteNbLots").attr("max", this.venteData.quantiteMaxLots)
|
this.html.find(".quantiteNbLots").attr("max", this.venteData.quantiteMaxLots)
|
||||||
}
|
}
|
||||||
|
|
||||||
setNbLots(nbLots) {
|
setNbLots(nbLots) {
|
||||||
if (this.venteData.isOwned) {
|
this.updateVente({
|
||||||
nbLots = Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots));
|
quantiteNbLots: this.venteData.isOwned ? Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots)) : nbLots
|
||||||
}
|
})
|
||||||
this.venteData.quantiteNbLots = nbLots;
|
|
||||||
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
|
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots);
|
||||||
}
|
}
|
||||||
|
|
||||||
setQuantiteIllimite(checked) {
|
setQuantiteIllimite(checked) {
|
||||||
this.venteData.quantiteIllimite = checked;
|
this.updateVente({ quantiteIllimite: checked })
|
||||||
this.html.find(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles");
|
this.html.find(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles");
|
||||||
HtmlUtility._showControlWhen(this.html.find(".quantiteNbLots"), !this.venteData.quantiteIllimite)
|
HtmlUtility.showControlWhen(this.html.find(".quantiteNbLots"), !this.venteData.quantiteIllimite)
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -1,57 +0,0 @@
|
|||||||
|
|
||||||
export class DialogRepos extends Dialog {
|
|
||||||
|
|
||||||
static async create(actor) {
|
|
||||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-repos.html", actor);
|
|
||||||
const dialog = new DialogRepos(html, actor);
|
|
||||||
dialog.render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(html, actor) {
|
|
||||||
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 400, height: 'fit-content', 'z-index': 99999 };
|
|
||||||
let conf = {
|
|
||||||
title: "Se reposer",
|
|
||||||
content: html,
|
|
||||||
default: "repos",
|
|
||||||
buttons: {
|
|
||||||
"repos": { label: "Se reposer", callback: async it => { this.repos(); } }
|
|
||||||
}
|
|
||||||
};
|
|
||||||
super(conf, options);
|
|
||||||
this.actor = actor;
|
|
||||||
}
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
this.html = html;
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
|
|
||||||
async repos() {
|
|
||||||
await this.html.find("[name='nb-heures']").change();
|
|
||||||
await this.html.find("[name='nb-jours']").change();
|
|
||||||
const selection = await this.html.find("[name='repos']:checked").val();
|
|
||||||
const nbHeures = Number.parseInt(await this.html.find("[name='nb-heures']").val());
|
|
||||||
const nbJours = Number.parseInt(await this.html.find("[name='nb-jours']").val());
|
|
||||||
console.log("ACTOR", this.actor)
|
|
||||||
switch (selection) {
|
|
||||||
case "sieste": {
|
|
||||||
await this.actor.dormir(nbHeures);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case "nuit": {
|
|
||||||
let heuresDormies = await this.actor.dormir(nbHeures);
|
|
||||||
if (heuresDormies == nbHeures) {
|
|
||||||
await this.actor.dormirChateauDormant();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
case "chateau-dormant":
|
|
||||||
await this.actor.dormirChateauDormant();
|
|
||||||
return;
|
|
||||||
case "gris-reve": {
|
|
||||||
await this.actor.grisReve(nbJours);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@@ -23,7 +23,7 @@ export class DialogValidationEncaissement extends Dialog {
|
|||||||
constructor(html, actor, rollData, armure, encaissement, show, onEncaisser) {
|
constructor(html, actor, rollData, armure, encaissement, show, onEncaisser) {
|
||||||
// Common conf
|
// Common conf
|
||||||
let buttons = {
|
let buttons = {
|
||||||
"valider": { label: "Valider", callback: html => this.validerEncaissement() },
|
"valider": { label: "Valider", callback: html => this.onValider() },
|
||||||
"annuler": { label: "Annuler", callback: html => { } },
|
"annuler": { label: "Annuler", callback: html => { } },
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ export class DialogValidationEncaissement extends Dialog {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async validerEncaissement() {
|
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, this.show)
|
||||||
}
|
}
|
||||||
|
@@ -1,223 +1,78 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
import { 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 { CompendiumTableHelpers, CompendiumTable } from "./settings/system-compendiums.js";
|
import { CompendiumTableHelpers, CompendiumTable, SystemCompendiums } from "./settings/system-compendiums.js";
|
||||||
|
|
||||||
const RARETES = [
|
|
||||||
{ name: 'Commune', frequence: 54, min: 27, max: 108 },
|
|
||||||
{ name: 'Frequente', frequence: 18, min: 9, max: 36 },
|
|
||||||
{ name: 'Rare', frequence: 6, min: 3, max: 12 },
|
|
||||||
{ name: 'Rarissime', frequence: 2, min: 1, max: 4 }]
|
|
||||||
const DEFAULT_RARETE = 1;
|
|
||||||
|
|
||||||
const SETTINGS_LISTE_MILIEUX = "liste-milieux";
|
const COMPENDIUMS_RECHERCHE = 'compendiums-recherche';
|
||||||
const MILIEUX = [
|
|
||||||
"Collines",
|
|
||||||
"Cours d'eau",
|
|
||||||
"Déserts",
|
|
||||||
"Forêts",
|
|
||||||
"Marais",
|
|
||||||
"Maritimes",
|
|
||||||
"Montagnes",
|
|
||||||
"Plaines",
|
|
||||||
"Sous-sols"
|
|
||||||
]
|
|
||||||
const ITEM_ENVIRONNEMENT_TYPES = [
|
|
||||||
'herbe', 'ingredient', 'faune'
|
|
||||||
]
|
|
||||||
|
|
||||||
export class Environnement {
|
export class Environnement {
|
||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
game.settings.register(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX, {
|
game.settings.register(SYSTEM_RDD, COMPENDIUMS_RECHERCHE, {
|
||||||
name: "Liste des milieux proposés",
|
name: COMPENDIUMS_RECHERCHE,
|
||||||
hint: "Liste des milieux proposés pour la faune&flore, séparés par des virgules",
|
default: [
|
||||||
|
SystemCompendiums.getCompendium('faune-flore-mineraux'),
|
||||||
|
SystemCompendiums.getCompendium('meditations-et-ecrits'),
|
||||||
|
SystemCompendiums.getCompendium('equipement')
|
||||||
|
],
|
||||||
scope: "world",
|
scope: "world",
|
||||||
config: true,
|
config: false,
|
||||||
default: MILIEUX.reduce(Misc.joining(',')),
|
type: Object
|
||||||
type: String
|
|
||||||
});
|
});
|
||||||
|
|
||||||
game.system.rdd.environnement = new Environnement();
|
game.system.rdd.environnement = new Environnement();
|
||||||
|
Hooks.once('ready', () => game.system.rdd.environnement.onReady());
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.table = new CompendiumTable('faune-flore-mineraux', 'Item', ITEM_ENVIRONNEMENT_TYPES)
|
this.compendiums = [];
|
||||||
|
this.compendiumTables = [];
|
||||||
|
this.mapMilieux = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
static getRarete(name = undefined) {
|
async onReady() {
|
||||||
return RARETES.find(it => it.name == name) ?? RARETES[DEFAULT_RARETE];
|
await this.$prepareCompendiums()
|
||||||
}
|
|
||||||
|
|
||||||
static getFrequenceRarete(rarete, field = undefined) {
|
|
||||||
const selected = this.getRarete(rarete);
|
|
||||||
return selected[field];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async milieux() {
|
async milieux() {
|
||||||
return Object.values(await this.mapMilieux());
|
return Object.values(this.mapMilieux);
|
||||||
}
|
}
|
||||||
|
|
||||||
async mapMilieux() {
|
async saveCompendiums(compendiumIds) {
|
||||||
const compendiumItems = await this.getElements(it => 1, it => ITEM_ENVIRONNEMENT_TYPES.includes(it.type));
|
game.settings.set(SYSTEM_RDD, COMPENDIUMS_RECHERCHE, compendiumIds);
|
||||||
return Misc.indexLowercase(this.getMilieuxSettings().concat(Environnement.listMilieux(compendiumItems)));
|
await this.$prepareCompendiums();
|
||||||
}
|
}
|
||||||
|
|
||||||
static listMilieux(items) {
|
async $prepareCompendiums() {
|
||||||
return Misc.concat(items.map(it => Environnement.$itemToMilieux(it).filter(m => m)));
|
this.compendiums = game.settings.get(SYSTEM_RDD, COMPENDIUMS_RECHERCHE).filter(c => SystemCompendiums.getPack(c));
|
||||||
|
|
||||||
|
this.compendiumTables = this.compendiums.map(it => new CompendiumTable(it, 'Item'));
|
||||||
|
const compendiumItems = await this.getElements(it => 1, it => it.isInventaire());
|
||||||
|
const fromCompendiums = Misc.concat(compendiumItems.map(it => it.getMilieux().filter(m => m)));
|
||||||
|
this.mapMilieux = Misc.indexLowercase(fromCompendiums);
|
||||||
}
|
}
|
||||||
|
|
||||||
async autresMilieux(item) {
|
async autresMilieux(item) {
|
||||||
const mapMilieux = await this.mapMilieux();
|
const milieuxExistants = item.getMilieux().map(it => Grammar.toLowerCaseNoAccent(it));
|
||||||
const milieuxExistants = Environnement.$itemToMilieux(item).map(it => Grammar.toLowerCaseNoAccent(it));
|
return Object.keys(this.mapMilieux)
|
||||||
return Object.keys(mapMilieux)
|
|
||||||
.filter(it => !milieuxExistants.includes(it))
|
.filter(it => !milieuxExistants.includes(it))
|
||||||
.map(it => mapMilieux[it]);
|
.map(it => this.mapMilieux[it]);
|
||||||
}
|
}
|
||||||
|
|
||||||
static $itemToMilieux(item) {
|
|
||||||
return item.system.environnement.map(env => env.milieu);
|
|
||||||
}
|
|
||||||
|
|
||||||
getMilieuxSettings() {
|
|
||||||
return game.settings.get(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX).split(',').map(it => it.trim()).filter(it => it != '');
|
|
||||||
}
|
|
||||||
|
|
||||||
async findEnvironnementsLike(search) {
|
|
||||||
const milieux = await this.mapMilieux();
|
|
||||||
const searchLower = Grammar.toLowerCaseNoAccent(search);
|
|
||||||
const keys = Object.keys(milieux).filter(it => it.includes(searchLower));
|
|
||||||
if (keys.length > 1) {
|
|
||||||
const milieuExact = milieux[searchLower];
|
|
||||||
if (milieuExact) {
|
|
||||||
return [milieuExact];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return keys.map(k => milieux[k]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async searchToChatMessage(milieux, typeName) {
|
|
||||||
const table = await this.buildEnvironnementTable(milieux);
|
|
||||||
await CompendiumTableHelpers.tableToChatMessage(table, 'Item', ITEM_ENVIRONNEMENT_TYPES, typeName);
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
async getRandom(milieux, typeName) {
|
|
||||||
const table = await this.buildEnvironnementTable(milieux);
|
|
||||||
return await CompendiumTableHelpers.getRandom(table, 'Item', ITEM_ENVIRONNEMENT_TYPES, undefined, typeName);
|
|
||||||
}
|
|
||||||
|
|
||||||
async buildEnvironnementTable(milieux) {
|
|
||||||
const filterMilieux = item => item.system?.environnement.filter(env => milieux.includes(env.milieu));
|
|
||||||
const itemRareteEnMilieu = item => {
|
|
||||||
const raretes = filterMilieux(item);
|
|
||||||
const frequenceMax = Math.max(raretes.map(env => env.frequence));
|
|
||||||
return raretes.find(env => env.frequence == frequenceMax);
|
|
||||||
}
|
|
||||||
const itemFrequenceEnMilieu = item => itemRareteEnMilieu(item)?.frequence ?? 0;
|
|
||||||
const isPresentEnMilieu = item => itemFrequenceEnMilieu(item) > 0;
|
|
||||||
return await this.table.buildTable(itemFrequenceEnMilieu, isPresentEnMilieu);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async getElements(itemFrequence, filter) {
|
async getElements(itemFrequence, filter) {
|
||||||
return await this.table.getContent(itemFrequence, filter);
|
const compendiumsElement = await Promise.all(
|
||||||
}
|
this.compendiumTables.map(async compTable => await compTable.getContent(itemFrequence, filter))
|
||||||
|
);
|
||||||
|
const elements = compendiumsElement.reduce((a, b) => a.concat(b));
|
||||||
|
elements.sort(Misc.ascending(it => it.name))
|
||||||
|
return elements;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class EnvironmentSheetHelper {
|
async buildTable(itemFrequence, filter = it => true) {
|
||||||
|
if (!itemFrequence) {
|
||||||
static defaultOptions(defaultOptions) {
|
itemFrequence = it => it.getFrequence()
|
||||||
return mergeObject(defaultOptions, {
|
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }]
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
const elements = await this.getElements(itemFrequence, filter);;
|
||||||
static setPosition(sheet, superPosition) {
|
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
|
||||||
const position = superPosition;
|
|
||||||
const sheetHeader = sheet.element.find(".sheet-header");
|
|
||||||
const sheetBody = sheet.element.find(".sheet-body");
|
|
||||||
sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async getData(sheet, formData) {
|
|
||||||
return mergeObject(formData, {
|
|
||||||
milieux: await game.system.rdd.environnement.autresMilieux(sheet.item)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static activateListeners(sheet) {
|
|
||||||
if (!sheet.options.editable) return;
|
|
||||||
|
|
||||||
sheet.html.find("input.input-selection-milieu").keypress(event => {
|
|
||||||
if (event.keyCode == '13') {
|
|
||||||
EnvironmentSheetHelper.onAddMilieu(sheet, event);
|
|
||||||
}
|
|
||||||
event.stopPropagation();
|
|
||||||
})
|
|
||||||
sheet.html.find("a.milieu-add").click(event => EnvironmentSheetHelper.onAddMilieu(sheet, event));
|
|
||||||
sheet.html.find("div.environnement-milieu a.milieu-delete").click(event => EnvironmentSheetHelper.onDeleteMilieu(sheet, event));
|
|
||||||
sheet.html.find("div.environnement-milieu select.environnement-rarete").change(event => EnvironmentSheetHelper.onChange(sheet, event,
|
|
||||||
updated => EnvironmentSheetHelper.$changeRarete(sheet, event, updated)));
|
|
||||||
sheet.html.find("div.environnement-milieu input[name='environnement-frequence']").change(event => EnvironmentSheetHelper.onChange(sheet, event,
|
|
||||||
updated => EnvironmentSheetHelper.$changeFrequence(sheet, event, updated)));
|
|
||||||
}
|
|
||||||
|
|
||||||
static $changeFrequence(sheet, event, updated) {
|
|
||||||
updated.frequence = Number(sheet.html.find(event.currentTarget).val());
|
|
||||||
}
|
|
||||||
|
|
||||||
static $changeRarete(sheet, event, updated) {
|
|
||||||
const name = sheet.html.find(event.currentTarget).val();
|
|
||||||
const rarete = Environnement.getRarete(name);
|
|
||||||
updated.rarete = rarete.name;
|
|
||||||
updated.frequence = rarete.frequence;
|
|
||||||
// updated.frequence = Math.min(
|
|
||||||
// Math.max(rarete.min, updated.frequence ?? rarete.frequence),
|
|
||||||
// rarete.max);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async onAddMilieu(sheet, event) {
|
|
||||||
const milieu = sheet.html.find('input.input-selection-milieu').val();
|
|
||||||
if (!milieu) {
|
|
||||||
ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${sheet.item.name}`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const list = sheet.item.system.environnement;
|
|
||||||
const exists = list.find(it => it.milieu == milieu);
|
|
||||||
if (exists) {
|
|
||||||
ui.notifications.warn(`${sheet.item.name} a déjà une rareté ${exists.rarete} en ${milieu} (fréquence: ${exists.frequence})`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
const rarete = Environnement.getRarete();
|
|
||||||
const newList = [...list, { milieu, rarete: rarete.name, frequence: rarete.frequence }].sort(Misc.ascending(it => it.milieu))
|
|
||||||
await sheet.item.update({ 'system.environnement': newList })
|
|
||||||
}
|
|
||||||
|
|
||||||
static async onDeleteMilieu(sheet, event) {
|
|
||||||
const milieu = EnvironmentSheetHelper.$getEventMilieu(sheet, event);
|
|
||||||
if (milieu != undefined) {
|
|
||||||
const newList = sheet.item.system.environnement.filter(it => it.milieu != milieu)
|
|
||||||
.sort(Misc.ascending(it => it.milieu));
|
|
||||||
await sheet.item.update({ 'system.environnement': newList });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async onChange(sheet, event, doMutation) {
|
|
||||||
const list = sheet.item.system.environnement;
|
|
||||||
const milieu = EnvironmentSheetHelper.$getEventMilieu(sheet, event);
|
|
||||||
const updated = list.find(it => it.milieu == milieu);
|
|
||||||
if (updated) {
|
|
||||||
doMutation(updated);
|
|
||||||
const newList = [...list.filter(it => it.milieu != milieu), updated]
|
|
||||||
.sort(Misc.ascending(it => it.milieu));
|
|
||||||
await sheet.item.update({ 'system.environnement': newList });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static $getEventMilieu(sheet, event) {
|
|
||||||
return sheet.html.find(event.currentTarget)?.parents("div.environnement-milieu").data("milieu");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,5 +1,5 @@
|
|||||||
export class HtmlUtility{
|
export class HtmlUtility{
|
||||||
static _showControlWhen(jQuerySelector, condition) {
|
static showControlWhen(jQuerySelector, condition) {
|
||||||
if (condition) {
|
if (condition) {
|
||||||
jQuerySelector.show();
|
jQuerySelector.show();
|
||||||
}
|
}
|
||||||
|
@@ -1,5 +1,4 @@
|
|||||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
|
||||||
import { Misc } from "./misc.js";
|
|
||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
import { RdDCombatManager } from "./rdd-combat.js";
|
||||||
|
|
||||||
const nomCategorieParade = {
|
const nomCategorieParade = {
|
||||||
@@ -166,7 +165,7 @@ export class RdDItemArme extends Item {
|
|||||||
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { system: { niveau: -6 } };
|
let corpsACorps = competences.find(it => it.name == 'Corps à corps') ?? { system: { niveau: -6 } };
|
||||||
let init = RdDCombatManager.calculInitiative(corpsACorps.system.niveau, carac['melee'].value);
|
let init = RdDCombatManager.calculInitiative(corpsACorps.system.niveau, carac['melee'].value);
|
||||||
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.system.niveau, initiative: init }));
|
armes.push(RdDItemArme.mainsNues({ niveau: corpsACorps.system.niveau, initiative: init }));
|
||||||
//armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.system.niveau, initiative: init }));
|
armes.push(RdDItemArme.empoignade({ niveau: corpsACorps.system.niveau, initiative: init }));
|
||||||
}
|
}
|
||||||
|
|
||||||
static corpsACorps(mainsNuesActor) {
|
static corpsACorps(mainsNuesActor) {
|
||||||
|
@@ -190,15 +190,6 @@ export class RdDItemCompetence extends Item {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static isVisible(item) {
|
|
||||||
return Number(item.system.niveau) != RdDItemCompetence.getNiveauBase(item.system.categorie);
|
|
||||||
}
|
|
||||||
|
|
||||||
static nomContientTexte(item, texte) {
|
|
||||||
return Grammar.toLowerCaseNoAccent(item.name).includes(Grammar.toLowerCaseNoAccent(texte))
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
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);
|
||||||
@@ -279,7 +270,7 @@ export class RdDItemCompetence extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static triVisible(competences) {
|
static triVisible(competences) {
|
||||||
return competences.filter(it => it.system.isVisible)
|
return competences.filter(it => !it.system.isHidden)
|
||||||
.sort((a, b) => RdDItemCompetence.compare(a, b))
|
.sort((a, b) => RdDItemCompetence.compare(a, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,67 +0,0 @@
|
|||||||
import { EnvironmentSheetHelper } from "./environnement.js";
|
|
||||||
import { RdDItemSheet } from "./item-sheet.js";
|
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
|
||||||
|
|
||||||
export class RdDFauneItemSheet extends RdDItemSheet {
|
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "faune" };
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
setPosition(options = {}) {
|
|
||||||
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
async getData() {
|
|
||||||
const formData = await super.getData();
|
|
||||||
return await EnvironmentSheetHelper.getData(this, formData);
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
if (!this.options.editable) return;
|
|
||||||
|
|
||||||
EnvironmentSheetHelper.activateListeners(this);
|
|
||||||
|
|
||||||
html.find("a.linked-actor-delete").click(event => this.onDeleteLinkedActor());
|
|
||||||
html.find("a.preparer-nourriture").click(event => this.preparerNourriture(event));
|
|
||||||
html.find("a.manger-nourriture").click(event => this.mangerNourriture(event));
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onDropActor(event, dragData) {
|
|
||||||
console.log('faune:dropActor', event, dragData)
|
|
||||||
const linkedActor = fromUuidSync(dragData.uuid);
|
|
||||||
if (linkedActor?.pack) {
|
|
||||||
this.item.update({
|
|
||||||
'system.actor.pack': linkedActor.pack,
|
|
||||||
'system.actor.id': linkedActor._id,
|
|
||||||
'system.actor.name': linkedActor.name
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ui.notifications.warn(`${linkedActor.name} ne provient pas d'un compendium.
|
|
||||||
<br>Choisissez une créature du compendium pour représenter un élément de faune générique`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async onDeleteLinkedActor() {
|
|
||||||
this.item.update({
|
|
||||||
'system.actor.pack': '',
|
|
||||||
'system.actor.id': '',
|
|
||||||
'system.actor.name': ''
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async preparerNourriture(event) {
|
|
||||||
if (this.actor) {
|
|
||||||
await this.actor.preparerNourriture(this.item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async mangerNourriture(event) {
|
|
||||||
if (this.actor) {
|
|
||||||
await this.actor.mangerNourriture(this.item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,25 +0,0 @@
|
|||||||
import { EnvironmentSheetHelper } from "./environnement.js";
|
|
||||||
import { RdDItemSheet } from "./item-sheet.js";
|
|
||||||
|
|
||||||
export class RdDHerbeItemSheet extends RdDItemSheet {
|
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "herbe" };
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
setPosition(options = {}) {
|
|
||||||
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
async getData() {
|
|
||||||
const formData = await super.getData();
|
|
||||||
return await EnvironmentSheetHelper.getData(this, formData);
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
EnvironmentSheetHelper.activateListeners(this);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,25 +0,0 @@
|
|||||||
import { EnvironmentSheetHelper } from "./environnement.js";
|
|
||||||
import { RdDItemSheet } from "./item-sheet.js";
|
|
||||||
|
|
||||||
export class RdDIngredientItemSheet extends RdDItemSheet {
|
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "ingredient" };
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
setPosition(options = {}) {
|
|
||||||
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
|
|
||||||
}
|
|
||||||
|
|
||||||
async getData() {
|
|
||||||
const formData = await super.getData();
|
|
||||||
return await EnvironmentSheetHelper.getData(this, formData);
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
EnvironmentSheetHelper.activateListeners(this);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -17,7 +17,7 @@ const MONNAIE_ARGENT = {
|
|||||||
system: { quantite: 0, cout: 1, encombrement: 0.003, description: "" }
|
system: { quantite: 0, cout: 1, encombrement: 0.003, description: "" }
|
||||||
};
|
};
|
||||||
const MONNAIE_OR = {
|
const MONNAIE_OR = {
|
||||||
name: "Dreagon (or)", type: 'monnaie',
|
name: "Dragon (or)", type: 'monnaie',
|
||||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
|
||||||
system: { quantite: 0, cout: 10, encombrement: 0.004, description: "" }
|
system: { quantite: 0, cout: 10, encombrement: 0.004, description: "" }
|
||||||
};
|
};
|
||||||
@@ -62,6 +62,13 @@ export class Monnaie {
|
|||||||
return deniers;
|
return deniers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static toSolsDeniers(fortune) {
|
||||||
|
return {
|
||||||
|
sols: Math.floor(fortune),
|
||||||
|
deniers: Math.round(100 * (fortune - Math.floor(fortune)))
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
static getFortune(monnaies) {
|
static getFortune(monnaies) {
|
||||||
return (monnaies??[])
|
return (monnaies??[])
|
||||||
.map(m => Number(m.system.cout) * Number(m.system.quantite))
|
.map(m => Number(m.system.cout) * Number(m.system.quantite))
|
||||||
|
@@ -10,7 +10,7 @@ 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 "./rdd-timestamp.js";
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the basic ItemSheet for RdD specific items
|
* Extend the basic ItemSheet for RdD specific items
|
||||||
@@ -86,25 +86,20 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getData() {
|
async getData() {
|
||||||
let formData = {
|
let formData = {
|
||||||
id: this.item.id,
|
|
||||||
title: this.item.name,
|
title: this.item.name,
|
||||||
|
id: this.item.id,
|
||||||
type: this.item.type,
|
type: this.item.type,
|
||||||
img: this.item.img,
|
img: this.item.img,
|
||||||
name: this.item.name,
|
name: this.item.name,
|
||||||
system: this.item.system,
|
system: this.item.system,
|
||||||
isGM: game.user.isGM,
|
|
||||||
actorId: this.actor?.id,
|
actorId: this.actor?.id,
|
||||||
isOwned: this.actor ? true : false,
|
|
||||||
owner: this.item.isOwner,
|
|
||||||
editable: this.isEditable,
|
|
||||||
cssClass: this.isEditable ? "editable" : "locked",
|
|
||||||
isSoins: false,
|
|
||||||
description: await TextEditor.enrichHTML(this.item.system.description, { async: true }),
|
description: await TextEditor.enrichHTML(this.item.system.description, { async: true }),
|
||||||
descriptionmj: await TextEditor.enrichHTML(this.item.system.descriptionmj, { async: true }),
|
descriptionmj: await TextEditor.enrichHTML(this.item.system.descriptionmj, { async: true }),
|
||||||
isComestible: this.item.isComestible()
|
isComestible: this.item.getUtilisationCuisine(),
|
||||||
|
options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable)
|
||||||
}
|
}
|
||||||
|
|
||||||
const competences = await SystemCompendiums.getCompetences(this.actor?.type);
|
const competences = await SystemCompendiums.getCompetences('personnage');
|
||||||
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences()
|
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences()
|
||||||
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
|
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
|
||||||
formData.caracList = duplicate(game.system.model.Actor.personnage.carac)
|
formData.caracList = duplicate(game.system.model.Actor.personnage.carac)
|
||||||
@@ -112,7 +107,7 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
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 => RdDItemCompetence.isCompetenceArme(it))
|
||||||
}
|
}
|
||||||
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));
|
||||||
@@ -138,12 +133,12 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
if (this.item.type == 'potion') {
|
if (this.item.type == 'potion') {
|
||||||
await RdDHerbes.addPotionFormData(formData);
|
await RdDHerbes.addPotionFormData(formData);
|
||||||
}
|
}
|
||||||
if (formData.isOwned && this.item.type == 'herbe' && (formData.system.categorie == 'Soin' || formData.system.categorie == 'Repos')) {
|
if (formData.options.isOwned && this.item.type == 'herbe' && (formData.system.categorie == 'Soin' || formData.system.categorie == 'Repos')) {
|
||||||
formData.isIngredientPotionBase = true;
|
formData.isIngredientPotionBase = true;
|
||||||
}
|
}
|
||||||
if (this.item.type == 'sortreserve') {
|
if (this.item.type == 'sortreserve') {
|
||||||
const sortId = this.item.system.sortid;
|
const sortId = this.item.system.sortid;
|
||||||
formData.sort = formData.isOwned ? this.item.actor.items.get(sortId) : game.items.get(sortId);
|
formData.sort = formData.options.isOwned ? this.item.actor.items.get(sortId) : game.items.get(sortId);
|
||||||
}
|
}
|
||||||
formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true);
|
formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true);
|
||||||
|
|
||||||
@@ -156,8 +151,10 @@ 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') || game.user.isGM || !this.item.isOwned);
|
HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs')
|
||||||
HtmlUtility._showControlWhen(this.html.find(".item-magique"), this.item.isMagique());
|
|| game.user.isGM
|
||||||
|
|| !this.item.isOwned);
|
||||||
|
HtmlUtility.showControlWhen(this.html.find(".item-magique"), this.item.isMagique());
|
||||||
|
|
||||||
// Everything below here is only needed if the sheet is editable
|
// Everything below here is only needed if the sheet is editable
|
||||||
if (!this.options.editable) return;
|
if (!this.options.editable) return;
|
||||||
@@ -191,7 +188,7 @@ 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.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).dialogFabriquerPotion(this.item));
|
||||||
|
|
||||||
this.html.find('.alchimie-tache a').click((event) => {
|
this.html.find('.alchimie-tache a').click((event) => {
|
||||||
@@ -206,12 +203,23 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.item-split').click(async event => RdDSheetUtility.splitItem(RdDSheetUtility.getItem(event, this.actor), this.actor, async () => this.render(true)));
|
if (this.actor) {
|
||||||
|
this.html.find('.item-split').click(async event => RdDSheetUtility.splitItem(RdDSheetUtility.getItem(event, this.actor), this.actor, this.getActionRenderItem()));
|
||||||
this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true));
|
this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true));
|
||||||
this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, RdDSheetUtility.getItem(event, this.actor)));
|
this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, RdDSheetUtility.getItem(event, this.actor)));
|
||||||
this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente());
|
this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente());
|
||||||
this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItemToChat());
|
this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItemToChat());
|
||||||
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor, async () => this.render(true)));
|
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor, this.getActionRenderItem()));
|
||||||
|
|
||||||
|
this.html.find('.item-quantite-plus').click(async event => {
|
||||||
|
await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), 1)
|
||||||
|
this.render();
|
||||||
|
});
|
||||||
|
this.html.find('.item-quantite-moins').click(async event => {
|
||||||
|
await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), -1)
|
||||||
|
this.render();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: duplicate(timestamp) })
|
const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: duplicate(timestamp) })
|
||||||
|
|
||||||
@@ -219,6 +227,16 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp);
|
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getActionRenderItem() {
|
||||||
|
return async () => {
|
||||||
|
let item = this.item;
|
||||||
|
while (item) {
|
||||||
|
await item.sheet?.render()
|
||||||
|
item = this.actor.getContenant(item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
_getEventActor(event) {
|
_getEventActor(event) {
|
||||||
let actorId = event.currentTarget.attributes['data-actor-id'].value;
|
let actorId = event.currentTarget.attributes['data-actor-id'].value;
|
||||||
let actor = game.actors.get(actorId);
|
let actor = game.actors.get(actorId);
|
||||||
@@ -242,9 +260,8 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
_updateObject(event, formData) {
|
_updateObject(event, formData) {
|
||||||
if (this.item.type == 'sort') {
|
if (this.item.type == 'sort') {
|
||||||
// Données de bonus de cases ?
|
// Données de bonus de cases ?
|
||||||
formData['system.bonuscase'] = RdDItemSort.buildBonusCaseStringFromFormData(formData.bonusValue, formData.caseValue);
|
formData['system.bonuscase'] = RdDItemSort.buildBonuscaseFromArrays(formData.bonusValue, formData.caseValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.item.update(formData);
|
return this.item.update(formData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
/* -------------------------------------------- */
|
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
|
||||||
@@ -31,22 +30,14 @@ export class RdDItemSort extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static buildBonusCaseList( caseBonusString, newCase ) {
|
static buildBonusCaseList(bonuscase, newCase) {
|
||||||
if (caseBonusString == undefined) {
|
const list = RdDItemSort._bonuscaseStringToList(bonuscase)
|
||||||
return [];
|
if (newCase) {
|
||||||
|
return list.concat({ case: "Nouvelle", bonus: 0 });
|
||||||
}
|
}
|
||||||
let bonusCaseList = [];
|
return list;
|
||||||
let bonusCaseArray = caseBonusString == undefined ? [] : caseBonusString.split(',');
|
|
||||||
for( let bonusCase of bonusCaseArray) {
|
|
||||||
let bonusSplit = bonusCase.split(':');
|
|
||||||
bonusCaseList.push( { case: bonusSplit[0], bonus: bonusSplit[1] } );
|
|
||||||
}
|
|
||||||
if ( newCase )
|
|
||||||
bonusCaseList.push( {case: "Nouvelle", bonus: 0} );
|
|
||||||
return bonusCaseList;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/**
|
/**
|
||||||
* Retourne une liste de bonus/case pour un item-sheet
|
* Retourne une liste de bonus/case pour un item-sheet
|
||||||
* @param {} item
|
* @param {} item
|
||||||
@@ -54,7 +45,7 @@ export class RdDItemSort extends Item {
|
|||||||
static getBonusCaseList(item, newCase = false) {
|
static getBonusCaseList(item, newCase = false) {
|
||||||
// Gestion spéciale case bonus
|
// Gestion spéciale case bonus
|
||||||
if (item.type == 'sort') {
|
if (item.type == 'sort') {
|
||||||
return this.buildBonusCaseList(item.system.bonuscase, newCase );
|
return RdDItemSort.buildBonusCaseList(item.system.bonuscase, newCase);
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -63,56 +54,61 @@ export class RdDItemSort extends Item {
|
|||||||
/** Met à jour les données de formulaire
|
/** Met à jour les données de formulaire
|
||||||
* si static des bonus de cases sont présents
|
* si static des bonus de cases sont présents
|
||||||
* */
|
* */
|
||||||
static buildBonusCaseStringFromFormData( bonuses, cases ) {
|
static buildBonuscaseFromArrays(bonuses, coords) {
|
||||||
if (bonuses) {
|
if (bonuses) {
|
||||||
let list = [];
|
const list = [];
|
||||||
let caseCheck = {};
|
const caseCheck = {};
|
||||||
for (let i=0; i<bonuses.length; i++) {
|
for (let i = 0; i < bonuses.length && i < coords.length; i++) {
|
||||||
let coord = cases[i]?.toUpperCase() || 'A1';
|
const coord = coords[i] == 'Fleuve' ? 'Fleuve' : (coords[i]?.toUpperCase() ?? 'A1');
|
||||||
let bonus = bonuses[i] || 0;
|
const bonus = bonuses[i] || 0;
|
||||||
if (TMRUtility.verifyTMRCoord(coord) && bonus > 0 && caseCheck[coord] == undefined) {
|
if (TMRUtility.verifyTMRCoord(coord) && bonus > 0 && caseCheck[coord] == undefined) {
|
||||||
caseCheck[coord] = bonus;
|
caseCheck[coord] = bonus;
|
||||||
list.push( coord+":"+bonus );
|
list.push({ case: coord, bonus: bonus });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list.toString();
|
return RdDItemSort._bonuscaseListToString(list);
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static incrementBonusCase(actor, sort, coord) {
|
static incrementBonusCase(actor, sort, coord) {
|
||||||
let bonusCaseList = this.buildBonusCaseList(sort.system.bonuscase, false);
|
if (TMRUtility.getTMR(coord).type == "fleuve") {
|
||||||
//console.log("ITEMSORT", sort, bonusCaseList);
|
coord = 'Fleuve';
|
||||||
|
}
|
||||||
|
const list = RdDItemSort.buildBonusCaseList(sort.system.bonuscase, false);
|
||||||
|
const bonus = Number(list.find(it => it.case == coord)?.bonus ?? 0);
|
||||||
|
const modified = { case: coord, bonus: bonus + 1 };
|
||||||
|
|
||||||
let found = false;
|
const bonuscase = RdDItemSort._bonuscaseListToString(
|
||||||
let StringList = [];
|
list.filter(it => it.case != coord).concat(modified)
|
||||||
for( let bc of bonusCaseList) {
|
);
|
||||||
if (bc.case == coord) { // Case existante
|
|
||||||
found = true;
|
|
||||||
bc.bonus = Number(bc.bonus) + 1;
|
|
||||||
}
|
|
||||||
StringList.push( bc.case+':'+bc.bonus );
|
|
||||||
}
|
|
||||||
if ( !found) { //Nouvelle case, bonus de 1
|
|
||||||
StringList.push(coord+':1');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sauvegarde/update
|
// Sauvegarde/update
|
||||||
let bonuscase = StringList.toString();
|
|
||||||
//console.log("Bonus cae :", bonuscase);
|
|
||||||
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]);
|
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getCaseBonus(sort, coord) {
|
static getCaseBonus(sort, coord) {
|
||||||
let bonusCaseList = this.buildBonusCaseList(sort.system.bonuscase, false);
|
const isFleuve = TMRUtility.getTMR(coord).type == "fleuve";
|
||||||
for( let bc of bonusCaseList) {
|
|
||||||
if (bc.case == coord) { // Case existante
|
let bc = RdDItemSort.buildBonusCaseList(sort.system.bonuscase, false)
|
||||||
return Number(bc.bonus);
|
.filter(it => it.case == coord || (isFleuve && it.case == 'Fleuve'))
|
||||||
|
.find(it => true)
|
||||||
|
return Number(bc?.bonus ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _bonuscaseListToString(list) {
|
||||||
|
return list.map(it => `${it.case}:${it.bonus}`)
|
||||||
|
.sort(Misc.ascending())
|
||||||
|
.join(',');
|
||||||
}
|
}
|
||||||
return 0;
|
static _bonuscaseStringToList(bonuscase) {
|
||||||
|
return (bonuscase ?? '').split(',').map(it => {
|
||||||
|
const b = it.split(':');
|
||||||
|
return { case: b[0], bonus: b[1] };
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -1,4 +0,0 @@
|
|||||||
export class RdDItemTache extends Item {
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
246
module/item.js
246
module/item.js
@@ -2,36 +2,77 @@ import { DialogItemVente } from "./dialog-item-vente.js";
|
|||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDHerbes } from "./rdd-herbes.js";
|
import { RdDHerbes } from "./rdd-herbes.js";
|
||||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
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";
|
||||||
|
|
||||||
|
export const TYPES = {
|
||||||
|
competence: 'competence',
|
||||||
|
competencecreature: 'competencecreature',
|
||||||
|
arme: 'arme',
|
||||||
|
armure: 'armure',
|
||||||
|
conteneur: 'conteneur',
|
||||||
|
sort: 'sort',
|
||||||
|
herbe: 'herbe',
|
||||||
|
faune: 'faune',
|
||||||
|
ingredient: 'ingredient',
|
||||||
|
livre: 'livre',
|
||||||
|
potion: 'potion',
|
||||||
|
rencontre: 'rencontre',
|
||||||
|
queue: 'queue',
|
||||||
|
ombre: 'ombre',
|
||||||
|
souffle: 'souffle',
|
||||||
|
tete: 'tete',
|
||||||
|
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',
|
||||||
|
gemme: 'gemme',
|
||||||
|
possession: 'possession',
|
||||||
|
sortreserve: 'sortreserve',
|
||||||
|
extraitpoetique: 'extraitpoetique',
|
||||||
|
tarot: 'tarot',
|
||||||
|
empoignade: 'empoignade'
|
||||||
|
}
|
||||||
const typesInventaireMateriel = [
|
const typesInventaireMateriel = [
|
||||||
"arme",
|
TYPES.arme,
|
||||||
"armure",
|
TYPES.armure,
|
||||||
"conteneur",
|
TYPES.conteneur,
|
||||||
"faune",
|
TYPES.faune,
|
||||||
"gemme",
|
TYPES.gemme,
|
||||||
"herbe",
|
TYPES.herbe,
|
||||||
"ingredient",
|
TYPES.plante,
|
||||||
"livre",
|
TYPES.ingredient,
|
||||||
"monnaie",
|
TYPES.livre,
|
||||||
"munition",
|
TYPES.monnaie,
|
||||||
"nourritureboisson",
|
TYPES.munition,
|
||||||
"objet",
|
TYPES.nourritureboisson,
|
||||||
"potion",
|
TYPES.objet,
|
||||||
|
TYPES.potion,
|
||||||
]
|
]
|
||||||
const typesInventaire = {
|
const typesInventaire = {
|
||||||
materiel: typesInventaireMateriel,
|
materiel: typesInventaireMateriel,
|
||||||
all: ['service'].concat(typesInventaireMateriel),
|
all: ['service'].concat(typesInventaireMateriel),
|
||||||
}
|
}
|
||||||
|
|
||||||
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]
|
const typesObjetsOeuvres = [TYPES.oeuvre, TYPES.recettecuisine, TYPES.musique, TYPES.chant, TYPES.danse, TYPES.jeu]
|
||||||
const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve", "rencontre"]
|
const typesObjetsDraconiques = [TYPES.queue, TYPES.ombre, TYPES.souffle, TYPES.tete, TYPES.signedraconique, TYPES.sortreserve, TYPES.rencontre]
|
||||||
const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"]
|
const typesObjetsConnaissance = [TYPES.meditation, TYPES.recettealchimique, TYPES.sort]
|
||||||
const typesObjetsEffet = ["possession", "poison", "maladie"]
|
const typesObjetsEffet = [TYPES.possession, TYPES.poison, TYPES.maladie, TYPES.blessure]
|
||||||
const typesObjetsCompetence = ["competence", "competencecreature"]
|
const typesObjetsCompetence = [TYPES.competence, TYPES.competencecreature]
|
||||||
const typesObjetsTemporels = ["poison", "maladie", "queue", "ombre", "souffle", "signedraconique", "rencontre"]
|
const typesObjetsTemporels = [TYPES.blessure, TYPES.poison, TYPES.maladie, TYPES.queue, TYPES.ombre, TYPES.souffle, TYPES.signedraconique, TYPES.rencontre]
|
||||||
|
const typesObjetsEquipable = [TYPES.arme, TYPES.armure, TYPES.objet];
|
||||||
|
const typesEnvironnement = typesInventaireMateriel;
|
||||||
const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
|
const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
|
||||||
const encPepin = 0.0007; /* un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc
|
const encPepin = 0.0007; /* un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc
|
||||||
densité 3.5 (~2.3 à 4, parfois plus) -- https://www.juwelo.fr/guide-des-pierres/faits-et-chiffres/
|
densité 3.5 (~2.3 à 4, parfois plus) -- https://www.juwelo.fr/guide-des-pierres/faits-et-chiffres/
|
||||||
@@ -72,11 +113,16 @@ export const defaultItemImg = {
|
|||||||
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
|
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
|
||||||
extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp",
|
extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp",
|
||||||
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
|
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
|
||||||
|
empoignade: "systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp"
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDItem extends Item {
|
export class RdDItem extends Item {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
static getDefaultImg(itemType) {
|
static getDefaultImg(itemType) {
|
||||||
return game.system.rdd.itemClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
|
return game.system.rdd.itemClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
|
||||||
}
|
}
|
||||||
@@ -84,12 +130,12 @@ export class RdDItem extends Item {
|
|||||||
static isFieldInventaireModifiable(type, field) {
|
static isFieldInventaireModifiable(type, field) {
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case 'quantite':
|
case 'quantite':
|
||||||
if (['conteneur'].includes(type)) {
|
if ([TYPES.conteneur].includes(type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'cout':
|
case 'cout':
|
||||||
if (['monnaie'].includes(type)) {
|
if ([TYPES.monnaie].includes(type)) {
|
||||||
return game.user.isGM;
|
return game.user.isGM;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -107,6 +153,12 @@ export class RdDItem extends Item {
|
|||||||
static getItemTypesInventaire(mode = 'materiel') {
|
static getItemTypesInventaire(mode = 'materiel') {
|
||||||
return typesInventaire[mode ?? 'materiel']
|
return typesInventaire[mode ?? 'materiel']
|
||||||
}
|
}
|
||||||
|
static getItemTypesDraconiques() {
|
||||||
|
return typesObjetsDraconiques;
|
||||||
|
}
|
||||||
|
static getItemTypesEnvironnement() {
|
||||||
|
return typesEnvironnement;
|
||||||
|
}
|
||||||
|
|
||||||
static getTypesOeuvres() {
|
static getTypesOeuvres() {
|
||||||
return typesObjetsOeuvres
|
return typesObjetsOeuvres
|
||||||
@@ -129,43 +181,78 @@ export class RdDItem extends Item {
|
|||||||
super(docData, context);
|
super(docData, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
static get defaultIcon() {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
getUniteQuantite() {
|
getUniteQuantite() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case "monnaie": return "(Pièces)"
|
case TYPES.monnaie: return "(Pièces)"
|
||||||
case "herbe":
|
case TYPES.herbe:
|
||||||
switch (this.system.categorie) {
|
switch (this.system.categorie) {
|
||||||
case 'Alchimie': case 'Repos': case 'Soin':
|
case 'Alchimie': case 'Repos': case 'Soin':
|
||||||
return "(Brins)"
|
return "(Brins)"
|
||||||
case 'Cuisine': return '';
|
case 'Cuisine': return '';
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
case "ingredient": return "(Pépins ou Brins)"
|
case TYPES.ingredient: return "(Pépins ou Brins)"
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
isCompetencePersonnage() { return this.type == 'competence' }
|
isEquipable() {
|
||||||
isCompetenceCreature() { return this.type == 'competencecreature' }
|
return typesObjetsEquipable.includes(this.type)
|
||||||
isConteneur() { return this.type == 'conteneur'; }
|
}
|
||||||
isMonnaie() { return this.type == 'monnaie'; }
|
|
||||||
isPotion() { return this.type == 'potion'; }
|
isCompetencePersonnage() { return this.type == TYPES.competence }
|
||||||
isNourritureBoisson() { return this.type == 'nourritureboisson'; }
|
isCompetenceCreature() { return this.type == TYPES.competencecreature }
|
||||||
isService() { return this.type == 'service'; }
|
isConteneur() { return this.type == TYPES.conteneur; }
|
||||||
|
isMonnaie() { return this.type == TYPES.monnaie; }
|
||||||
|
isPotion() { return this.type == TYPES.potion; }
|
||||||
|
isNourritureBoisson() { return this.type == TYPES.nourritureboisson; }
|
||||||
|
isService() { return this.type == TYPES.service; }
|
||||||
|
|
||||||
isCompetence() { return typesObjetsCompetence.includes(this.type) }
|
isCompetence() { return typesObjetsCompetence.includes(this.type) }
|
||||||
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 typesObjetsDraconiques.includes(this.type) }
|
isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
|
||||||
|
isQueueDragon() { return [TYPES.queue, TYPES.ombre].includes(this.type) }
|
||||||
isEffet() { return typesObjetsEffet.includes(this.type) }
|
isEffet() { return typesObjetsEffet.includes(this.type) }
|
||||||
isConnaissance() { return typesObjetsConnaissance.includes(this.type) }
|
isConnaissance() { return typesObjetsConnaissance.includes(this.type) }
|
||||||
|
|
||||||
isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); }
|
isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); }
|
||||||
|
isBoisson() { return this.isNourritureBoisson() && this.system.boisson; }
|
||||||
isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; }
|
isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; }
|
||||||
isHerbeAPotion() { return this.type == 'herbe' && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
|
isHerbeAPotion() { return this.type == TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
|
||||||
|
isBlessure() { return this.type == TYPES.blessure }
|
||||||
|
|
||||||
|
isPresentDansMilieux(milieux) {
|
||||||
|
return this.getEnvironnements(milieux).length > 0
|
||||||
|
}
|
||||||
|
|
||||||
|
getEnvironnements(milieux = undefined) {
|
||||||
|
const environnements = this.isInventaire() ? this.system.environnement : undefined;
|
||||||
|
if (milieux == undefined || !environnements) {
|
||||||
|
return environnements ?? [];
|
||||||
|
}
|
||||||
|
return environnements.filter(env => milieux.includes(env.milieu))
|
||||||
|
}
|
||||||
|
|
||||||
|
getMilieux() {
|
||||||
|
return this.getEnvironnements().map(env => env.milieu);
|
||||||
|
}
|
||||||
|
|
||||||
|
getRaretes(milieux = undefined) {
|
||||||
|
if (this.isInventaire()) {
|
||||||
|
const raretes = this.getEnvironnements(milieux).map(env => RdDRaretes.byCode(env.rarete));
|
||||||
|
if (milieux == undefined && raretes.length == 0) {
|
||||||
|
return [RdDRaretes.rareteFrequente()];
|
||||||
|
}
|
||||||
|
return raretes;
|
||||||
|
}
|
||||||
|
return [RdDRaretes.rareteEgale()];
|
||||||
|
}
|
||||||
|
|
||||||
|
getFrequence(milieux = undefined) {
|
||||||
|
const frequences = this.getEnvironnements(milieux).map(it => it.frequence);
|
||||||
|
return frequences.length == 0 ? 0 : Math.max(...frequences);
|
||||||
|
}
|
||||||
|
|
||||||
getItemGroup() {
|
getItemGroup() {
|
||||||
if (this.isInventaire()) return "equipement";
|
if (this.isInventaire()) return "equipement";
|
||||||
@@ -216,19 +303,42 @@ export class RdDItem extends Item {
|
|||||||
await this.actor?.deleteEmbeddedDocuments('Item', [this.id]);
|
await this.actor?.deleteEmbeddedDocuments('Item', [this.id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
isComestible() {
|
getUtilisation() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case 'nourritureboisson': return 'pret';
|
case TYPES.potion:
|
||||||
case 'herbe':
|
switch (this.system.categorie) {
|
||||||
return this.system.categorie == 'Cuisine' && this.system.sust > 0 ? 'brut' : '';
|
case 'Alchimie': case 'AlchimieEnchante': case 'AlchimieAutre': return 'alchimie'
|
||||||
case 'faune':
|
case 'Cuisine': return 'cuisine'
|
||||||
return this.system.sust > 0 ? 'brut' : '';
|
case 'Remede': case 'Repos': case 'ReposEnchante': case 'Soin': case 'SoinEnchante': return 'soins'
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
case TYPES.nourritureboisson: return 'cuisine';
|
||||||
|
case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante:
|
||||||
|
switch (this.system.categorie) {
|
||||||
|
case 'Cuisine': return 'cuisine';
|
||||||
|
case 'Toxique': case 'Poison': return 'poison';
|
||||||
|
case 'Alchimie': return 'alchimie'
|
||||||
|
case 'Soin': case 'Repos': return 'soins'
|
||||||
|
}
|
||||||
|
return this.system.sust > 0 ? 'cuisine' : '';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
getUtilisationCuisine() {
|
||||||
|
if (this.getUtilisation() == 'cuisine') {
|
||||||
|
switch (this.type) {
|
||||||
|
case TYPES.nourritureboisson:
|
||||||
|
return 'pret';
|
||||||
|
case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante:
|
||||||
|
return 'brut';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
isCristalAlchimique() {
|
isCristalAlchimique() {
|
||||||
return this.type == 'objet' && Grammar.toLowerCaseNoAccent(this.name) == 'cristal alchimique' && this.system.quantite > 0;
|
return this.type == TYPES.objet && Grammar.includesLowerCaseNoAccent(this.name, 'cristal alchimique') && this.system.quantite > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isMagique() {
|
isMagique() {
|
||||||
@@ -239,6 +349,13 @@ export class RdDItem extends Item {
|
|||||||
return this.parent?.type == 'commerce';
|
return this.parent?.type == 'commerce';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isNomLike(texte) {
|
||||||
|
return Grammar.includesLowerCaseNoAccent(this.name, texte)
|
||||||
|
}
|
||||||
|
isNomTypeLike(texte) {
|
||||||
|
return this.isNomLike(texte) || Grammar.includesLowerCaseNoAccent(Misc.typeName(this.type, 'Item'), texte)
|
||||||
|
}
|
||||||
|
|
||||||
getQuantite() {
|
getQuantite() {
|
||||||
return this.isService() ? undefined : Math.round(this.system.quantite ?? 0)
|
return this.isService() ? undefined : Math.round(this.system.quantite ?? 0)
|
||||||
}
|
}
|
||||||
@@ -249,11 +366,11 @@ export class RdDItem extends Item {
|
|||||||
|
|
||||||
getEnc() {
|
getEnc() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case 'service':
|
case TYPES.service:
|
||||||
return 0;
|
return 0;
|
||||||
case 'herbe':
|
case TYPES.herbe:
|
||||||
return this.getEncHerbe();
|
return this.getEncHerbe();
|
||||||
case 'gemme':
|
case TYPES.gemme:
|
||||||
return encPepin * this.system.taille;
|
return encPepin * this.system.taille;
|
||||||
}
|
}
|
||||||
return Math.max(this.system.encombrement ?? 0, 0);
|
return Math.max(this.system.encombrement ?? 0, 0);
|
||||||
@@ -293,6 +410,7 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
this.system.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
|
this.system.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
|
||||||
}
|
}
|
||||||
|
this.equipable = this.isEquipable();
|
||||||
}
|
}
|
||||||
|
|
||||||
prepareDataPotion() {
|
prepareDataPotion() {
|
||||||
@@ -308,19 +426,19 @@ export class RdDItem extends Item {
|
|||||||
|
|
||||||
getActionPrincipale(options = { warnIfNot: true }) {
|
getActionPrincipale(options = { warnIfNot: true }) {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case 'conteneur': return 'Ouvrir';
|
case TYPES.conteneur: return 'Ouvrir';
|
||||||
}
|
}
|
||||||
if (this.actor?.isPersonnage()) {
|
if (this.actor?.isPersonnage()) {
|
||||||
const warn = options.warnIfNot;
|
const warn = options.warnIfNot;
|
||||||
if (this.isComestible() == 'brut') {
|
if (this.getUtilisationCuisine() == 'brut') {
|
||||||
return 'Utiliser';
|
return 'Utiliser';
|
||||||
}
|
}
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case 'nourritureboisson': return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
|
case TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
|
||||||
case 'potion': return this._actionOrWarnQuantiteZero('Boire', warn);
|
case TYPES.potion: return this._actionOrWarnQuantiteZero('Boire', warn);
|
||||||
case 'livre': return this._actionOrWarnQuantiteZero('Lire', warn);
|
case TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn);
|
||||||
case 'herbe': return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
|
case TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
|
||||||
case 'queue': case 'ombre': return this.system.refoulement > 0 ? 'Refouler' : undefined;
|
case TYPES.queue: case TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -335,11 +453,11 @@ export class RdDItem extends Item {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case 'potion': return await actor.consommerPotion(this, onActionItem);
|
case TYPES.potion: return await actor.consommerPotion(this, onActionItem);
|
||||||
case 'livre': return await actor.actionLire(this);
|
case TYPES.livre: return await actor.actionLire(this);
|
||||||
case 'conteneur': return await this.sheet.render(true);
|
case TYPES.conteneur: return await this.sheet.render(true);
|
||||||
case 'herbe': return await actor.actionHerbe(this);
|
case TYPES.herbe: return await actor.actionHerbe(this, onActionItem);
|
||||||
case 'queue': case 'ombre': return await actor.actionRefoulement(this);
|
case TYPES.queue: case TYPES.ombre: return await actor.actionRefoulement(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -361,7 +479,7 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onCreateDecoupeComestible(actor) {
|
async onCreateDecoupeComestible(actor) {
|
||||||
if (actor && this.isComestible() == 'brut' && this.system.sust != 1) {
|
if (actor && this.getUtilisationCuisine() == 'brut' && this.system.sust != 1) {
|
||||||
if (this.system.sust < 1) {
|
if (this.system.sust < 1) {
|
||||||
await actor.updateEmbeddedDocuments('Item', [{
|
await actor.updateEmbeddedDocuments('Item', [{
|
||||||
_id: this.id,
|
_id: this.id,
|
||||||
@@ -382,7 +500,7 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async empiler(item) {
|
async empiler(item) {
|
||||||
if (this.isComestible() == 'brut') {
|
if (this.getUtilisationCuisine() == 'brut') {
|
||||||
const sust = this.system.sust + item.system.sust;
|
const sust = this.system.sust + item.system.sust;
|
||||||
const encombrement = this.system.encombrement + item.system.encombrement;
|
const encombrement = this.system.encombrement + item.system.encombrement;
|
||||||
await this.update({
|
await this.update({
|
||||||
@@ -433,8 +551,8 @@ export class RdDItem extends Item {
|
|||||||
return [false, `Impossible de regrouper ${this.name} avec ${other.name}`];
|
return [false, `Impossible de regrouper ${this.name} avec ${other.name}`];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
const excludedProperties = ['quantite', 'cout', 'encTotal', 'environnement'];
|
const excludedProperties = ['quantite', 'cout', 'encTotal', 'environnement', 'contenu'];
|
||||||
if (this.isComestible()) {
|
if (this.getUtilisationCuisine()) {
|
||||||
excludedProperties.push('sust', 'encombrement');
|
excludedProperties.push('sust', 'encombrement');
|
||||||
}
|
}
|
||||||
let differences = Object.entries(this.system)
|
let differences = Object.entries(this.system)
|
||||||
|
51
module/item/armure.js
Normal file
51
module/item/armure.js
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import { RdDItem } from "../item.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { ReglesOptionelles } from "../settings/regles-optionelles.js";
|
||||||
|
|
||||||
|
export class RdDItemArmure extends RdDItem {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.webp";
|
||||||
|
}
|
||||||
|
|
||||||
|
deteriorerArmure(dmg) {
|
||||||
|
if (!ReglesOptionelles.isUsing('deteriorationArmure') || this.system.protection == '0') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let deterioration = (this.system.deterioration ?? 0) + dmg;
|
||||||
|
let protection = this.system.protection;
|
||||||
|
|
||||||
|
if (deterioration >= 10) {
|
||||||
|
deterioration -= 10;
|
||||||
|
protection = this.calculProtectionDeterioree();
|
||||||
|
ChatMessage.create({ content: `Votre armure ${this.name} s'est détériorée, elle protège maintenant de ${protection}` });
|
||||||
|
}
|
||||||
|
this.update({
|
||||||
|
system: {
|
||||||
|
deterioration: deterioration,
|
||||||
|
protection: protection
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
calculProtectionDeterioree() {
|
||||||
|
const protectionCourante = this.system.protection;
|
||||||
|
let res = /(\d+)?d(\d+)(\-\d+)?/.exec(protectionCourante);
|
||||||
|
if (res) {
|
||||||
|
let protection = Misc.toInt(res[2]);
|
||||||
|
let malus = Misc.toInt(res[3]) - 1;
|
||||||
|
if (protection + malus <= 0) {
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return `1d${protection}${malus}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (/\d+/.exec(protectionCourante)) {
|
||||||
|
return `1d${protectionCourante}`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.warn(`La valeur d'armure de votre ${this.name} est incorrecte`);
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
199
module/item/blessure.js
Normal file
199
module/item/blessure.js
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
import { RdDItem } from "../item.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { RdDTimestamp } from "../time/rdd-timestamp.js";
|
||||||
|
|
||||||
|
const BASE_TACHE_SOIN_BLESSURE = {
|
||||||
|
type: "tache",
|
||||||
|
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_chirurgie.webp',
|
||||||
|
system: { carac: "dexterite", competence: "Chirurgie", periodicite: "1 round", fatigue: 0, }
|
||||||
|
}
|
||||||
|
const TACHES_SOIN_BLESSURE = {
|
||||||
|
6: { name: 'Blessure critique', system: { difficulte: -6, points_de_tache: 6 } },
|
||||||
|
4: { name: 'Blessure grave', system: { difficulte: -4, points_de_tache: 4 } },
|
||||||
|
2: { name: 'Blessure légère', system: { difficulte: -2, points_de_tache: 2 } },
|
||||||
|
}
|
||||||
|
|
||||||
|
const definitionsBlessures = [
|
||||||
|
{ type: "contusion", gravite: 0, label: 'Contusion/éraflure', max: 100, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/eraflure.webp" },
|
||||||
|
{ type: "legere", gravite: 2, label: 'Légère', max: 5, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
|
||||||
|
{ type: "grave", gravite: 4, label: 'Grave', max: 2, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
|
||||||
|
{ type: "critique", gravite: 6, label: 'Critique', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
|
||||||
|
{ type: "mort", gravite: 8, label: 'Mort', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/mort.webp" }
|
||||||
|
]
|
||||||
|
|
||||||
|
export class RdDItemBlessure extends RdDItem {
|
||||||
|
|
||||||
|
static get defaultIcon() {
|
||||||
|
return "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp";
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareDerivedData() {
|
||||||
|
super.prepareDerivedData();
|
||||||
|
this.system.label = this.getLabelGravite()
|
||||||
|
}
|
||||||
|
|
||||||
|
static prepareTacheSoin(gravite) {
|
||||||
|
const tache = TACHES_SOIN_BLESSURE[gravite]
|
||||||
|
if (!tache) {
|
||||||
|
ui.notifications.warn(`Pas de tâche de soins pour une blessure ${gravite}`)
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return mergeObject(duplicate(BASE_TACHE_SOIN_BLESSURE), tache)
|
||||||
|
}
|
||||||
|
static async createBlessure(actor, gravite, localisation = '', attacker) {
|
||||||
|
const definition = RdDItemBlessure.getDefinition(gravite)
|
||||||
|
const blessure = {
|
||||||
|
name: definition.label,
|
||||||
|
type: 'blessure',
|
||||||
|
img: definition.icon,
|
||||||
|
system: {
|
||||||
|
gravite: gravite,
|
||||||
|
difficulte: - gravite,
|
||||||
|
localisation: localisation,
|
||||||
|
origine: attacker?.name ?? ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
|
||||||
|
return blessures[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
static async createTacheSoinBlessure(actor, gravite) {
|
||||||
|
const tache = RdDItemBlessure.prepareTacheSoin(gravite)
|
||||||
|
if (tache) {
|
||||||
|
const taches = await actor.createEmbeddedDocuments('Item', [tache], { renderSheet: false });
|
||||||
|
return taches[0];
|
||||||
|
}
|
||||||
|
return undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateTacheSoinBlessure(tache) {
|
||||||
|
if (tache) {
|
||||||
|
await tache.update({
|
||||||
|
system: {
|
||||||
|
itemId: this.id,
|
||||||
|
difficulte: Math.min(this.system.difficulte, tache.system.difficulte),
|
||||||
|
points_de_tache_courant: Math.max(0, this.system.premierssoins.tache)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async setSoinsBlessure(systemUpdate = {}) {
|
||||||
|
systemUpdate = mergeObject(systemUpdate, this.system, { overwrite: false }),
|
||||||
|
systemUpdate.soinscomplets.done = systemUpdate.premierssoins.done && systemUpdate.soinscomplets.done
|
||||||
|
await this.update({
|
||||||
|
img: this.getImgSoins(systemUpdate.gravite, systemUpdate.soinscomplets.done),
|
||||||
|
system: systemUpdate
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async recuperationBlessure({ actor, timestamp, message, isMaladeEmpoisonne, blessures }) {
|
||||||
|
if (this.parent != actor || actor == undefined) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (new RdDTimestamp(this.system.temporel.fin).compare(timestamp) > 0) {
|
||||||
|
// attente periode
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.system.gravite > 0) {
|
||||||
|
const update = { system: { premierssoins: { bonus: 0 }, soinscomplets: { bonus: 0 } } }
|
||||||
|
const gravite = this.system.gravite;
|
||||||
|
const graviteMoindre = gravite - 2;
|
||||||
|
const moindres = blessures.filter(it => it.system.gravite == graviteMoindre, 'blessures').length
|
||||||
|
const label = this.getLabelGravite();
|
||||||
|
|
||||||
|
let rolled = await actor.jetRecuperationConstitution(this.system.soinscomplets.bonus, message);
|
||||||
|
|
||||||
|
if (rolled.isETotal) {
|
||||||
|
message.content += ` -- une blessure ${label} s'infecte (temps de guérison augmenté de ${gravite} jours, perte de vie)`;
|
||||||
|
await actor.santeIncDec("vie", -1);
|
||||||
|
mergeObject(update, {
|
||||||
|
system: { fin: { indexDate: timestamp.addJours(gravite).indexDate } }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!isMaladeEmpoisonne && rolled.isSuccess && this.peutRetrograder(graviteMoindre, moindres)) {
|
||||||
|
message.content += ` -- une blessure ${label} cicatrise`;
|
||||||
|
mergeObject(update, {
|
||||||
|
system: { gravite: graviteMoindre, fin: { indexDate: timestamp.addJours(graviteMoindre).indexDate } }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
message.content += ` -- une blessure ${label} reste stable`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await this.update(update);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
peutRetrograder(graviteMoindre, moindres) {
|
||||||
|
return moindres < RdDItemBlessure.getDefinition(graviteMoindre).max
|
||||||
|
}
|
||||||
|
|
||||||
|
async calculerFinPeriodeTemporel(debut) {
|
||||||
|
return await debut.nouveauJour().addJours(this.system.gravite);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onFinPeriode(oldTimestamp, newTimestamp) {
|
||||||
|
if (this.system.gravite <= 0) {
|
||||||
|
await super.onFinPeriode(oldTimestamp, newTimestamp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getImgSoins(gravite, soins) {
|
||||||
|
let img = 'blessure'
|
||||||
|
if (gravite > 6) {
|
||||||
|
img = 'mort'
|
||||||
|
}
|
||||||
|
if (gravite <= 0) {
|
||||||
|
img = 'eraflure'
|
||||||
|
}
|
||||||
|
return `systems/foundryvtt-reve-de-dragon/icons/sante/${soins ? 'blessure-soins' : img}.webp`
|
||||||
|
}
|
||||||
|
|
||||||
|
getLabelGravite() {
|
||||||
|
return RdDItemBlessure.getDefinition(this.system.gravite).label
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDefinition(gravite) {
|
||||||
|
return definitionsBlessures.sort(Misc.ascending(it => it.gravite))
|
||||||
|
.find(it => it.gravite >= gravite);
|
||||||
|
}
|
||||||
|
static maxBlessures(gravite) {
|
||||||
|
return RdDItemBlessure.getDefinition(gravite).max
|
||||||
|
}
|
||||||
|
|
||||||
|
isContusion() {
|
||||||
|
return this.system.gravite <= 0
|
||||||
|
}
|
||||||
|
isLegere() {
|
||||||
|
return this.system.gravite > 0 && this.system.gravite <= 2
|
||||||
|
}
|
||||||
|
isGrave() {
|
||||||
|
return this.system.gravite > 2 && this.system.gravite <= 4
|
||||||
|
}
|
||||||
|
isCritique() {
|
||||||
|
return this.system.gravite > 4 && this.system.gravite <= 6
|
||||||
|
}
|
||||||
|
isMort() {
|
||||||
|
return this.system.gravite > 6
|
||||||
|
}
|
||||||
|
|
||||||
|
getProprietes() {
|
||||||
|
return [
|
||||||
|
RdDItem.propertyIfDefined('Causée par', this.system.origine, this.system.origine),
|
||||||
|
`<b>Heure et Date</b>: ${new RdDTimestamp(this.system.temporel.debut).formatDateHeure()}`,
|
||||||
|
RdDItem.propertyIfDefined('Blessé', this.parent?.name, this.parent),
|
||||||
|
`<b>Localisation</b>: ${this.system.localisation}`,
|
||||||
|
`<b>Gravité</b>: ${RdDItemBlessure.getDefinition(this.system.gravite).label}`,
|
||||||
|
`<b>Difficulté des soins</b>: ${this.system.difficulte}`,
|
||||||
|
(this.system.soinscomplets.done ?
|
||||||
|
`<b>Bonus soins complets</b>: ${this.system.soinscomplets.bonus}` :
|
||||||
|
(this.system.premierssoins.done ?
|
||||||
|
`<b>Bonus premiers soins</b>: ${this.system.premierssoins.bonus}` :
|
||||||
|
`<b>Points de tâche</b>: ${this.system.premierssoins.tache}`
|
||||||
|
)
|
||||||
|
),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@@ -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 { RdDTimestamp } from "../rdd-timestamp.js";
|
import { RdDTimestamp } from "../time/rdd-timestamp.js";
|
||||||
|
|
||||||
export class RdDItemMaladie extends RdDItem {
|
export class RdDItemMaladie extends RdDItem {
|
||||||
|
|
||||||
|
31
module/item/raretes.js
Normal file
31
module/item/raretes.js
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
|
||||||
|
const RARETE_COMMUNE = { code: 'Commune', label: 'Commune', frequence: 54, min: 27, max: 108 };
|
||||||
|
const RARETE_FREQUENTE = { code: 'Frequente', label: 'Fréquente', frequence: 18, min: 9, max: 36 };
|
||||||
|
const RARETE_RARE = { code: 'Rare', label: 'Rare', frequence: 6, min: 3, max: 12 };
|
||||||
|
const RARETE_RARISSIME = { code: 'Rarissime', label: 'Rarissime', frequence: 2, min: 1, max: 4 };
|
||||||
|
const RARETE_INEXISTANT = { code: 'Inexistant', label: 'Inexistant', frequence: 0, min: 0, max: 0 };
|
||||||
|
const RARETE_EGALE = { code: 'eqal', label: 'Egal', frequence: 1, min: 1, max: 1 };
|
||||||
|
|
||||||
|
const RARETES = [
|
||||||
|
RARETE_COMMUNE,
|
||||||
|
RARETE_FREQUENTE,
|
||||||
|
RARETE_RARE,
|
||||||
|
RARETE_RARISSIME,
|
||||||
|
RARETE_INEXISTANT,
|
||||||
|
]
|
||||||
|
|
||||||
|
export class RdDRaretes {
|
||||||
|
|
||||||
|
static rareteFrequente() { return RARETE_FREQUENTE; }
|
||||||
|
static rareteEgale() { return RARETE_EGALE; }
|
||||||
|
static raretes() { return RARETES; }
|
||||||
|
|
||||||
|
static byCode(code = undefined) {
|
||||||
|
return RARETES.find(it => it.code == code) ?? RARETE_FREQUENTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getChamp(rarete, field = undefined) {
|
||||||
|
return RdDRaretes.byCode(rarete)[field ?? 'frequence'];
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
import { EffetsRencontre } from "../effets-rencontres.js";
|
import { EffetsRencontre } from "../tmr/effets-rencontres.js";
|
||||||
import { RdDItem } from "../item.js";
|
import { RdDItem } from "../item.js";
|
||||||
|
|
||||||
const tableEffets = [
|
const tableEffets = [
|
120
module/item/sheet-base-inventaire.js
Normal file
120
module/item/sheet-base-inventaire.js
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
import { HtmlUtility } from "../html-utility.js";
|
||||||
|
import { RdDItemSheet } from "../item-sheet.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { RdDRaretes } from "./raretes.js";
|
||||||
|
|
||||||
|
const TYPE_ITEMS_NATURELS = ["faune", "herbe", "plante", "ingredient"];
|
||||||
|
|
||||||
|
export class RdDItemInventaireSheet extends RdDItemSheet {
|
||||||
|
|
||||||
|
static get defaultOptions() {
|
||||||
|
return mergeObject(RdDItemSheet.defaultOptions, {
|
||||||
|
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
setPosition(options = {}) {
|
||||||
|
const position = super.setPosition(options);
|
||||||
|
const sheetHeader = this.element.find(".sheet-header");
|
||||||
|
const sheetBody = this.element.find(".sheet-body");
|
||||||
|
sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getData() {
|
||||||
|
const formData = await super.getData();
|
||||||
|
return mergeObject(formData, {
|
||||||
|
milieux: await game.system.rdd.environnement.autresMilieux(this.item)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
HtmlUtility.showControlWhen(this.html.find("div.description-milieu"), TYPE_ITEMS_NATURELS.includes(this.item.type));
|
||||||
|
|
||||||
|
if (!this.options.editable) return;
|
||||||
|
this.html.find("a.preparer-nourriture").click(event => this.preparerNourriture(event));
|
||||||
|
this.html.find("a.manger-nourriture").click(event => this.mangerNourriture(event));
|
||||||
|
|
||||||
|
this.html.find("input.input-selection-milieu").keypress(event => {
|
||||||
|
if (event.keyCode == '13') {
|
||||||
|
this.onAddMilieu(event);
|
||||||
|
}
|
||||||
|
event.stopPropagation();
|
||||||
|
})
|
||||||
|
this.html.find("a.milieu-add").click(event => this.onAddMilieu(event));
|
||||||
|
this.html.find("div.environnement-milieu a.milieu-delete").click(event => this.onDeleteMilieu(event));
|
||||||
|
this.html.find("div.environnement-milieu select.environnement-rarete").change(event => this.onChange(event,
|
||||||
|
updated => this.$changeRarete(event, updated)));
|
||||||
|
this.html.find("div.environnement-milieu input[name='environnement-frequence']").change(event => this.onChange(event,
|
||||||
|
updated => this.$changeFrequence(event, updated)));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async preparerNourriture(event) {
|
||||||
|
if (this.actor && this.item.getUtilisationCuisine() == 'brut') {
|
||||||
|
await this.actor.preparerNourriture(this.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async mangerNourriture(event) {
|
||||||
|
if (this.actor && this.item.getUtilisation() == 'cuisine') {
|
||||||
|
await this.actor.mangerNourriture(this.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$changeFrequence(event, updated) {
|
||||||
|
updated.frequence = Number(this.html.find(event.currentTarget).val());
|
||||||
|
}
|
||||||
|
|
||||||
|
$changeRarete(event, updated) {
|
||||||
|
const code = this.html.find(event.currentTarget).val();
|
||||||
|
const rarete = RdDRaretes.byCode(code);
|
||||||
|
updated.rarete = rarete.code;
|
||||||
|
updated.frequence = rarete.frequence;
|
||||||
|
}
|
||||||
|
|
||||||
|
async onAddMilieu(event) {
|
||||||
|
const milieu = this.html.find('input.input-selection-milieu').val();
|
||||||
|
if (!milieu) {
|
||||||
|
ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${this.item.name}`);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const list = this.item.getEnvironnements();
|
||||||
|
const exists = list.find(it => it.milieu == milieu);
|
||||||
|
if (exists) {
|
||||||
|
ui.notifications.warn(`${this.item.name} a déjà une rareté ${exists.rarete} en ${milieu} (fréquence: ${exists.frequence})`);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const rarete = RdDRaretes.rareteFrequente();
|
||||||
|
const added = { milieu, rarete: rarete.code, frequence: rarete.frequence };
|
||||||
|
const newList = [added, ...list].sort(Misc.ascending(it => it.milieu))
|
||||||
|
await this.item.update({ 'system.environnement': newList })
|
||||||
|
}
|
||||||
|
|
||||||
|
async onDeleteMilieu(event) {
|
||||||
|
const milieu = this.$getEventMilieu(event);
|
||||||
|
if (milieu != undefined) {
|
||||||
|
const newList = this.item.getEnvironnements().filter(it => it.milieu != milieu)
|
||||||
|
.sort(Misc.ascending(it => it.milieu));
|
||||||
|
await this.item.update({ 'system.environnement': newList });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async onChange(event, doMutation) {
|
||||||
|
const list = this.item.system.environnement;
|
||||||
|
const milieu = this.$getEventMilieu(event);
|
||||||
|
const updated = list.find(it => it.milieu == milieu);
|
||||||
|
if (updated) {
|
||||||
|
doMutation(updated);
|
||||||
|
const newList = [...list.filter(it => it.milieu != milieu), updated]
|
||||||
|
.sort(Misc.ascending(it => it.milieu));
|
||||||
|
await this.item.update({ 'system.environnement': newList });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$getEventMilieu(event) {
|
||||||
|
return this.html.find(event.currentTarget)?.parents("div.environnement-milieu").data("milieu");
|
||||||
|
}
|
||||||
|
}
|
29
module/item/sheet-blessure.js
Normal file
29
module/item/sheet-blessure.js
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import { RdDItemSheet } from "../item-sheet.js";
|
||||||
|
|
||||||
|
export class RdDBlessureItemSheet extends RdDItemSheet {
|
||||||
|
|
||||||
|
static get ITEM_TYPE() { return "blessure" };
|
||||||
|
|
||||||
|
async getData() {
|
||||||
|
const formData = await super.getData();
|
||||||
|
formData.disabled = formData.options.isGM || formData.options.isOwned ? '' : 'disabled';
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
this.html.find('[name="premierssoins-done"]').change(async event => {
|
||||||
|
await this.item.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } });
|
||||||
|
});
|
||||||
|
this.html.find('[name="soinscomplets-done"]').change(async event => {
|
||||||
|
await this.item.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } })
|
||||||
|
});
|
||||||
|
this.html.find('[name="system-gravite"]').change(async event => {
|
||||||
|
const gravite = Number(event.currentTarget.value)
|
||||||
|
await this.item.setSoinsBlessure({ gravite: gravite, difficulte: - gravite })
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
@@ -1,8 +1,9 @@
|
|||||||
import { RdDItemSheet } from "./item-sheet.js";
|
import { RdDBaseActorSheet } from "../actor/base-actor-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";
|
||||||
|
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
||||||
|
|
||||||
export class RdDConteneurItemSheet extends RdDItemSheet {
|
export class RdDConteneurItemSheet extends RdDItemInventaireSheet {
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "conteneur" };
|
static get ITEM_TYPE() { return "conteneur" };
|
||||||
|
|
||||||
@@ -27,8 +28,7 @@ export class RdDConteneurItemSheet extends RdDItemSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
prepareConteneurData(formData) {
|
prepareConteneurData(formData) {
|
||||||
RdDUtility.filterEquipementParType(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.objets);
|
||||||
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
|
formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems;
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,8 @@ export class RdDConteneurItemSheet extends RdDItemSheet {
|
|||||||
const dragData = {
|
const dragData = {
|
||||||
actorId: this.actor.id,
|
actorId: this.actor.id,
|
||||||
type: "Item",
|
type: "Item",
|
||||||
data: item.system
|
data: item.system,
|
||||||
|
uuid: item.uuid
|
||||||
};
|
};
|
||||||
|
|
||||||
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
|
event.dataTransfer.setData("text/plain", JSON.stringify(dragData));
|
||||||
@@ -51,7 +52,8 @@ export class RdDConteneurItemSheet extends RdDItemSheet {
|
|||||||
|
|
||||||
async _onDropItem(event, dragData) {
|
async _onDropItem(event, dragData) {
|
||||||
if (this.actor) {
|
if (this.actor) {
|
||||||
const dropParams = await RdDSheetUtility.prepareItemDropParameters(this.item.id, this.actor, dragData, this.objetVersConteneur);
|
const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id') ?? this.item.id
|
||||||
|
const dropParams = await RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor, dragData, this.objetVersConteneur);
|
||||||
await this.actor.processDropItem(dropParams);
|
await this.actor.processDropItem(dropParams);
|
||||||
await this.render(true);
|
await this.render(true);
|
||||||
}
|
}
|
38
module/item/sheet-faune.js
Normal file
38
module/item/sheet-faune.js
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
||||||
|
|
||||||
|
export class RdDFauneItemSheet extends RdDItemInventaireSheet {
|
||||||
|
|
||||||
|
static get ITEM_TYPE() { return "faune" };
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
|
||||||
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
html.find("a.linked-actor-delete").click(event => this.onDeleteLinkedActor());
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onDropActor(event, dragData) {
|
||||||
|
console.log('faune:dropActor', event, dragData)
|
||||||
|
const linkedActor = fromUuidSync(dragData.uuid);
|
||||||
|
if (linkedActor?.pack) {
|
||||||
|
this.item.update({
|
||||||
|
'system.actor.pack': linkedActor.pack,
|
||||||
|
'system.actor.id': linkedActor._id,
|
||||||
|
'system.actor.name': linkedActor.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.warn(`${linkedActor.name} ne provient pas d'un compendium.
|
||||||
|
<br>Choisissez une créature du compendium pour représenter un élément de faune générique`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async onDeleteLinkedActor() {
|
||||||
|
this.item.update({
|
||||||
|
'system.actor.pack': '',
|
||||||
|
'system.actor.id': '',
|
||||||
|
'system.actor.name': ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
6
module/item/sheet-herbe.js
Normal file
6
module/item/sheet-herbe.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
||||||
|
|
||||||
|
export class RdDHerbeItemSheet extends RdDItemInventaireSheet {
|
||||||
|
|
||||||
|
static get ITEM_TYPE() { return "herbe" };
|
||||||
|
}
|
5
module/item/sheet-ingredient.js
Normal file
5
module/item/sheet-ingredient.js
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
||||||
|
|
||||||
|
export class RdDIngredientItemSheet extends RdDItemInventaireSheet {
|
||||||
|
static get ITEM_TYPE() { return "ingredient" };
|
||||||
|
}
|
7
module/item/sheet-plante.js
Normal file
7
module/item/sheet-plante.js
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
||||||
|
|
||||||
|
export class RdDPlanteItemSheet extends RdDItemInventaireSheet {
|
||||||
|
|
||||||
|
static get ITEM_TYPE() { return "plante" };
|
||||||
|
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
import { RdDRencontre } from "./item/item-rencontre.js";
|
import { RdDRencontre } from "./rencontre.js";
|
||||||
import { RdDItemSheet } from "./item-sheet.js";
|
import { RdDItemSheet } from "../item-sheet.js";
|
||||||
|
|
||||||
export class RdDRencontreItemSheet extends RdDItemSheet {
|
export class RdDRencontreItemSheet extends RdDItemSheet {
|
||||||
|
|
@@ -1,4 +1,4 @@
|
|||||||
import { RdDItemSheet } from "./item-sheet.js";
|
import { RdDItemSheet } from "../item-sheet.js";
|
||||||
|
|
||||||
export class RdDServiceItemSheet extends RdDItemSheet {
|
export class RdDServiceItemSheet extends RdDItemSheet {
|
||||||
|
|
||||||
@@ -6,7 +6,7 @@ export class RdDServiceItemSheet extends RdDItemSheet {
|
|||||||
|
|
||||||
async getData() {
|
async getData() {
|
||||||
const formData = await super.getData();
|
const formData = await super.getData();
|
||||||
formData.disabled = formData.isGM || formData.isOwned ? '' : 'disabled';
|
formData.disabled = formData.options.isGM || formData.options.isOwned ? '' : 'disabled';
|
||||||
return formData;
|
return formData;
|
||||||
}
|
}
|
||||||
|
|
@@ -1,6 +1,6 @@
|
|||||||
import { RdDItemSheet } from "./item-sheet.js";
|
import { RdDItemSheet } from "../item-sheet.js";
|
||||||
import { RdDItemSigneDraconique } from "./item/item-signedraconique.js";
|
import { RdDItemSigneDraconique } from "./signedraconique.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "../tmr-utility.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item sheet pour signes draconiques
|
* Item sheet pour signes draconiques
|
@@ -2,7 +2,7 @@ import { RdDItem, defaultItemImg } from "../item.js";
|
|||||||
import { Misc } from "../misc.js";
|
import { Misc } from "../misc.js";
|
||||||
import { RdDDice } from "../rdd-dice.js";
|
import { RdDDice } from "../rdd-dice.js";
|
||||||
import { RdDRollTables } from "../rdd-rolltables.js";
|
import { RdDRollTables } from "../rdd-rolltables.js";
|
||||||
import { RdDTimestamp } from "../rdd-timestamp.js";
|
import { RdDTimestamp } from "../time/rdd-timestamp.js";
|
||||||
import { TMRType, TMRUtility } from "../tmr-utility.js";
|
import { TMRType, TMRUtility } from "../tmr-utility.js";
|
||||||
|
|
||||||
const tableSignesIndicatifs = [
|
const tableSignesIndicatifs = [
|
@@ -1,10 +1,10 @@
|
|||||||
import { RdDBaseActor } from "./actor/base-actor.js";
|
import { RdDBaseActor } from "./actor/base-actor.js";
|
||||||
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
|
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
|
||||||
import { Environnement } from "./environnement.js";
|
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { Monnaie } from "./item-monnaie.js";
|
import { Monnaie } from "./item-monnaie.js";
|
||||||
import { RdDItem } from "./item.js";
|
import { RdDItem } from "./item.js";
|
||||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||||
|
import { RdDRaretes } from "./item/raretes.js";
|
||||||
|
|
||||||
class Migration {
|
class Migration {
|
||||||
get code() { return "sample"; }
|
get code() { return "sample"; }
|
||||||
@@ -288,10 +288,11 @@ class _10_3_0_FrequenceEnvironnement extends Migration {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_updatesFrequences(it) {
|
_updatesFrequences(it) {
|
||||||
|
const rarete = RdDRaretes.byCode(it.system.rarete);
|
||||||
return {
|
return {
|
||||||
_id: it.id,
|
_id: it.id,
|
||||||
'system.rarete': undefined,
|
'system.rarete': undefined,
|
||||||
'system.environnement': [{ milieu: it.system.milieu, rarete: it.system.rarete, frequence: Environnement.getFrequenceRarete(it.system.rarete, 'frequence') }]
|
'system.environnement': [{ milieu: it.system.milieu, rarete: rarete.code, frequence: rarete.frequence }]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -415,6 +416,48 @@ class _10_5_0_UpdatePeriodicite extends Migration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _10_7_0_MigrationBlessures extends Migration {
|
||||||
|
get code() { return "migration-blessures"; }
|
||||||
|
get version() { return "10.7.0"; }
|
||||||
|
|
||||||
|
async migrate() {
|
||||||
|
const timestamp = game.system.rdd.calendrier.getTimestamp()
|
||||||
|
await Promise.all(game.actors.filter(it => it.isPersonnage() || it.isCreature())
|
||||||
|
.map(async (actor) => {
|
||||||
|
const legeres = actor.system.blessures?.legeres.liste.filter(it => it.active).map(it => this.creerBlessure(2, 'légère', it, timestamp)) ?? [];
|
||||||
|
const graves = actor.system.blessures?.graves.liste.filter(it => it.active).map(it => this.creerBlessure(4, 'grave', it, timestamp)) ?? [];
|
||||||
|
const critiques = actor.system.blessures?.critiques.liste.filter(it => it.active).map(it => this.creerBlessure(6, 'critique', it, timestamp));
|
||||||
|
const blessures = legeres.concat(graves).concat(critiques);
|
||||||
|
if (blessures.length > 0) {
|
||||||
|
await actor.createEmbeddedDocuments("Item", blessures);
|
||||||
|
}
|
||||||
|
await actor.update({
|
||||||
|
'system.blessures.legeres.liste': [],
|
||||||
|
'system.blessures.graves.liste': [],
|
||||||
|
'system.blessures.critiques.liste': []
|
||||||
|
})
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
creerBlessure(gravite, graviteTexte, blessure, timestamp) {
|
||||||
|
const dateBlessure = timestamp.addJours(-blessure.jours);
|
||||||
|
const datePremiereRecup = dateBlessure.addJours(gravite);
|
||||||
|
return {
|
||||||
|
name: `Blessure ${graviteTexte}`,
|
||||||
|
type: 'blessure',
|
||||||
|
img: `systems/foundryvtt-reve-de-dragon/icons/sante/blessure${blessure.psdone ? '-soins' : ''}.webp`,
|
||||||
|
system: {
|
||||||
|
gravite: gravite,
|
||||||
|
difficulte: -gravite,
|
||||||
|
debut: { indexDate: dateBlessure.indexDate, indexMinute: 0 },
|
||||||
|
fin: { indexDate: datePremiereRecup.indexDate, indexMinute: 0 },
|
||||||
|
premierssoins: { done: blessure.psdone, bonus: blessure.premiers_soins },
|
||||||
|
soinscomplets: { done: blessure.scdone, bonus: blessure.soins_complets },
|
||||||
|
localisation: blessure.localisation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class Migrations {
|
export class Migrations {
|
||||||
static getMigrations() {
|
static getMigrations() {
|
||||||
return [
|
return [
|
||||||
@@ -430,6 +473,7 @@ export class Migrations {
|
|||||||
new _10_3_17_Monnaies(),
|
new _10_3_17_Monnaies(),
|
||||||
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(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -85,6 +85,7 @@ export class Misc {
|
|||||||
list.forEach(it => addToObj(obj, it))
|
list.forEach(it => addToObj(obj, it))
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
static concat(lists) {
|
static concat(lists) {
|
||||||
return lists.reduce((a, b) => a.concat(b), []);
|
return lists.reduce((a, b) => a.concat(b), []);
|
||||||
}
|
}
|
||||||
@@ -118,6 +119,17 @@ export class Misc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @returns an array of incremental integers (including from / excluding to).
|
||||||
|
* if max<min, the array is decrementing integers
|
||||||
|
*/
|
||||||
|
static intArray(from, to) {
|
||||||
|
if (from > to) {
|
||||||
|
return Array.from(Array(from - to).keys()).map(i => from - i)
|
||||||
|
}
|
||||||
|
return Array.from(Array(to - from).keys()).map(i => from + i)
|
||||||
|
}
|
||||||
|
|
||||||
static distinct(array) {
|
static distinct(array) {
|
||||||
return [...new Set(array)];
|
return [...new Set(array)];
|
||||||
}
|
}
|
||||||
@@ -227,4 +239,15 @@ export class Misc {
|
|||||||
}
|
}
|
||||||
return subset;
|
return subset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static cssRotation(angle) {
|
||||||
|
const rotation = `rotate(${angle}deg)`;
|
||||||
|
return {
|
||||||
|
'transform': rotation,
|
||||||
|
'-ms-transform': rotation,
|
||||||
|
'-moz-transform': rotation,
|
||||||
|
'-webkit-transform': rotation,
|
||||||
|
'-o-transform': rotation
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -8,13 +8,11 @@ export class RdDAlchimie {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static processManipulation(recette, actorId = undefined) {
|
static processManipulation(recette, actorId = undefined) {
|
||||||
//console.log("CALLED", recette, recette.isOwned, actorId );
|
|
||||||
let manip = recette.system.manipulation;
|
let manip = recette.system.manipulation;
|
||||||
let matchArray = manip.match(matchOperations);
|
let matchArray = manip.match(matchOperations);
|
||||||
if (matchArray) {
|
if (matchArray) {
|
||||||
for (let matchStr of matchArray) {
|
for (let matchStr of matchArray) {
|
||||||
let result = matchStr.match(matchOperationTerms);
|
let result = matchStr.match(matchOperationTerms);
|
||||||
//console.log("RESULT ", result);
|
|
||||||
if (result[1] && result[2]) {
|
if (result[1] && result[2]) {
|
||||||
let commande = Misc.upperFirst(result[1]);
|
let commande = Misc.upperFirst(result[1]);
|
||||||
let replacement = this[`_alchimie${commande}`](recette, result[2], actorId);
|
let replacement = this[`_alchimie${commande}`](recette, result[2], actorId);
|
||||||
@@ -27,20 +25,19 @@ export class RdDAlchimie {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _alchimieCouleur(recette, couleurs, actorId) {
|
static _alchimieCouleur(recette, couleurs, actorId) {
|
||||||
if (actorId) {
|
return RdDAlchimie._alchimieLink(recette, couleurs, actorId, 'couleur', 'Température');
|
||||||
return `<span class="alchimie-tache"><a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="couleur" data-alchimie-data="${couleurs}">couleur ${couleurs}</a></span>`;
|
|
||||||
} else {
|
|
||||||
return `<span class="alchimie-tache">couleur ${couleurs} </span>`;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _alchimieConsistance(recette, consistances, actorId) {
|
static _alchimieConsistance(recette, consistances, actorId) {
|
||||||
if (actorId) {
|
return RdDAlchimie._alchimieLink(recette, consistances, actorId, 'consistance', 'Consistance');
|
||||||
return `<span class="alchimie-tache"><a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="consistance" data-alchimie-data="${consistances}">consistance ${consistances}</a></span>`;
|
|
||||||
} else {
|
|
||||||
return `<span class="alchimie-tache">consistance ${consistances} </span>`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static _alchimieLink(recette, termes, actorId, tacheAlchimie, labelTache) {
|
||||||
|
const difficulte = RdDAlchimie.getDifficulte(termes);
|
||||||
|
const link = actorId ? ` <a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="${tacheAlchimie}" data-alchimie-data="${termes}">` : '';
|
||||||
|
const endLink = actorId ? '</a>' : '';
|
||||||
|
return `<span class="alchimie-tache">${link}${labelTache} ${termes} (${difficulte})${endLink}</span>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@@ -1,53 +0,0 @@
|
|||||||
|
|
||||||
/**
|
|
||||||
* Extend the base Dialog entity by defining a custom window to perform roll.
|
|
||||||
* @extends {Dialog}
|
|
||||||
*/
|
|
||||||
export class RdDAstrologieEditeur extends Dialog {
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
constructor(html, calendrier, calendrierData) {
|
|
||||||
|
|
||||||
let myButtons = {
|
|
||||||
resetButton: { label: "Re-tirer les nombres astraux", callback: html => this.resetNombreAstraux() },
|
|
||||||
saveButton: { label: "Fermer", callback: html => this.fillData() }
|
|
||||||
};
|
|
||||||
|
|
||||||
// Common conf
|
|
||||||
let dialogConf = { content: html, title: "Editeur d'Astrologie", buttons: myButtons, default: "saveButton" };
|
|
||||||
let dialogOptions = {
|
|
||||||
classes: ["rdd-roll-dialog"], width: 600,
|
|
||||||
height: 'fit-content',
|
|
||||||
'max-height': 800,
|
|
||||||
'z-index': 99999
|
|
||||||
}
|
|
||||||
super(dialogConf, dialogOptions)
|
|
||||||
|
|
||||||
this.calendrier = calendrier;
|
|
||||||
this.updateData(calendrierData);
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
this.html = html;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async resetNombreAstraux() {
|
|
||||||
game.system.rdd.calendrier.resetNombreAstral();
|
|
||||||
await game.system.rdd.calendrier.rebuildListeNombreAstral();
|
|
||||||
|
|
||||||
game.system.rdd.calendrier.showAstrologieEditor();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
fillData() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
updateData(calendrierData) {
|
|
||||||
this.calendrierData = duplicate(calendrierData);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -1,100 +0,0 @@
|
|||||||
import { RdDItemCompetence } from "./item-competence.js";
|
|
||||||
import { Misc } from "./misc.js";
|
|
||||||
import { SYSTEM_SOCKET_ID } from "./constants.js";
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend the base Dialog entity by defining a custom window to perform roll.
|
|
||||||
* @extends {Dialog}
|
|
||||||
*/
|
|
||||||
export class RdDAstrologieJoueur extends Dialog {
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async create(actor) {
|
|
||||||
|
|
||||||
let dialogData = {
|
|
||||||
nombres: this.organizeNombres(actor),
|
|
||||||
dates: game.system.rdd.calendrier.getJoursSuivants(10),
|
|
||||||
etat: actor.getEtatGeneral(),
|
|
||||||
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
|
|
||||||
astrologie: RdDItemCompetence.findCompetence(actor.items, 'Astrologie')
|
|
||||||
}
|
|
||||||
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', dialogData);
|
|
||||||
|
|
||||||
const options = { classes: ["rdd-roll-dialog"], width: 600, height: 'fit-content', 'z-index': 99999 };
|
|
||||||
const dialog = new RdDAstrologieJoueur(html, actor, dialogData, options);
|
|
||||||
dialog.render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
constructor(html, actor, dialogData, dialogOptions) {
|
|
||||||
const dialogConf = {
|
|
||||||
title: "Nombres Astraux",
|
|
||||||
content: html,
|
|
||||||
default: "saveButton",
|
|
||||||
buttons: {
|
|
||||||
saveButton: { label: "Fermer", callback: html => this.quitDialog() }
|
|
||||||
},
|
|
||||||
};
|
|
||||||
super(dialogConf, dialogOptions);
|
|
||||||
|
|
||||||
this.actor = actor;
|
|
||||||
this.dataNombreAstral = duplicate(dialogData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
this.html = html;
|
|
||||||
|
|
||||||
this.html.find("[name='diffConditions']").val(0);
|
|
||||||
|
|
||||||
this.html.find('[name="jet-astrologie"]').click((event) => {
|
|
||||||
this.requestJetAstrologie();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static organizeNombres(actor) {
|
|
||||||
let itemNombres = actor.listItems('nombreastral');
|
|
||||||
let itemFiltered = {};
|
|
||||||
for (let item of itemNombres) {
|
|
||||||
if (itemFiltered[item.system.jourindex]) {
|
|
||||||
itemFiltered[item.system.jourindex].listValues.push(item.system.value);
|
|
||||||
} else {
|
|
||||||
itemFiltered[item.system.jourindex] = {
|
|
||||||
listValues: [item.system.value],
|
|
||||||
jourlabel: item.system.jourlabel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return itemFiltered;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
requestJetAstrologie() {
|
|
||||||
let socketData = {
|
|
||||||
id: this.actor.id,
|
|
||||||
carac_vue: this.actor.system.carac['vue'].value,
|
|
||||||
etat: this.dataNombreAstral.etat,
|
|
||||||
astrologie: this.dataNombreAstral.astrologie,
|
|
||||||
conditions: this.html.find('[name="diffConditions"]').val(),
|
|
||||||
date: this.html.find('[name="joursAstrologie"]').val(),
|
|
||||||
userId: game.user.id
|
|
||||||
}
|
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
|
||||||
game.system.rdd.calendrier.requestNombreAstral(socketData);
|
|
||||||
} else {
|
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
|
||||||
msg: "msg_request_nombre_astral",
|
|
||||||
data: socketData
|
|
||||||
});
|
|
||||||
}
|
|
||||||
this.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
quitDialog() {
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@@ -24,11 +24,14 @@ export class RdDBonus {
|
|||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isDefenseAttaqueFinesse(rollData) {
|
static isDefenseAttaqueFinesse(rollData) {
|
||||||
|
if (rollData.isEmpoignade && rollData.rolled?.isPart) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return rollData.attackerRoll?.particuliere == 'finesse';
|
return rollData.attackerRoll?.particuliere == 'finesse';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static dmg(rollData, dmgActor, isCauchemar = false) {
|
static dmg(rollData, dmgActor, isEntiteIncarnee = false) {
|
||||||
let dmg = { total: 0 };
|
let dmg = { total: 0 };
|
||||||
if (rollData.arme && rollData.arme.name.toLowerCase() == "esquive") {
|
if (rollData.arme && rollData.arme.name.toLowerCase() == "esquive") {
|
||||||
// Specific case management
|
// Specific case management
|
||||||
@@ -41,7 +44,7 @@ export class RdDBonus {
|
|||||||
dmg.dmgSurprise = RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris.used);
|
dmg.dmgSurprise = RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris.used);
|
||||||
dmg.dmgActor = rollData.selectedCarac ? RdDBonus._dmgPerso(dmgActor, rollData.selectedCarac.label, dmg.dmgArme) : 0;
|
dmg.dmgActor = rollData.selectedCarac ? RdDBonus._dmgPerso(dmgActor, rollData.selectedCarac.label, dmg.dmgArme) : 0;
|
||||||
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere;
|
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere;
|
||||||
dmg.mortalite = RdDBonus._calculMortalite(rollData, isCauchemar)
|
dmg.mortalite = RdDBonus._calculMortalite(rollData, isEntiteIncarnee)
|
||||||
}
|
}
|
||||||
return dmg;
|
return dmg;
|
||||||
}
|
}
|
||||||
@@ -62,11 +65,8 @@ export class RdDBonus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _calculMortalite(rollData, isCauchemar) {
|
static _calculMortalite(rollData, isEntiteIncarnee) {
|
||||||
if (isCauchemar) {
|
return isEntiteIncarnee ? "entiteincarnee"
|
||||||
return "cauchemar";
|
|
||||||
}
|
|
||||||
return isCauchemar ? "cauchemar"
|
|
||||||
: rollData.dmg?.mortalite
|
: rollData.dmg?.mortalite
|
||||||
?? rollData.arme?.system.mortalite
|
?? rollData.arme?.system.mortalite
|
||||||
?? "mortel";
|
?? "mortel";
|
||||||
|
@@ -1,501 +0,0 @@
|
|||||||
import { RdDCalendrierEditeur } from "./rdd-calendrier-editeur.js";
|
|
||||||
import { RdDAstrologieEditeur } from "./rdd-astrologie-editeur.js";
|
|
||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
|
||||||
import { Misc } from "./misc.js";
|
|
||||||
import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
|
||||||
import { DialogChronologie } from "./dialog-chronologie.js";
|
|
||||||
import { RdDTimestamp, WORLD_TIMESTAMP_SETTING } from "./rdd-timestamp.js";
|
|
||||||
|
|
||||||
const RDD_JOUR_PAR_MOIS = 28;
|
|
||||||
const RDD_HEURES_PAR_JOUR = 12;
|
|
||||||
const MAX_NOMBRE_ASTRAL = 12;
|
|
||||||
const JOURS_DU_MOIS = Array(RDD_JOUR_PAR_MOIS).fill().map((item, index) => 1 + index);
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
export class RdDCalendrier extends Application {
|
|
||||||
|
|
||||||
static get defaultOptions() {
|
|
||||||
return mergeObject(super.defaultOptions, {
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html",
|
|
||||||
popOut: false,
|
|
||||||
resizable: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
static createCalendrierPos() {
|
|
||||||
return { top: 200, left: 200 };
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
// position
|
|
||||||
this.calendrierPos = duplicate(game.settings.get(SYSTEM_RDD, "calendrier-pos"));
|
|
||||||
if (this.calendrierPos == undefined || this.calendrierPos.top == undefined) {
|
|
||||||
this.calendrierPos = RdDCalendrier.createCalendrierPos();
|
|
||||||
game.settings.set(SYSTEM_RDD, "calendrier-pos", this.calendrierPos);
|
|
||||||
}
|
|
||||||
// Calendrier
|
|
||||||
this.timestamp = RdDTimestamp.getWorldTime();
|
|
||||||
|
|
||||||
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
|
|
||||||
RdDTimestamp.setWorldTime(this.timestamp);
|
|
||||||
this.listeNombreAstral = this.getListeNombreAstral();
|
|
||||||
this.rebuildListeNombreAstral(HIDE_DICE); // Ensure always up-to-date
|
|
||||||
}
|
|
||||||
console.log('RdDCalendrier.constructor()', this.timestamp, this.timestamp.toCalendrier(), this.calendrierPos, this.listeNombreAstral);
|
|
||||||
Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id));
|
|
||||||
}
|
|
||||||
|
|
||||||
async onUpdateSetting(setting, update, options, id) {
|
|
||||||
if (setting.key == SYSTEM_RDD + '.' + WORLD_TIMESTAMP_SETTING) {
|
|
||||||
this.timestamp = RdDTimestamp.getWorldTime();
|
|
||||||
this.updateDisplay();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** @override */
|
|
||||||
async activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
this.html = html;
|
|
||||||
|
|
||||||
this.updateDisplay();
|
|
||||||
|
|
||||||
this.html.find('.ajout-chronologie').click(ev => DialogChronologie.create());
|
|
||||||
|
|
||||||
this.html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));
|
|
||||||
|
|
||||||
this.html.find('.calendar-btn-edit').click(ev => {
|
|
||||||
ev.preventDefault();
|
|
||||||
this.showCalendarEditor();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.html.find('.astrologie-btn-edit').click(ev => {
|
|
||||||
ev.preventDefault();
|
|
||||||
this.showAstrologieEditor();
|
|
||||||
});
|
|
||||||
|
|
||||||
this.html.find('#calendar-move-handle').mousedown(ev => {
|
|
||||||
ev.preventDefault();
|
|
||||||
ev = ev || window.event;
|
|
||||||
let isRightMB = false;
|
|
||||||
if ("which" in ev) { // Gecko (Firefox), WebKit (Safari/Chrome) & Opera
|
|
||||||
isRightMB = ev.which == 3;
|
|
||||||
} else if ("button" in ev) { // IE, Opera
|
|
||||||
isRightMB = ev.button == 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isRightMB) {
|
|
||||||
dragElement(document.getElementById("calendar-time-container"));
|
|
||||||
let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
|
|
||||||
|
|
||||||
function dragElement(elmnt) {
|
|
||||||
elmnt.onmousedown = dragMouseDown;
|
|
||||||
function dragMouseDown(e) {
|
|
||||||
e = e || window.event;
|
|
||||||
e.preventDefault();
|
|
||||||
pos3 = e.clientX;
|
|
||||||
pos4 = e.clientY;
|
|
||||||
|
|
||||||
document.onmouseup = closeDragElement;
|
|
||||||
document.onmousemove = elementDrag;
|
|
||||||
}
|
|
||||||
|
|
||||||
function elementDrag(e) {
|
|
||||||
e = e || window.event;
|
|
||||||
e.preventDefault();
|
|
||||||
// calculate the new cursor position:
|
|
||||||
pos1 = pos3 - e.clientX;
|
|
||||||
pos2 = pos4 - e.clientY;
|
|
||||||
pos3 = e.clientX;
|
|
||||||
pos4 = e.clientY;
|
|
||||||
// set the element's new position:
|
|
||||||
elmnt.style.bottom = undefined
|
|
||||||
elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
|
|
||||||
elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeDragElement() {
|
|
||||||
// stop moving when mouse button is released:
|
|
||||||
elmnt.onmousedown = undefined;
|
|
||||||
document.onmouseup = undefined;
|
|
||||||
document.onmousemove = undefined;
|
|
||||||
let xPos = (elmnt.offsetLeft - pos1) > window.innerWidth ? window.innerWidth - 200 : (elmnt.offsetLeft - pos1);
|
|
||||||
let yPos = (elmnt.offsetTop - pos2) > window.innerHeight - 20 ? window.innerHeight - 100 : (elmnt.offsetTop - pos2)
|
|
||||||
xPos = xPos < 0 ? 0 : xPos;
|
|
||||||
yPos = yPos < 0 ? 0 : yPos;
|
|
||||||
if (xPos != (elmnt.offsetLeft - pos1) || yPos != (elmnt.offsetTop - pos2)) {
|
|
||||||
elmnt.style.top = (yPos) + "px";
|
|
||||||
elmnt.style.left = (xPos) + "px";
|
|
||||||
}
|
|
||||||
game.system.rdd.calendrier.calendrierPos.top = yPos;
|
|
||||||
game.system.rdd.calendrier.calendrierPos.left = xPos;
|
|
||||||
if (game.user.isGM) {
|
|
||||||
game.settings.set(SYSTEM_RDD, "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (isRightMB) {
|
|
||||||
game.system.rdd.calendrier.calendrierPos.top = 200;
|
|
||||||
game.system.rdd.calendrier.calendrierPos.left = 200;
|
|
||||||
if (game.user.isGM) {
|
|
||||||
game.settings.set(SYSTEM_RDD, "calendrier-pos", duplicate(game.system.rdd.calendrier.calendrierPos));
|
|
||||||
}
|
|
||||||
this.setPos(game.system.rdd.calendrier.calendrierPos);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getListeNombreAstral() {
|
|
||||||
return game.settings.get(SYSTEM_RDD, "liste-nombre-astral") ?? [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
dateCourante() {
|
|
||||||
return this.timestamp.formatDate();
|
|
||||||
}
|
|
||||||
|
|
||||||
isAfterIndexDate(indexDate) {
|
|
||||||
// TODO: standardize
|
|
||||||
return indexDate < this.timestamp.indexDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
heureCourante() { return RdDTimestamp.definition(this.timestamp.heure); }
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getCurrentMinute() { return this.timestamp.indexMinute; }
|
|
||||||
|
|
||||||
getTimestampFinChateauDormant(nbJours = 0) {
|
|
||||||
return this.timestamp.nouveauJour().addJour(nbJours);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTimestampFinHeure(nbHeures = 0) {
|
|
||||||
return this.timestamp.nouvelleHeure().addHeures(nbHeures);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getIndexFromDate(jour, mois) {
|
|
||||||
const addYear = mois < this.timestamp.mois || (mois == this.timestamp.mois && jour < this.timestamp.jour)
|
|
||||||
const time = RdDTimestamp.timestamp(this.timestamp.annee + (addYear ? 1 : 0), mois, jour);
|
|
||||||
return time.indexDate;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getJoursSuivants(count) {
|
|
||||||
let jours = [];
|
|
||||||
let indexDate = this.timestamp.indexDate;
|
|
||||||
for (let i = 0; i < count; i++, indexDate++) {
|
|
||||||
jours[i] = { label: RdDTimestamp.formatIndexDate(indexDate), index: indexDate };
|
|
||||||
}
|
|
||||||
return jours;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async ajouterNombreAstral(indexDate, showDice = SHOW_DICE) {
|
|
||||||
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: showDice, 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 {
|
|
||||||
nombreAstral: nombreAstral,
|
|
||||||
valeursFausses: [],
|
|
||||||
index: indexDate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getCurrentNombreAstral() {
|
|
||||||
return this.getNombreAstral(this.timestamp.indexDate);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
resetNombreAstral() {
|
|
||||||
this.listeNombreAstral = [];
|
|
||||||
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.listeNombreAstral);
|
|
||||||
|
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
|
||||||
msg: "msg_reset_nombre_astral",
|
|
||||||
data: {}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getNombreAstral(indexDate) {
|
|
||||||
const listNombreAstral = this.getListeNombreAstral();
|
|
||||||
let astralData = listNombreAstral.find((nombreAstral, i) => nombreAstral.index == indexDate);
|
|
||||||
return astralData?.nombreAstral;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async rebuildListeNombreAstral(showDice = HIDE_DICE) {
|
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
|
||||||
let newList = [];
|
|
||||||
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
|
|
||||||
let dayIndex = this.timestamp.indexDate + i;
|
|
||||||
let na = this.listeNombreAstral.find(n => n.index == dayIndex);
|
|
||||||
if (na) {
|
|
||||||
newList[i] = na;
|
|
||||||
} else {
|
|
||||||
newList[i] = await this.ajouterNombreAstral(dayIndex, showDice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.listeNombreAstral = newList;
|
|
||||||
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", newList);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async setNewTimestamp(newTimestamp) {
|
|
||||||
game.actors.forEach(actor => actor.onTimeChanging(this.timestamp, newTimestamp));
|
|
||||||
RdDTimestamp.setWorldTime(newTimestamp);
|
|
||||||
this.timestamp = newTimestamp;
|
|
||||||
await this.rebuildListeNombreAstral();
|
|
||||||
this.updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async onCalendarButton(ev) {
|
|
||||||
ev.preventDefault();
|
|
||||||
const calendarAvance = ev.currentTarget.attributes['data-calendar-avance'];
|
|
||||||
const calendarSet = ev.currentTarget.attributes['data-calendar-set'];
|
|
||||||
if (calendarAvance) {
|
|
||||||
await this.incrementTime(Number(calendarAvance.value));
|
|
||||||
}
|
|
||||||
else if (calendarSet) {
|
|
||||||
this.positionnerHeure(Number(calendarSet.value));
|
|
||||||
}
|
|
||||||
this.updateDisplay();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async incrementTime(minutes = 0) {
|
|
||||||
await this.setNewTimestamp(this.timestamp.addMinutes(minutes));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async incrementerJour() {
|
|
||||||
await this.setNewTimestamp(this.timestamp.nouveauJour());
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async positionnerHeure(indexHeure) {
|
|
||||||
await this.setNewTimestamp(new RdDTimestamp({ indexDate: this.timestamp.indexDate + (this.timestamp.heure < indexHeure ? 0 : 1) }).addHeures(indexHeure))
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
fillCalendrierData(formData = {}) {
|
|
||||||
mergeObject(formData, this.timestamp.toCalendrier());
|
|
||||||
formData.isGM = game.user.isGM;
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getLectureAstrologieDifficulte(dateIndex) {
|
|
||||||
let indexNow = this.timestamp.indexDate;
|
|
||||||
let diffDay = dateIndex - indexNow;
|
|
||||||
return - Math.floor(diffDay / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async requestNombreAstral(request) {
|
|
||||||
const actor = game.actors.get(request.id);
|
|
||||||
if (Misc.isUniqueConnectedGM()) { // Only once
|
|
||||||
console.log(request);
|
|
||||||
let jourDiff = this.getLectureAstrologieDifficulte(request.date);
|
|
||||||
let niveau = Number(request.astrologie.system.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat);
|
|
||||||
let rollData = {
|
|
||||||
caracValue: request.carac_vue,
|
|
||||||
finalLevel: niveau,
|
|
||||||
showDice: HIDE_DICE,
|
|
||||||
rollMode: "blindroll"
|
|
||||||
};
|
|
||||||
await RdDResolutionTable.rollData(rollData);
|
|
||||||
request.rolled = rollData.rolled;
|
|
||||||
request.isValid = request.rolled.isSuccess;
|
|
||||||
request.nbAstral = this.getNombreAstral(request.date);
|
|
||||||
|
|
||||||
if (request.rolled.isSuccess) {
|
|
||||||
if (request.rolled.isPart) {
|
|
||||||
// Gestion expérience (si existante)
|
|
||||||
request.competence = actor.getCompetence("astrologie")
|
|
||||||
request.selectedCarac = actor.system.carac["vue"];
|
|
||||||
actor.appliquerAjoutExperience(request, 'hide');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
request.nbAstral = await RdDDice.rollTotal("1dhr" + request.nbAstral, {
|
|
||||||
rollMode: "selfroll", showDice: HIDE_DICE
|
|
||||||
});
|
|
||||||
// Mise à jour des nombres astraux du joueur
|
|
||||||
this.addNbAstralIncorect(request.id, request.date, request.nbAstral);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Misc.getActiveUser(request.userId)?.isGM) {
|
|
||||||
RdDUtility.responseNombreAstral(request);
|
|
||||||
} else {
|
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, {
|
|
||||||
msg: "msg_response_nombre_astral",
|
|
||||||
data: request
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addNbAstralIncorect(actorId, date, nbAstral) {
|
|
||||||
let astralData = this.listeNombreAstral.find((nombreAstral, i) => nombreAstral.index == date);
|
|
||||||
astralData.valeursFausses.push({ actorId: actorId, nombreAstral: nbAstral });
|
|
||||||
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.listeNombreAstral);
|
|
||||||
}
|
|
||||||
|
|
||||||
getHeureChance(heure) {
|
|
||||||
return heure + (this.getCurrentNombreAstral() ?? 1) - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getHeuresChanceMalchance(heureNaissance) {
|
|
||||||
let defHeure = RdDTimestamp.findHeure(heureNaissance);
|
|
||||||
if (defHeure) {
|
|
||||||
const signe = h => h % RDD_HEURES_PAR_JOUR;
|
|
||||||
const chance = this.getHeureChance(defHeure.heure);
|
|
||||||
return [
|
|
||||||
{ ajustement: "+4", heures: [signe(chance)] },
|
|
||||||
{ ajustement: "+2", heures: [signe(chance + 4), signe(chance + 8)] },
|
|
||||||
{ ajustement: "-4", heures: [signe(chance + 6)] },
|
|
||||||
{ ajustement: "-2", heures: [signe(chance + 3), signe(chance + 9)] }
|
|
||||||
];
|
|
||||||
}
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getAjustementAstrologique(heureNaissance, name = undefined) {
|
|
||||||
let defHeure = RdDTimestamp.findHeure(heureNaissance);
|
|
||||||
if (defHeure) {
|
|
||||||
const chance = this.getHeureChance(defHeure.heure);
|
|
||||||
const ecartChance = (chance - this.timestamp.heure) % RDD_HEURES_PAR_JOUR;
|
|
||||||
switch (ecartChance) {
|
|
||||||
case 0: return 4;
|
|
||||||
case 4: case 8: return 2;
|
|
||||||
case 6: return -4;
|
|
||||||
case 3: case 9: return -2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (name) {
|
|
||||||
ui.notifications.warn(name + " n'a pas d'heure de naissance, ou elle est incorrecte : " + heureNaissance);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
ui.notifications.warn(heureNaissance + " ne correspond pas à une heure de naissance");
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getData() {
|
|
||||||
let formData = super.getData();
|
|
||||||
this.fillCalendrierData(formData);
|
|
||||||
this.setPos(this.calendrierPos);
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
setPos(pos) {
|
|
||||||
return new Promise(resolve => {
|
|
||||||
function check() {
|
|
||||||
let elmnt = document.getElementById("calendar-time-container");
|
|
||||||
if (elmnt) {
|
|
||||||
elmnt.style.bottom = undefined;
|
|
||||||
let xPos = (pos.left) > window.innerWidth ? window.innerWidth - 200 : pos.left;
|
|
||||||
let yPos = (pos.top) > window.innerHeight - 20 ? window.innerHeight - 100 : pos.top;
|
|
||||||
elmnt.style.top = (yPos) + "px";
|
|
||||||
elmnt.style.left = (xPos) + "px";
|
|
||||||
resolve();
|
|
||||||
} else {
|
|
||||||
setTimeout(check, 30);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
check();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
updateDisplay() {
|
|
||||||
let calendrier = this.fillCalendrierData();
|
|
||||||
// Rebuild text du calendrier
|
|
||||||
let dateHTML = `${calendrier.jourDuMois} ${calendrier.mois.label} ${calendrier.annee} (${calendrier.mois.saison})`
|
|
||||||
if (game.user.isGM) {
|
|
||||||
dateHTML = dateHTML + " - NA: " + (this.getCurrentNombreAstral() ?? "?");
|
|
||||||
}
|
|
||||||
for (let handle of document.getElementsByClassName("calendar-date-rdd")) {
|
|
||||||
handle.innerHTML = dateHTML;
|
|
||||||
}
|
|
||||||
for (let heure of document.getElementsByClassName("calendar-heure-texte")) {
|
|
||||||
heure.innerHTML = calendrier.heure.label;
|
|
||||||
}
|
|
||||||
for (const minute of document.getElementsByClassName("calendar-time-disp")) {
|
|
||||||
minute.innerHTML = `${calendrier.minute} minutes`;
|
|
||||||
}
|
|
||||||
for (const heureImg of document.getElementsByClassName("calendar-heure-img")) {
|
|
||||||
heureImg.src = calendrier.heure.icon;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async saveEditeur(calendrierData) {
|
|
||||||
const newTimestamp = RdDTimestamp.timestamp(
|
|
||||||
Number.parseInt(calendrierData.annee),
|
|
||||||
calendrierData.mois.heure,
|
|
||||||
Number.parseInt(calendrierData.jourMois),
|
|
||||||
calendrierData.heure.heure,
|
|
||||||
Number.parseInt(calendrierData.minutes)
|
|
||||||
);
|
|
||||||
await this.setNewTimestamp(newTimestamp);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async showCalendarEditor() {
|
|
||||||
let calendrierData = this.fillCalendrierData();
|
|
||||||
if (this.editeur == undefined) {
|
|
||||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html', calendrierData);
|
|
||||||
this.editeur = new RdDCalendrierEditeur(html, this, calendrierData)
|
|
||||||
}
|
|
||||||
this.editeur.updateData(calendrierData);
|
|
||||||
this.editeur.render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
static buildJoursMois() { return JOURS_DU_MOIS; }
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async showAstrologieEditor() {
|
|
||||||
const calendrierData = duplicate(this.fillCalendrierData());
|
|
||||||
this.listeNombreAstral = this.listeNombreAstral || [];
|
|
||||||
|
|
||||||
calendrierData.astrologieData = this.listeNombreAstral.map(astro => {
|
|
||||||
const timestamp = new RdDTimestamp({ indexDate: astro.index });
|
|
||||||
astro.date = { mois: timestamp.mois, jour: timestamp.jour + 1 }
|
|
||||||
for (let vf of astro.valeursFausses) {
|
|
||||||
let actor = game.actors.get(vf.actorId);
|
|
||||||
vf.actorName = (actor) ? actor.name : "Inconnu";
|
|
||||||
}
|
|
||||||
return astro;
|
|
||||||
});
|
|
||||||
|
|
||||||
calendrierData.heuresParActeur = {};
|
|
||||||
game.actors.filter(it => it.isPersonnage() && it.hasPlayerOwner).forEach(actor => {
|
|
||||||
let heureNaissance = actor.getHeureNaissance();
|
|
||||||
if (heureNaissance) {
|
|
||||||
calendrierData.heuresParActeur[actor.name] = this.getHeuresChanceMalchance(heureNaissance);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/calendar-astrologie-template.html', calendrierData);
|
|
||||||
let astrologieEditeur = new RdDAstrologieEditeur(html, this, calendrierData)
|
|
||||||
astrologieEditeur.updateData(calendrierData);
|
|
||||||
astrologieEditeur.render(true);
|
|
||||||
}
|
|
||||||
}
|
|
@@ -39,9 +39,10 @@ const tableCaracDerivee = {
|
|||||||
|
|
||||||
export class RdDCarac {
|
export class RdDCarac {
|
||||||
|
|
||||||
static isAgiliteOuDerivee(selectedCarac) {
|
static isAgiliteOuDerobee(selectedCarac) {
|
||||||
return selectedCarac?.label.match(/(Agilité|Dérobée)/);
|
return selectedCarac?.label.match(/(Agilité|Dérobée)/);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isVolonte(selectedCarac) {
|
static isVolonte(selectedCarac) {
|
||||||
return selectedCarac?.label == 'Volonté';
|
return selectedCarac?.label == 'Volonté';
|
||||||
}
|
}
|
||||||
|
@@ -1,6 +1,5 @@
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
import { ENTITE_BLURETTE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
import { DialogSelectTarget } from "./dialog-select-target.js";
|
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { RdDItemArme } from "./item-arme.js";
|
import { RdDItemArme } from "./item-arme.js";
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
@@ -13,6 +12,7 @@ import { RdDRollTables } from "./rdd-rolltables.js";
|
|||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||||
import { STATUSES } from "./settings/status-effects.js";
|
import { STATUSES } from "./settings/status-effects.js";
|
||||||
import { Targets } from "./targets.js";
|
import { Targets } from "./targets.js";
|
||||||
|
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const premierRoundInit = [
|
const premierRoundInit = [
|
||||||
@@ -40,35 +40,32 @@ export class RdDCombatManager extends Combat {
|
|||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
Hooks.on("getCombatTrackerEntryContext", (html, options) => {
|
Hooks.on("getCombatTrackerEntryContext", (html, options) => { RdDCombatManager.pushInitiativeOptions(html, options); });
|
||||||
RdDCombatManager.pushInitiativeOptions(html, options);
|
Hooks.on("updateCombat", (combat, change, options, userId) => { RdDCombat.onUpdateCombat(combat, change, options, userId) });
|
||||||
});
|
Hooks.on("preDeleteCombat", (combat, html, id) => { combat.onPreDeleteCombat() });
|
||||||
Hooks.on("preDeleteCombat", (combat, html, id) => {
|
|
||||||
combat.onPreDeleteCombat()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
cleanItemUse() {
|
|
||||||
for (let turn of this.turns) {
|
|
||||||
turn.actor.resetItemUse()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async nextRound() {
|
async nextRound() {
|
||||||
this.cleanItemUse();
|
|
||||||
await this.finDeRound();
|
await this.finDeRound();
|
||||||
return await super.nextRound();
|
return await super.nextRound();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onPreDeleteCombat() {
|
async onPreDeleteCombat() {
|
||||||
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
await this.finDeRound({ terminer: true });
|
await this.finDeRound({ terminer: true });
|
||||||
|
ChatUtility.removeChatMessageContaining(`<div data-combatid="${this.id}" data-combatmessage="actor-turn-summary">`)
|
||||||
|
game.messages.filter(m => ChatUtility.getMessageData(m, 'attacker-roll') != undefined && ChatUtility.getMessageData(m, 'defender-roll') != undefined)
|
||||||
|
.forEach(it => it.delete());
|
||||||
|
RdDEmpoignade.deleteAllEmpoignades()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async finDeRound(options = { terminer: false }) {
|
async finDeRound(options = { terminer: false }) {
|
||||||
|
this.turns.forEach(turn => turn.actor.resetItemUse());
|
||||||
|
|
||||||
for (let combatant of this.combatants) {
|
for (let combatant of this.combatants) {
|
||||||
if (combatant.actor) {
|
if (combatant.actor) {
|
||||||
await combatant.actor.finDeRound(options);
|
await combatant.actor.finDeRound(options);
|
||||||
@@ -96,13 +93,26 @@ export class RdDCombatManager extends Combat {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
|
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
|
||||||
const compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.system.competence;
|
let compName = "Corps à corps"
|
||||||
|
if (armeCombat) {
|
||||||
|
if (armeCombat.system.competence != "") {
|
||||||
|
compName = armeCombat.system.competence
|
||||||
|
}
|
||||||
|
if (armeCombat.system.lancer != "") {
|
||||||
|
compName = armeCombat.system.lancer
|
||||||
|
}
|
||||||
|
if (armeCombat.system.tir != "") {
|
||||||
|
compName = armeCombat.system.tir
|
||||||
|
}
|
||||||
|
}
|
||||||
const competence = RdDItemCompetence.findCompetence(combatant.actor.items, compName);
|
const competence = RdDItemCompetence.findCompetence(combatant.actor.items, compName);
|
||||||
if (competence) {
|
if (competence && competence.system.defaut_carac) {
|
||||||
const carac = combatant.actor.system.carac[competence.system.defaut_carac].value;
|
const carac = combatant.actor.system.carac[competence.system.defaut_carac].value;
|
||||||
const niveau = competence.system.niveau;
|
const niveau = competence.system.niveau;
|
||||||
const bonusEcaille = (armeCombat?.system.magique) ? armeCombat.system.ecaille_efficacite : 0;
|
const bonusEcaille = (armeCombat?.system.magique) ? armeCombat.system.ecaille_efficacite : 0;
|
||||||
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, bonusEcaille);
|
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, bonusEcaille);
|
||||||
|
} else {
|
||||||
|
ui.notifications.warn(`Votre arme ${armeCombat.name} n'a pas de compétence renseignée`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -111,10 +121,10 @@ export class RdDCombatManager extends Combat {
|
|||||||
if (!roll.total) {
|
if (!roll.total) {
|
||||||
roll.evaluate({ async: false });
|
roll.evaluate({ async: false });
|
||||||
}
|
}
|
||||||
if (roll.total <= 0) roll.total = 0.00;
|
const total = Math.max(roll.total, 0.00);
|
||||||
console.log("Compute init for", rollFormula, roll.total, combatant);
|
console.log("Compute init for", rollFormula, roll, total, combatant);
|
||||||
let id = combatant._id || combatant.id;
|
let id = combatant._id || combatant.id;
|
||||||
await this.updateEmbeddedDocuments("Combatant", [{ _id: id, initiative: roll.total }]);
|
await this.updateEmbeddedDocuments("Combatant", [{ _id: id, initiative: total }]);
|
||||||
|
|
||||||
// Send a chat message
|
// Send a chat message
|
||||||
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
|
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
|
||||||
@@ -145,9 +155,8 @@ export class RdDCombatManager extends Combat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static calculInitiative(niveau, caracValue, bonusEcaille = 0) {
|
static calculInitiative(niveau, caracValue, bonus = 0) {
|
||||||
let base = niveau + Math.floor(caracValue / 2);
|
let base = niveau + Math.floor(caracValue / 2) + bonus;
|
||||||
base += bonusEcaille;
|
|
||||||
return "1d6" + (base >= 0 ? "+" : "") + base;
|
return "1d6" + (base >= 0 ? "+" : "") + base;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +259,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
} 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))
|
const armes = actor.itemTypes['arme'].filter(it => RdDItemArme.isArmeUtilisable(it))
|
||||||
//.concat(RdDItemArme.empoignade())
|
.concat(RdDItemArme.empoignade())
|
||||||
.concat(RdDItemArme.mainsNues());
|
.concat(RdDItemArme.mainsNues());
|
||||||
|
|
||||||
const competences = actor.itemTypes['competence'];
|
const competences = actor.itemTypes['competence'];
|
||||||
@@ -421,18 +430,11 @@ export class RdDCombatManager extends Combat {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDCombat {
|
export class RdDCombat {
|
||||||
|
|
||||||
static init() {
|
|
||||||
Hooks.on("updateCombat", (combat, change, options, userId) => { RdDCombat.onUpdateCombat(combat, change, options, userId) });
|
|
||||||
Hooks.on("preDeleteCombat", (combat, options, userId) => { RdDCombat.onPreDeleteCombat(combat, options, userId); });
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static onSocketMessage(sockmsg) {
|
static onSocketMessage(sockmsg) {
|
||||||
switch (sockmsg.msg) {
|
switch (sockmsg.msg) {
|
||||||
case "msg_encaisser":
|
case "msg_encaisser": return RdDCombat.onMsgEncaisser(sockmsg.data);
|
||||||
return RdDCombat.onMsgEncaisser(sockmsg.data);
|
case "msg_defense": return RdDCombat.onMsgDefense(sockmsg.data);
|
||||||
case "msg_defense":
|
|
||||||
return RdDCombat.onMsgDefense(sockmsg.data);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -443,16 +445,6 @@ export class RdDCombat {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static onPreDeleteCombat(combat, options, userId) {
|
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
|
||||||
combat.cleanItemUse();
|
|
||||||
ChatUtility.removeChatMessageContaining(`<div data-combatid="${combat.id}" data-combatmessage="actor-turn-summary">`)
|
|
||||||
game.messages.filter(m => ChatUtility.getMessageData(m, 'attacker-roll') != undefined && ChatUtility.getMessageData(m, 'defender-roll') != undefined)
|
|
||||||
.forEach(it => it.delete());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static combatNouveauTour(combat) {
|
static combatNouveauTour(combat) {
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
@@ -757,29 +749,14 @@ export class RdDCombat {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async attaque(competence, arme) {
|
async attaque(competence, arme) {
|
||||||
// const nonIncarnee = this.defender.isEntite([ENTITE_NONINCARNE])
|
|
||||||
// const blurette = this.defender.isEntite([ENTITE_BLURETTE])
|
|
||||||
// if (nonIncarnee || blurette) {
|
|
||||||
// ChatMessage.create( {
|
|
||||||
// content: `<strong>La cible est ${nonIncarnee ? 'non incarnée' : 'une blurette'}.
|
|
||||||
// Il est impossible de l'atteindre.`,
|
|
||||||
// whisper: ChatMessage.getWhisperRecipients("GM")})
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
|
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (arme.system.cac == 'empoignade' && this.attacker.isCombatTouche()) {
|
if (arme.system.cac == 'empoignade') {
|
||||||
ChatMessage.create({
|
RdDEmpoignade.onAttaqueEmpoignade(this.attacker, this.defender)
|
||||||
alias: this.attacker.name,
|
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
|
||||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-actor-perte-empoignade.html', {
|
|
||||||
attacker: this.attacker,
|
|
||||||
competence: competence
|
|
||||||
})
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
RdDEmpoignade.checkEmpoignadeEnCours(this.attacker)
|
||||||
|
|
||||||
let rollData = this._prepareAttaque(competence, arme);
|
let rollData = this._prepareAttaque(competence, arme);
|
||||||
console.log("RdDCombat.attaque >>>", rollData);
|
console.log("RdDCombat.attaque >>>", rollData);
|
||||||
@@ -971,9 +948,8 @@ export class RdDCombat {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
_filterArmesParade(defender, competence) {
|
_filterArmesParade(defender, competence) {
|
||||||
let items = defender.items.filter(it => RdDItemArme.isArmeUtilisable(it) || RdDItemCompetenceCreature.isCompetenceParade(it))
|
let items = defender.items.filter(it => RdDItemArme.isArmeUtilisable(it) || RdDItemCompetenceCreature.isCompetenceParade(it))
|
||||||
for (let item of items) {
|
items.forEach(item => item.system.nbUsage = defender.getItemUse(item.id)); // Ajout du # d'utilisation ce round
|
||||||
item.system.nbUsage = defender.getItemUse(item.id); // Ajout du # d'utilisation ce round
|
|
||||||
}
|
|
||||||
switch (competence.system.categorie) {
|
switch (competence.system.categorie) {
|
||||||
case 'tir':
|
case 'tir':
|
||||||
case 'lancer':
|
case 'lancer':
|
||||||
@@ -1328,13 +1304,8 @@ export class RdDCombat {
|
|||||||
blessuresStatus: actor.computeResumeBlessure(),
|
blessuresStatus: actor.computeResumeBlessure(),
|
||||||
SConst: actor.getSConst(),
|
SConst: actor.getSConst(),
|
||||||
actorId: actor.id,
|
actorId: actor.id,
|
||||||
isGrave: false,
|
isGrave: actor.countBlessures(it => it.isGrave()) > 0,
|
||||||
isCritique: false
|
isCritique: actor.countBlessures(it => it.isCritique()) > 0
|
||||||
}
|
|
||||||
if (actor.countBlessuresNonSoigneeByName("critiques") > 0) { // Pour éviter le cumul grave + critique
|
|
||||||
formData.isCritique = true;
|
|
||||||
} else if (actor.countBlessuresNonSoigneeByName("graves") > 0) {
|
|
||||||
formData.isGrave = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ChatUtility.createChatWithRollMode(actor.name, {
|
ChatUtility.createChatWithRollMode(actor.name, {
|
||||||
|
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
import { DialogChronologie } from "./dialog-chronologie.js";
|
import { DialogChronologie } from "./dialog-chronologie.js";
|
||||||
import { DialogCreateSigneDraconique } from "./dialog-create-signedraconique.js";
|
import { DialogCreateSigneDraconique } from "./dialog-create-signedraconique.js";
|
||||||
import { DialogStress } from "./dialog-stress.js";
|
import { DialogChateauDormant } from "./sommeil/dialog-chateau-dormant.js";
|
||||||
|
import { DialogStress } from "./sommeil/dialog-stress.js";
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
@@ -13,7 +14,7 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
|||||||
import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
|
import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
|
||||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { CompendiumTableHelpers } from "./settings/system-compendiums.js";
|
import { FenetreRechercheTirage } from "./tirage/fenetre-recherche-tirage.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
|
||||||
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
|
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
|
||||||
@@ -23,6 +24,7 @@ export class RdDCommands {
|
|||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
const rddCommands = new RdDCommands();
|
const rddCommands = new RdDCommands();
|
||||||
|
game.system.rdd.commands = rddCommands;
|
||||||
|
|
||||||
Hooks.on("chatMessage", (html, content, msg) => {
|
Hooks.on("chatMessage", (html, content, msg) => {
|
||||||
if (content[0] == '/') {
|
if (content[0] == '/') {
|
||||||
@@ -35,7 +37,6 @@ export class RdDCommands {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
game.system.rdd.commands = rddCommands;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@@ -63,7 +64,6 @@ export class RdDCommands {
|
|||||||
<br><strong>/table rencontre deso</strong> affiche la table des rencontres en Désolation
|
<br><strong>/table rencontre deso</strong> affiche la table des rencontres en Désolation
|
||||||
<br><strong>/table rencontre mauvaise</strong> affiche la table des mauvaises rencontres`
|
<br><strong>/table rencontre mauvaise</strong> affiche la table des mauvaises rencontres`
|
||||||
});
|
});
|
||||||
this.registerCommand({ path: ["/table", "milieu"], func: (content, msg, params) => this.tableMilieu(msg, params, 'liste'), descr: "Affiche la table des ressource naturelles pour un milieu donné" });
|
|
||||||
|
|
||||||
this.registerCommand({ path: ["/tirer", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence('chat'), descr: "Tire une compétence au hasard" });
|
this.registerCommand({ path: ["/tirer", "comp"], func: (content, msg, params) => RdDRollTables.getCompetence('chat'), descr: "Tire une compétence au hasard" });
|
||||||
this.registerCommand({ path: ["/tirer", "queue"], func: (content, msg, params) => RdDRollTables.getQueue('chat'), descr: "Tire une Queue de Dragon" });
|
this.registerCommand({ path: ["/tirer", "queue"], func: (content, msg, params) => RdDRollTables.getQueue('chat'), descr: "Tire une Queue de Dragon" });
|
||||||
@@ -75,8 +75,9 @@ export class RdDCommands {
|
|||||||
this.registerCommand({ path: ["/tirer", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe('chat'), descr: "Tire une Idée fixe" });
|
this.registerCommand({ path: ["/tirer", "ideefixe"], func: (content, msg, params) => RdDRollTables.getIdeeFixe('chat'), descr: "Tire une Idée fixe" });
|
||||||
this.registerCommand({ path: ["/tirer", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant('chat'), descr: "Tire un Désir Lancinant" });
|
this.registerCommand({ path: ["/tirer", "desir"], func: (content, msg, params) => RdDRollTables.getDesirLancinant('chat'), descr: "Tire un Désir Lancinant" });
|
||||||
this.registerCommand({ path: ["/tirer", "rencontre"], func: (content, msg, params) => this.getRencontreTMR(params), descr: `Détermine une rencontre dans les TMR (synonyme de "/tmrr")` });
|
this.registerCommand({ path: ["/tirer", "rencontre"], func: (content, msg, params) => this.getRencontreTMR(params), descr: `Détermine une rencontre dans les TMR (synonyme de "/tmrr")` });
|
||||||
this.registerCommand({ path: ["/tirer", "milieu"], func: (content, msg, params) => this.tableMilieu(msg, params, 'chat'), descr: "Effectue un tirage dans la table desressource naturelles pour un milieu donné" });
|
this.registerCommand({ path: ["/tirage"], func: (content, msg, params) => this.tirage(), descr: "Ouvre la fenêtre de recherche et tirage" });
|
||||||
|
|
||||||
|
this.registerCommand({ path: ["/sommeil"], func: (content, msg, params) => this.sommeil(msg, params), descr: "Prépare le passage de journée pour chateau dormant" });
|
||||||
this.registerCommand({ path: ["/meteo"], func: (content, msg, params) => this.getMeteo(msg, params), descr: "Propose une météo marine" });
|
this.registerCommand({ path: ["/meteo"], func: (content, msg, params) => this.getMeteo(msg, params), descr: "Propose une météo marine" });
|
||||||
this.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
|
this.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" });
|
||||||
|
|
||||||
@@ -254,10 +255,7 @@ export class RdDCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async help(msg) {
|
async help(msg, table = undefined) {
|
||||||
this.help(msg, undefined);
|
|
||||||
}
|
|
||||||
async help(msg, table) {
|
|
||||||
let commands = []
|
let commands = []
|
||||||
this._buildSubTableHelp(commands, table ?? this.commandsTable);
|
this._buildSubTableHelp(commands, table ?? this.commandsTable);
|
||||||
|
|
||||||
@@ -334,7 +332,7 @@ export class RdDCommands {
|
|||||||
let competence = length > 1 ? actors[0].getCompetence(Misc.join(params.slice(1, length), ' ')) : { name: undefined };
|
let competence = length > 1 ? actors[0].getCompetence(Misc.join(params.slice(1, length), ' ')) : { name: undefined };
|
||||||
if (competence) {
|
if (competence) {
|
||||||
for (let actor of actors) {
|
for (let actor of actors) {
|
||||||
await actor.rollCaracCompetence(caracName, competence.name, diff);
|
await actor.doRollCaracCompetence(caracName, competence.name, diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -398,32 +396,6 @@ export class RdDCommands {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async tableMilieu(msg, params, toChat) {
|
|
||||||
if (params && params.length > 0) {
|
|
||||||
const search = Misc.join(params, ' ');
|
|
||||||
const milieux = await game.system.rdd.environnement.findEnvironnementsLike(search);
|
|
||||||
if (milieux.length == 0) {
|
|
||||||
const tous = Object.values(await game.system.rdd.environnement.milieux());
|
|
||||||
return RdDCommands._chatAnswer(msg, `<strong>Aucun milieu correspondant à '${search}'.</strong>
|
|
||||||
<br>Milieux disponibles:
|
|
||||||
<br><ul class="chat-list"><li>${tous.reduce(Misc.joining('</li><li>'))}</li></ul>`);
|
|
||||||
}
|
|
||||||
if (milieux.length > 1) {
|
|
||||||
ui.notifications.warn(`<strong>Plusieurs milieux correspondent à '${search}'</strong>:
|
|
||||||
<br><ul class="chat-list"><li>${milieux.reduce(Misc.joining('</li><li>'))}</li></ul>`);
|
|
||||||
}
|
|
||||||
const tableName = `ressources en ${milieux.reduce(Misc.joining(', '))}`;
|
|
||||||
if (toChat == 'liste') {
|
|
||||||
return await game.system.rdd.environnement.searchToChatMessage(milieux, tableName);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const row = await game.system.rdd.environnement.getRandom(milieux, tableName);
|
|
||||||
await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item');
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getCoutXpComp(msg, params) {
|
getCoutXpComp(msg, params) {
|
||||||
if (params && (params.length == 1 || params.length == 2)) {
|
if (params && (params.length == 1 || params.length == 2)) {
|
||||||
@@ -491,13 +463,14 @@ export class RdDCommands {
|
|||||||
let name = params[params.length - 1];
|
let name = params[params.length - 1];
|
||||||
if (name == undefined) {
|
if (name == undefined) {
|
||||||
for (let actor of game.actors) {
|
for (let actor of game.actors) {
|
||||||
actor.distribuerStress('stress', stress, motif);
|
// TODO: ne plus stresser les entités de cauchemar!
|
||||||
|
await actor.distribuerStress('stress', stress, motif);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//console.log(stressValue, nomJoueur);
|
//console.log(stressValue, nomJoueur);
|
||||||
let actor = Misc.findActor(name, game.actors.filter(it => it.hasPlayerOwner)) ?? Misc.findPlayer(name)?.character
|
let actor = Misc.findActor(name, game.actors.filter(it => it.hasPlayerOwner)) ?? Misc.findPlayer(name)?.character
|
||||||
if (actor) {
|
if (actor) {
|
||||||
actor.distribuerStress('stress', stress, motif);
|
await actor.distribuerStress('stress', stress, motif);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ui.notifications.warn(`Pas de personnage ou de joueur correspondant à ${name}!`);
|
ui.notifications.warn(`Pas de personnage ou de joueur correspondant à ${name}!`);
|
||||||
@@ -511,5 +484,11 @@ export class RdDCommands {
|
|||||||
return await RdDMeteo.getMeteo();
|
return await RdDMeteo.getMeteo();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async tirage() {
|
||||||
|
FenetreRechercheTirage.create();
|
||||||
|
}
|
||||||
|
async sommeil() {
|
||||||
|
DialogChateauDormant.create();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
import { SYSTEM_RDD } from "./constants.js";
|
||||||
|
|
||||||
export class RddCompendiumOrganiser {
|
export class RdDCompendiumOrganiser {
|
||||||
static init() {
|
static init() {
|
||||||
Hooks.on('renderCompendium', async (pack, html, compendiumData) => RddCompendiumOrganiser.onRenderCompendium(pack, html, compendiumData))
|
Hooks.on('renderCompendium', async (pack, html, compendiumData) => RdDCompendiumOrganiser.onRenderCompendium(pack, html, compendiumData))
|
||||||
}
|
}
|
||||||
|
|
||||||
static async onRenderCompendium(compendium, html, compendiumData) {
|
static async onRenderCompendium(compendium, html, compendiumData) {
|
||||||
@@ -10,14 +10,14 @@ export class RddCompendiumOrganiser {
|
|||||||
const pack = compendium.collection
|
const pack = compendium.collection
|
||||||
if (pack.metadata.system === SYSTEM_RDD) {
|
if (pack.metadata.system === SYSTEM_RDD) {
|
||||||
html.find('.directory-item').each((i, element) => {
|
html.find('.directory-item').each((i, element) => {
|
||||||
RddCompendiumOrganiser.setEntityTypeName(pack, element);
|
RdDCompendiumOrganiser.setEntityTypeName(pack, element);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async setEntityTypeName(pack, element) {
|
static async setEntityTypeName(pack, element) {
|
||||||
const label = RddCompendiumOrganiser.getEntityTypeLabel(await pack.getDocument(element.dataset.documentId));
|
const label = RdDCompendiumOrganiser.getEntityTypeLabel(await pack.getDocument(element.dataset.documentId));
|
||||||
RddCompendiumOrganiser.insertEntityType(element, label);
|
RdDCompendiumOrganiser.insertEntityType(element, label);
|
||||||
}
|
}
|
||||||
|
|
||||||
static insertEntityType(element, label) {
|
static insertEntityType(element, label) {
|
||||||
|
314
module/rdd-empoignade.js
Normal file
314
module/rdd-empoignade.js
Normal file
@@ -0,0 +1,314 @@
|
|||||||
|
/* -------------------------------------------- */
|
||||||
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
|
import { RdDRoll } from "./rdd-roll.js";
|
||||||
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||||
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
|
import { STATUSES } from "./settings/status-effects.js";
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
export class RdDEmpoignade {
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static checkEmpoignadeEnCours(actor) {
|
||||||
|
// TODO: autoriser la perception? la comédie/séduction?
|
||||||
|
if (RdDEmpoignade.isEmpoignadeEnCours(actor)) {
|
||||||
|
ui.notifications.warn("Une empoignade est en cours ! Normalement, vous ne pouvez rien faire d'autre que continuer l'empoignade ou la rompre.")
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static isEmpoignadeEnCours(actor) {
|
||||||
|
return actor.itemTypes['empoignade'].find(it => it.system.pointsemp > 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static getEmpoignadeById(actor, id) {
|
||||||
|
let emp = actor.itemTypes['empoignade'].find(it => it.system.empoignadeid == id)
|
||||||
|
return emp && duplicate(emp) || undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static getEmpoignade(attacker, defender) {
|
||||||
|
let emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id)
|
||||||
|
if (!emp) {
|
||||||
|
emp = attacker.itemTypes['empoignade'].find(it => it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
|
||||||
|
}
|
||||||
|
if (emp) {
|
||||||
|
return duplicate(emp);
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static getMalusTaille(emp, attacker, defender) {
|
||||||
|
// Si pas empoigné, alors 0
|
||||||
|
if (emp.system.pointsemp == 0) {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
// Malus de -1 si différence de taille de 2 ou plus (p 135)
|
||||||
|
if (attacker.system.carac.taille.value < defender.system.carac.taille.value - 1) {
|
||||||
|
return attacker.system.carac.taille.value - (defender.system.carac.taille.value - 1)
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
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"
|
||||||
|
|
||||||
|
let rollData = {
|
||||||
|
mode: mode,
|
||||||
|
isEmpoignade: 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async onAttaqueEmpoignade(attacker, defender) {
|
||||||
|
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
||||||
|
const isNouvelle = empoignade == undefined;
|
||||||
|
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
||||||
|
//console.log("W.", empoignade, defender.hasArmeeMeleeEquipee())
|
||||||
|
if ((isNouvelle || empoignade.system.pointsemp == 0) && defender.hasArmeeMeleeEquipee()) {
|
||||||
|
ChatUtility.createChatWithRollMode(attacker.name, {
|
||||||
|
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-valider.html`, { attacker: attacker, defender: defender })
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async onAttaqueEmpoignadeFromItem(empoignade) {
|
||||||
|
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||||
|
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||||
|
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) {
|
||||||
|
const dialog = await RdDRoll.create(attacker, rollData,
|
||||||
|
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
|
||||||
|
{
|
||||||
|
name: 'jet-empoignade',
|
||||||
|
label: 'Empoigner',
|
||||||
|
callbacks: [
|
||||||
|
{ 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async $onRollEmpoignade(rollData, isSuccess, isNouvelle = false) {
|
||||||
|
let attacker = game.actors.get(rollData.attackerId)
|
||||||
|
let defender = game.actors.get(rollData.defenderId)
|
||||||
|
|
||||||
|
let empoignade = rollData.empoignade
|
||||||
|
empoignade.isSuccess = isSuccess;
|
||||||
|
|
||||||
|
if (isSuccess && isNouvelle) {
|
||||||
|
// Creer l'empoignade sur attaquant/defenseur
|
||||||
|
await attacker.createEmbeddedDocuments('Item', [empoignade.toObject()])
|
||||||
|
await defender.createEmbeddedDocuments('Item', [empoignade.toObject()])
|
||||||
|
}
|
||||||
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-resultat.html');
|
||||||
|
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async onDefenseEmpoignade(rollData, defenseMode, competenceName = "Corps à corps", carac = "melee") {
|
||||||
|
let attacker = game.actors.get(rollData.attackerId)
|
||||||
|
let defender = game.actors.get(rollData.defenderId)
|
||||||
|
let empoignade = this.getEmpoignade(attacker, defender)
|
||||||
|
|
||||||
|
if (!empoignade) {
|
||||||
|
ui.notifications.warn("Une erreur s'est produite : Aucune empoignade trouvée !!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
empoignade = duplicate(empoignade)
|
||||||
|
rollData.mode = defenseMode
|
||||||
|
rollData.empoignade = empoignade
|
||||||
|
rollData.competence = defender.getCompetence(competenceName),
|
||||||
|
rollData.selectedCarac = defender.system.carac[carac],
|
||||||
|
rollData.malusTaille = RdDEmpoignade.getMalusTaille(empoignade, defender, attacker)
|
||||||
|
|
||||||
|
await RdDEmpoignade.$rollDefenseEmpoignade(defender, rollData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async $rollDefenseEmpoignade(defender, rollData) {
|
||||||
|
const dialog = await RdDRoll.create(defender, rollData,
|
||||||
|
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-empoignade.html' },
|
||||||
|
{
|
||||||
|
name: 'empoignade',
|
||||||
|
label: 'Contrer',
|
||||||
|
callbacks: [
|
||||||
|
{ action: async (r) => await RdDEmpoignade.$onRollContrerLiberer(r) }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
);
|
||||||
|
dialog.render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async $onRollContrerLiberer(rollData) {
|
||||||
|
let empoignade = rollData.empoignade
|
||||||
|
|
||||||
|
if (rollData.mode == "contrer-empoigner" && !rollData.rolled.isSuccess) {
|
||||||
|
empoignade.system.pointsemp++
|
||||||
|
RdDEmpoignade.$updateEtatEmpoignade(empoignade)
|
||||||
|
}
|
||||||
|
if (rollData.mode == "contrer-liberer" && !rollData.rolled.isSuccess) {
|
||||||
|
empoignade.system.pointsemp--
|
||||||
|
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')
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async $updateEtatEmpoignade(empoignade) {
|
||||||
|
console.log("UPDATE Empoignade", empoignade)
|
||||||
|
|
||||||
|
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||||
|
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
||||||
|
let update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
|
||||||
|
await defender.updateEmbeddedDocuments('Item', [update])
|
||||||
|
|
||||||
|
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
||||||
|
emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
|
||||||
|
update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
|
||||||
|
await attacker.updateEmbeddedDocuments('Item', [update])
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async $deleteEmpoignade(empoignade) {
|
||||||
|
console.log("DELETE Empoignade", empoignade)
|
||||||
|
|
||||||
|
let defender = game.actors.get(empoignade.system.empoigneid)
|
||||||
|
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
|
||||||
|
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) {
|
||||||
|
let attacker = game.actors.get(rollData.attackerId)
|
||||||
|
let defender = game.actors.get(rollData.defenderId)
|
||||||
|
let empoignade = this.getEmpoignade(attacker, defender)
|
||||||
|
|
||||||
|
empoignade.system.ausol = true
|
||||||
|
await this.$updateEtatEmpoignade(empoignade)
|
||||||
|
|
||||||
|
await attacker.setEffect(STATUSES.StatusProne, true);
|
||||||
|
await defender.setEffect(STATUSES.StatusProne, true);
|
||||||
|
|
||||||
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.html');
|
||||||
|
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async projeterAuSol(rollData) {
|
||||||
|
let attacker = game.actors.get(rollData.attackerId)
|
||||||
|
let defender = game.actors.get(rollData.defenderId)
|
||||||
|
let empoignade = this.getEmpoignade(attacker, defender)
|
||||||
|
|
||||||
|
await defender.setEffect(STATUSES.StatusProne, true);
|
||||||
|
await this.$deleteEmpoignade(empoignade)
|
||||||
|
|
||||||
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-projeter-sol.html');
|
||||||
|
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async perteEndurance(rollData, perteMode) {
|
||||||
|
let attacker = game.actors.get(rollData.attackerId)
|
||||||
|
let defender = game.actors.get(rollData.defenderId)
|
||||||
|
let empoignade = this.getEmpoignade(attacker, defender)
|
||||||
|
|
||||||
|
//console.log("Perte d'endurance :!!!", perteMode)
|
||||||
|
let endValue = defender.system.sante.endurance.value
|
||||||
|
if (perteMode == "end0") {
|
||||||
|
await defender.santeIncDec("endurance", -endValue);
|
||||||
|
}
|
||||||
|
if (perteMode == "end1") {
|
||||||
|
await defender.santeIncDec("endurance", -(endValue - 1));
|
||||||
|
}
|
||||||
|
if (perteMode == "endmoitie") {
|
||||||
|
await defender.santeIncDec("endurance", -Math.floor(endValue / 2));
|
||||||
|
}
|
||||||
|
if (perteMode == "endquart") {
|
||||||
|
await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4)));
|
||||||
|
}
|
||||||
|
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.html');
|
||||||
|
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async deleteAllEmpoignades() {
|
||||||
|
for (let actor of game.actors) {
|
||||||
|
let empIds = actor.itemTypes["empoignade"].map(it => it.id)
|
||||||
|
await actor.deleteEmbeddedDocuments('Item', empIds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async deleteLinkedEmpoignade(actorId, empoignade) {
|
||||||
|
let actorDeleteId = (actorId == empoignade.system.empoigneurid) ? empoignade.system.empoigneid : empoignade.system.empoigneurid
|
||||||
|
let actor = game.actors.get(actorDeleteId)
|
||||||
|
let emp = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
|
||||||
|
if (emp) {
|
||||||
|
await actor.deleteEmbeddedDocuments('Item', [emp._id])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async createEmpoignade(attacker, defender) {
|
||||||
|
return await Item.create({
|
||||||
|
name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name,
|
||||||
|
type: 'empoignade',
|
||||||
|
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
||||||
|
system: { description: "", empoignadeid: randomID(16), compteempoigne: 0, empoigneurid: attacker.id, empoigneid: defender.id, ptsemp: 0, empoigneurname: attacker.name, empoignename: defender.name }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
temporary: true
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
@@ -1,6 +1,6 @@
|
|||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDHerbes extends Item {
|
export class RdDHerbes extends Item {
|
||||||
|
@@ -1,16 +1,20 @@
|
|||||||
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
import { RdDActor } from "./actor.js";
|
import { Migrations } from './migrations.js';
|
||||||
import { RdDItem } from "./item.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 { RdDCalendrier } from "./rdd-calendrier.js";
|
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||||
|
import { RdDCalendrier } from "./time/rdd-calendrier.js";
|
||||||
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||||
|
import { DialogChronologie } from "./dialog-chronologie.js";
|
||||||
|
|
||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
import { RdDTokenHud } from "./rdd-token-hud.js";
|
import { RdDTokenHud } from "./rdd-token-hud.js";
|
||||||
import { RdDCommands } from "./rdd-commands.js";
|
import { RdDCommands } from "./rdd-commands.js";
|
||||||
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
|
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 { ReglesOptionelles } from "./settings/regles-optionelles.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";
|
||||||
@@ -18,37 +22,43 @@ import { RdDHerbes } from "./rdd-herbes.js";
|
|||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { RdDPossession } from "./rdd-possession.js";
|
import { RdDPossession } from "./rdd-possession.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { Migrations } from './migrations.js';
|
|
||||||
import { DialogChronologie } from "./dialog-chronologie.js";
|
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||||
import { Environnement } from "./environnement.js";
|
import { Environnement } from "./environnement.js";
|
||||||
import { RdDItemService } from "./item/item-service.js";
|
|
||||||
import { RdDBaseActor } from "./actor/base-actor.js";
|
|
||||||
import { RdDCommerceSheet } from "./actor/commerce-sheet.js";
|
|
||||||
import { RdDCommerce } from "./actor/commerce.js";
|
|
||||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
|
||||||
import { RdDItemMaladie } from "./item/maladie.js";
|
|
||||||
import { RdDItemPoison } from "./item/poison.js";
|
|
||||||
import { RdDItemSigneDraconique } from "./item/item-signedraconique.js";
|
|
||||||
import { RdDItemQueue } from "./item/queue.js";
|
|
||||||
import { RdDItemOmbre } from "./item/ombre.js";
|
|
||||||
import { RdDItemSouffle } from "./item/souffle.js";
|
|
||||||
import { RdDRencontre } from "./item/item-rencontre.js";
|
|
||||||
|
|
||||||
|
import { RdDActor } from "./actor.js";
|
||||||
|
import { RdDBaseActor } from "./actor/base-actor.js";
|
||||||
|
import { RdDCommerce } from "./actor/commerce.js";
|
||||||
import { RdDActorSheet } from "./actor-sheet.js";
|
import { RdDActorSheet } from "./actor-sheet.js";
|
||||||
|
import { RdDCommerceSheet } from "./actor/commerce-sheet.js";
|
||||||
import { RdDActorCreatureSheet } from "./actor-creature-sheet.js";
|
import { RdDActorCreatureSheet } from "./actor-creature-sheet.js";
|
||||||
import { RdDActorVehiculeSheet } from "./actor-vehicule-sheet.js";
|
import { RdDActorVehiculeSheet } from "./actor-vehicule-sheet.js";
|
||||||
import { RdDActorEntiteSheet } from "./actor-entite-sheet.js";
|
import { RdDActorEntiteSheet } from "./actor-entite-sheet.js";
|
||||||
import { RdDItemSheet } from "./item-sheet.js";
|
|
||||||
import { RdDServiceItemSheet } from "./item-service-sheet.js";
|
|
||||||
import { RdDHerbeItemSheet } from "./item-herbe-sheet.js";
|
|
||||||
import { RdDRencontreItemSheet } from "./item-rencontre-sheet.js";
|
|
||||||
import { RdDIngredientItemSheet } from "./item-ingredient-sheet.js";
|
|
||||||
import { RdDFauneItemSheet } from "./item-faune-sheet.js";
|
|
||||||
import { RdDConteneurItemSheet } from "./item-conteneur-sheet.js";
|
|
||||||
import { RdDSigneDraconiqueItemSheet } from "./item-signedraconique-sheet.js";
|
|
||||||
|
|
||||||
import { TMRRencontres } from "./tmr-rencontres.js";
|
import { RdDItem } from "./item.js";
|
||||||
|
import { RdDItemBlessure } from "./item/blessure.js";
|
||||||
|
import { RdDItemService } from "./item/service.js";
|
||||||
|
import { RdDItemMaladie } from "./item/maladie.js";
|
||||||
|
import { RdDItemPoison } from "./item/poison.js";
|
||||||
|
import { RdDItemSigneDraconique } from "./item/signedraconique.js";
|
||||||
|
import { RdDItemQueue } from "./item/queue.js";
|
||||||
|
import { RdDItemOmbre } from "./item/ombre.js";
|
||||||
|
import { RdDItemSouffle } from "./item/souffle.js";
|
||||||
|
import { RdDRencontre } from "./item/rencontre.js";
|
||||||
|
|
||||||
|
import { RdDItemSheet } from "./item-sheet.js";
|
||||||
|
import { RdDBlessureItemSheet } from "./item/sheet-blessure.js";
|
||||||
|
import { RdDServiceItemSheet } from "./item/sheet-service.js";
|
||||||
|
import { RdDRencontreItemSheet } from "./item/sheet-rencontre.js";
|
||||||
|
import { RdDHerbeItemSheet } from "./item/sheet-herbe.js";
|
||||||
|
import { RdDPlanteItemSheet } from "./item/sheet-plante.js";
|
||||||
|
import { RdDIngredientItemSheet } from "./item/sheet-ingredient.js";
|
||||||
|
import { RdDFauneItemSheet } from "./item/sheet-faune.js";
|
||||||
|
import { RdDConteneurItemSheet } from "./item/sheet-conteneur.js";
|
||||||
|
import { RdDSigneDraconiqueItemSheet } from "./item/sheet-signedraconique.js";
|
||||||
|
import { RdDItemInventaireSheet } from "./item/sheet-base-inventaire.js";
|
||||||
|
import { AppAstrologie } from "./sommeil/app-astrologie.js";
|
||||||
|
import { RdDItemArmure } from "./item/armure.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* RdD system
|
* RdD system
|
||||||
@@ -67,21 +77,23 @@ export class SystemReveDeDragon {
|
|||||||
this.RdDUtility = RdDUtility;
|
this.RdDUtility = RdDUtility;
|
||||||
this.RdDHotbar = RdDHotbar;
|
this.RdDHotbar = RdDHotbar;
|
||||||
this.itemClasses = {
|
this.itemClasses = {
|
||||||
service: RdDItemService,
|
armure: RdDItemArmure,
|
||||||
|
blessure: RdDItemBlessure,
|
||||||
maladie: RdDItemMaladie,
|
maladie: RdDItemMaladie,
|
||||||
|
ombre: RdDItemOmbre,
|
||||||
poison: RdDItemPoison,
|
poison: RdDItemPoison,
|
||||||
queue: RdDItemQueue,
|
queue: RdDItemQueue,
|
||||||
ombre: RdDItemOmbre,
|
rencontre: RdDRencontre,
|
||||||
souffle: RdDItemSouffle,
|
service: RdDItemService,
|
||||||
signedraconique: RdDItemSigneDraconique,
|
signedraconique: RdDItemSigneDraconique,
|
||||||
rencontre: RdDRencontre
|
souffle: RdDItemSouffle,
|
||||||
}
|
}
|
||||||
this.actorClasses = {
|
this.actorClasses = {
|
||||||
|
commerce: RdDCommerce,
|
||||||
creature: RdDActor,
|
creature: RdDActor,
|
||||||
entite: RdDActor,
|
entite: RdDActor,
|
||||||
personnage: RdDActor,
|
personnage: RdDActor,
|
||||||
vehicule: RdDActor,
|
vehicule: RdDActor,
|
||||||
commerce: RdDCommerce,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +102,8 @@ export class SystemReveDeDragon {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onInit() {
|
async onInit() {
|
||||||
game.system.rdd = this;
|
game.system.rdd = this;
|
||||||
|
this.AppAstrologie = AppAstrologie;
|
||||||
|
|
||||||
|
|
||||||
console.log(`Initializing Reve de Dragon System`);
|
console.log(`Initializing Reve de Dragon System`);
|
||||||
|
|
||||||
@@ -145,35 +159,41 @@ export class SystemReveDeDragon {
|
|||||||
RdDItemSheet.register(RdDConteneurItemSheet);
|
RdDItemSheet.register(RdDConteneurItemSheet);
|
||||||
RdDItemSheet.register(RdDHerbeItemSheet);
|
RdDItemSheet.register(RdDHerbeItemSheet);
|
||||||
RdDItemSheet.register(RdDFauneItemSheet);
|
RdDItemSheet.register(RdDFauneItemSheet);
|
||||||
|
RdDItemSheet.register(RdDPlanteItemSheet);
|
||||||
RdDItemSheet.register(RdDIngredientItemSheet);
|
RdDItemSheet.register(RdDIngredientItemSheet);
|
||||||
RdDItemSheet.register(RdDServiceItemSheet);
|
RdDItemSheet.register(RdDServiceItemSheet);
|
||||||
|
RdDItemSheet.register(RdDBlessureItemSheet);
|
||||||
|
|
||||||
|
Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, {
|
||||||
|
types: [
|
||||||
|
"objet", "arme", "armure", "livre", "potion", "munition",
|
||||||
|
"monnaie", "nourritureboisson", "gemme",
|
||||||
|
], makeDefault: true
|
||||||
|
});
|
||||||
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
|
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
|
||||||
types: [
|
types: [
|
||||||
"competence", "competencecreature",
|
"competence", "competencecreature",
|
||||||
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
|
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
|
||||||
"objet", "arme", "armure", "livre", "potion", "munition",
|
|
||||||
"monnaie", "nourritureboisson", "gemme",
|
|
||||||
"meditation", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
|
"meditation", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
|
||||||
"nombreastral", "tache", "maladie", "poison", "possession",
|
"nombreastral", "tache", "maladie", "poison", "possession",
|
||||||
"tarot", "extraitpoetique"
|
"tarot", "extraitpoetique", "empoignade"
|
||||||
], makeDefault: true
|
], makeDefault: true
|
||||||
});
|
});
|
||||||
CONFIG.Combat.documentClass = RdDCombatManager;
|
CONFIG.Combat.documentClass = RdDCombatManager;
|
||||||
|
|
||||||
// préparation des différents modules
|
// préparation des différents modules
|
||||||
RdDTimestamp.init();
|
RdDTimestamp.init();
|
||||||
|
RdDCalendrier.init();
|
||||||
SystemCompendiums.init();
|
SystemCompendiums.init();
|
||||||
DialogChronologie.init();
|
DialogChronologie.init();
|
||||||
ReglesOptionelles.init();
|
ReglesOptionelles.init();
|
||||||
RdDUtility.init();
|
RdDUtility.init();
|
||||||
RdDDice.init();
|
RdDDice.init();
|
||||||
RdDCommands.init();
|
RdDCommands.init();
|
||||||
RdDCombat.init();
|
|
||||||
RdDCombatManager.init();
|
RdDCombatManager.init();
|
||||||
RdDTokenHud.init();
|
RdDTokenHud.init();
|
||||||
RdDBaseActor.init();
|
RdDBaseActor.init();
|
||||||
RddCompendiumOrganiser.init();
|
RdDCompendiumOrganiser.init();
|
||||||
EffetsDraconiques.init()
|
EffetsDraconiques.init()
|
||||||
TMRUtility.init();
|
TMRUtility.init();
|
||||||
RdDHotbar.initDropbar();
|
RdDHotbar.initDropbar();
|
||||||
@@ -199,25 +219,6 @@ export class SystemReveDeDragon {
|
|||||||
default: "avant-encaissement"
|
default: "avant-encaissement"
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
game.settings.register(SYSTEM_RDD, "liste-nombre-astral", {
|
|
||||||
name: "liste-nombre-astral",
|
|
||||||
scope: "world",
|
|
||||||
config: false,
|
|
||||||
default: [],
|
|
||||||
type: Object
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
game.settings.register(SYSTEM_RDD, "calendrier-pos", {
|
|
||||||
name: "calendrierPos",
|
|
||||||
scope: "client",
|
|
||||||
config: false,
|
|
||||||
default: RdDCalendrier.createCalendrierPos(),
|
|
||||||
type: Object
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", {
|
game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", {
|
||||||
name: "Supprimer les dialogues de combat",
|
name: "Supprimer les dialogues de combat",
|
||||||
@@ -263,9 +264,11 @@ export class SystemReveDeDragon {
|
|||||||
let sidebar = document.getElementById("sidebar");
|
let sidebar = document.getElementById("sidebar");
|
||||||
sidebar.style.width = "min-content";
|
sidebar.style.width = "min-content";
|
||||||
}
|
}
|
||||||
|
game.system.rdd.calendrier = new RdDCalendrier();
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
new Migrations().migrate();
|
new Migrations().migrate();
|
||||||
|
this.messageDeBienvenue();
|
||||||
|
this.registerUsageCount(SYSTEM_RDD);
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusEffects.onReady();
|
StatusEffects.onReady();
|
||||||
@@ -273,14 +276,7 @@ export class SystemReveDeDragon {
|
|||||||
RdDDice.onReady();
|
RdDDice.onReady();
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Affiche/Init le calendrier */
|
/* Affiche/Init le calendrier */
|
||||||
let calendrier = new RdDCalendrier();
|
game.system.rdd.calendrier.display();
|
||||||
let templatePath = "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html";
|
|
||||||
let templateData = {};
|
|
||||||
renderTemplate(templatePath, templateData).then(html => {
|
|
||||||
calendrier.render(true);
|
|
||||||
});
|
|
||||||
game.system.rdd.calendrier = calendrier; // Reference;
|
|
||||||
|
|
||||||
// Avertissement si joueur sans personnage
|
// Avertissement si joueur sans personnage
|
||||||
if (!game.user.isGM && game.user.character == undefined) {
|
if (!game.user.isGM && game.user.character == undefined) {
|
||||||
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !");
|
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !");
|
||||||
@@ -289,10 +285,6 @@ export class SystemReveDeDragon {
|
|||||||
user: game.user.id
|
user: game.user.id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
|
||||||
this.messageDeBienvenue();
|
|
||||||
this.registerUsageCount(SYSTEM_RDD);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@@ -195,17 +195,6 @@ export class RdDResolutionTable {
|
|||||||
return Math.max(Math.floor(carac * (diff + 10) / 2), 1);
|
return Math.max(Math.floor(carac * (diff + 10) / 2), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static isAjustementAstrologique(rollData) {
|
|
||||||
if (rollData.selectedCarac?.label.toLowerCase().includes('chance')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (rollData.selectedSort?.system.isrituel) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isEchec(rollData) {
|
static isEchec(rollData) {
|
||||||
switch (rollData.surprise) {
|
switch (rollData.surprise) {
|
||||||
@@ -294,12 +283,9 @@ export class RdDResolutionTable {
|
|||||||
carac: carac,
|
carac: carac,
|
||||||
difficulte: level,
|
difficulte: level,
|
||||||
min: minLevel,
|
min: minLevel,
|
||||||
rows: RdDResolutionTable.incrementalArray(minCarac, maxCarac),
|
rows: Misc.intArray(minCarac, maxCarac+1),
|
||||||
cols: RdDResolutionTable.incrementalArray(minLevel, maxLevel)
|
cols: Misc.intArray(minLevel, maxLevel+1)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
static incrementalArray(min, max) {
|
|
||||||
return Array.from(Array(max-min+1).keys()).map(i=>i+min)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@@ -30,9 +30,9 @@ export class RdDEncaisser extends Dialog {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (actor.isEntite([ENTITE_BLURETTE, ENTITE_INCARNE])) {
|
else if (actor.isEntite([ENTITE_BLURETTE, ENTITE_INCARNE])) {
|
||||||
dialogConf.default = "cauchemar"
|
dialogConf.default = "entiteincarnee"
|
||||||
dialogConf.buttons = {
|
dialogConf.buttons = {
|
||||||
"cauchemar": { label: "Cauchemar", callback: html => this.performEncaisser("cauchemar") }
|
"entiteincarnee": { label: "Entité incarnée", callback: html => this.performEncaisser("entiteincarnee") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,6 @@ export class RdDEncaisser extends Dialog {
|
|||||||
total: Number(this.modifier),
|
total: Number(this.modifier),
|
||||||
ajustement: Number(this.modifier),
|
ajustement: Number(this.modifier),
|
||||||
encaisserSpecial: this.encaisserSpecial,
|
encaisserSpecial: this.encaisserSpecial,
|
||||||
loc: { result: 0, label: "" },
|
|
||||||
mortalite: mortalite
|
mortalite: mortalite
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@@ -276,11 +276,11 @@ export class RdDRoll extends Dialog {
|
|||||||
const diffVariable = RdDItemSort.isDifficulteVariable(sort);
|
const diffVariable = RdDItemSort.isDifficulteVariable(sort);
|
||||||
const coutVariable = RdDItemSort.isCoutVariable(sort);
|
const coutVariable = RdDItemSort.isCoutVariable(sort);
|
||||||
|
|
||||||
HtmlUtility._showControlWhen(this.html.find(".div-sort-non-rituel"), !sort.system.isrituel);
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-non-rituel"), !sort.system.isrituel);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".div-sort-difficulte-var"), diffVariable);
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-difficulte-var"), diffVariable);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".div-sort-difficulte-fixe"), !diffVariable);
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-difficulte-fixe"), !diffVariable);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".div-sort-ptreve-var"), coutVariable);
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-ptreve-var"), coutVariable);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".div-sort-ptreve-fixe"), !coutVariable);
|
HtmlUtility.showControlWhen(this.html.find(".div-sort-ptreve-fixe"), !coutVariable);
|
||||||
}
|
}
|
||||||
|
|
||||||
async setSelectedSigneDraconique(signe) {
|
async setSelectedSigneDraconique(signe) {
|
||||||
@@ -311,11 +311,11 @@ export class RdDRoll extends Dialog {
|
|||||||
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);
|
||||||
|
|
||||||
HtmlUtility._showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerivee(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(".diffMoral"), rollData.ajustements.moralTotal.used);
|
||||||
HtmlUtility._showControlWhen(this.html.find(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
HtmlUtility.showControlWhen(this.html.find(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
||||||
|
|
||||||
// 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));
|
||||||
|
@@ -1,9 +1,25 @@
|
|||||||
import { DialogSplitItem } from "./dialog-split-item.js";
|
import { DialogSplitItem } from "./dialog-split-item.js";
|
||||||
import { RdDItem } from "./item.js";
|
import { RdDItem } from "./item.js";
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
|
||||||
|
|
||||||
export class RdDSheetUtility {
|
export class RdDSheetUtility {
|
||||||
|
|
||||||
|
static mergeDocumentRights(options, document, editable) {
|
||||||
|
const userRightLevel = game.user.isGM
|
||||||
|
? CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
|
||||||
|
: document.getUserLevel(game.user);
|
||||||
|
let newOptions = {
|
||||||
|
isGM: game.user.isGM,
|
||||||
|
isOwned: document.parent ? true : false,
|
||||||
|
editable: editable,
|
||||||
|
cssClass: editable ? "editable" : "locked",
|
||||||
|
isLimited: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.LIMITED,
|
||||||
|
isObserver: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER,
|
||||||
|
isOwner: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
|
||||||
|
}
|
||||||
|
mergeObject(options, newOptions);
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
|
||||||
static getItem(event, actor) {
|
static getItem(event, actor) {
|
||||||
return actor.items.get(RdDSheetUtility.getItemId(event))
|
return actor.items.get(RdDSheetUtility.getItemId(event))
|
||||||
}
|
}
|
||||||
|
@@ -15,9 +15,8 @@ import { HtmlUtility } from "./html-utility.js";
|
|||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./settings/regles-optionelles.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/item-rencontre.js";
|
import { RdDRencontre } from "./item/rencontre.js";
|
||||||
import { RdDCalendrier } from "./rdd-calendrier.js";
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
@@ -208,8 +207,8 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
HtmlUtility._showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
|
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionelles.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
|
// Roll Sort
|
||||||
this.html.find('.lancer-sort').click((event) => {
|
this.html.find('.lancer-sort').click((event) => {
|
||||||
@@ -246,7 +245,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
const coord = this._getActorCoord();
|
const coord = this._getActorCoord();
|
||||||
|
|
||||||
HtmlUtility._showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
|
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
|
||||||
|
|
||||||
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
||||||
ptsreve.innerHTML = this.actor.system.reve.reve.value;
|
ptsreve.innerHTML = this.actor.system.reve.reve.value;
|
||||||
@@ -285,7 +284,12 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onActionRencontre(action, tmr) {
|
async onActionRencontre(action, tmr, rencontre) {
|
||||||
|
if (!this.currentRencontre) {
|
||||||
|
ui.notifications.warn("#612 Rencontre perdue, récupération en cours. Vous pouvez contacter l'équipe avec les logs pour aider à résoudre ce problème")
|
||||||
|
console.error("#612 Rencontre perdue", action, tmr, rencontre, this);
|
||||||
|
this.currentRencontre = rencontre;
|
||||||
|
}
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case 'derober':
|
case 'derober':
|
||||||
await this.derober();
|
await this.derober();
|
||||||
@@ -589,6 +593,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
|
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
|
||||||
} else {
|
} else {
|
||||||
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
|
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,19 +804,21 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async declencheSortEnReserve(coord) {
|
async declencheSortEnReserve(coord) {
|
||||||
let sorts = this.getSortsReserve(coord);
|
const sorts = this.getSortsReserve(coord);
|
||||||
if (sorts.length > 0) {
|
if (sorts.length > 0) {
|
||||||
if (EffetsDraconiques.isSortReserveImpossible(this.actor)) {
|
if (EffetsDraconiques.isSortReserveImpossible(this.actor)) {
|
||||||
ui.notifications.error("Une queue ou un souffle vous empèche de déclencher de sort!");
|
ui.notifications.error("Une queue ou un souffle vous empèche de déclencher de sort!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) &&
|
const reserveSecurite = EffetsDraconiques.isReserveEnSecurite(this.actor);
|
||||||
(EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord))) {
|
const reserveExtensible = this.isReserveExtensible(coord);
|
||||||
let msg = "Vous êtes sur une case avec un Sort en Réserve. Grâce à votre Tête <strong>Reserve en Sécurité</strong> ou <strong>Réserve Exensible</strong>, vous pouvez contrôler le déclenchement. Cliquez si vous souhaitez le déclencher : <ul>";
|
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) && (reserveSecurite || reserveExtensible)) {
|
||||||
for (let sort of sorts) {
|
const msg = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-demande-declencher-sort.hbs`, {
|
||||||
msg += `<li><a class="chat-card-button declencher-sort-reserve" data-actor-id="${this.actor.id}" data-tmr-coord="${coord}" data-sort-id='${sort.id}">${sort.name}</a></li>`;
|
actor: this.actor,
|
||||||
}
|
sorts: sorts,
|
||||||
msg += "</ol>";
|
coord: coord,
|
||||||
|
tete: { reserveSecurite: reserveSecurite, reserveExtensible: reserveExtensible }
|
||||||
|
})
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
content: msg,
|
content: msg,
|
||||||
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
whisper: ChatMessage.getWhisperRecipients(game.user.name)
|
||||||
@@ -1045,6 +1052,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _computeEventOddq(origEvent) {
|
static _computeEventOddq(origEvent) {
|
||||||
|
console.log("EVENT", origEvent)
|
||||||
let canvasRect = origEvent.target.getBoundingClientRect();
|
let canvasRect = origEvent.target.getBoundingClientRect();
|
||||||
let x = origEvent.clientX - canvasRect.left;
|
let x = origEvent.clientX - canvasRect.left;
|
||||||
let y = origEvent.clientY - canvasRect.top;
|
let y = origEvent.clientY - canvasRect.top;
|
||||||
|
@@ -29,12 +29,13 @@ export class RdDTMRRencontreDialog extends Dialog {
|
|||||||
this.toClose = false;
|
this.toClose = false;
|
||||||
this.tmr = tmr;
|
this.tmr = tmr;
|
||||||
this.tmrApp = tmrApp;
|
this.tmrApp = tmrApp;
|
||||||
|
this.rencontre = rencontre;
|
||||||
this.tmrApp.minimize();
|
this.tmrApp.minimize();
|
||||||
}
|
}
|
||||||
|
|
||||||
async onButtonAction(action) {
|
async onButtonAction(action) {
|
||||||
this.toClose = true;
|
this.toClose = true;
|
||||||
this.tmrApp.onActionRencontre(action, this.tmr)
|
this.tmrApp.onActionRencontre(action, this.tmr, this.rencontre)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@@ -2,6 +2,7 @@
|
|||||||
import { HtmlUtility } from "./html-utility.js";
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
import { RdDCombatManager } from "./rdd-combat.js";
|
||||||
|
import { Targets } from "./targets.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDTokenHud {
|
export class RdDTokenHud {
|
||||||
@@ -18,29 +19,39 @@ export class RdDTokenHud {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async addExtensionHud(app, html, tokenId) {
|
static async addExtensionHud(app, html, tokenId, isCombat) {
|
||||||
|
|
||||||
let token = canvas.tokens.get(tokenId);
|
let token = canvas.tokens.get(tokenId);
|
||||||
let actor = token.actor;
|
let actor = token.actor;
|
||||||
|
app.hasExtension = true;
|
||||||
|
// soins
|
||||||
|
await RdDTokenHud.addExtensionHudSoins(html, actor);
|
||||||
|
|
||||||
|
if (isCombat) {
|
||||||
let combatant = game.combat.combatants.find(c => c.tokenId == tokenId);
|
let combatant = game.combat.combatants.find(c => c.tokenId == tokenId);
|
||||||
if (!(combatant?.actor)) {
|
if (!(combatant?.actor)) {
|
||||||
ui.notifications.warn(`Le combatant ${token.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
|
ui.notifications.warn(`Le combatant ${token.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
app.hasExtension = true;
|
let actions = RdDCombatManager.listActionsCombat(combatant);
|
||||||
|
// initiative
|
||||||
|
await RdDTokenHud.addExtensionHudInit(html, combatant, actions);
|
||||||
|
// combat
|
||||||
|
await RdDTokenHud.addExtensionHudCombat(html, combatant, actions);
|
||||||
|
}
|
||||||
|
|
||||||
let actionsCombat = RdDCombatManager.listActionsCombat(combatant);
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static async addExtensionHudInit(html, combatant, actions) {
|
||||||
const hudData = {
|
const hudData = {
|
||||||
combatant: combatant,
|
combatant, actions,
|
||||||
actions: actionsCombat,
|
|
||||||
commandes: [
|
commandes: [
|
||||||
{ name: "Autre action", command: 'autre' },
|
{ name: "Autre action", command: 'autre' },
|
||||||
{ name: 'Initiative +1', command: 'inc', value: 0.01 },
|
{ name: 'Initiative +1', command: 'inc', value: 0.01 },
|
||||||
{ name: 'Initiative -1', command: 'dec', value: -0.01 }]
|
{ name: 'Initiative -1', command: 'dec', value: -0.01 }]
|
||||||
};
|
};
|
||||||
|
|
||||||
const controlIconCombat = html.find('.control-icon[data-action=combat]');
|
const controlIconCombat = html.find('.control-icon[data-action=combat]');
|
||||||
// initiative
|
|
||||||
await RdDTokenHud._configureSubMenu(controlIconCombat,
|
await RdDTokenHud._configureSubMenu(controlIconCombat,
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
|
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
|
||||||
hudData,
|
hudData,
|
||||||
@@ -51,26 +62,47 @@ export class RdDTokenHud {
|
|||||||
RdDTokenHud._initiativeCommand(initCommand, combatantId);
|
RdDTokenHud._initiativeCommand(initCommand, combatantId);
|
||||||
} else {
|
} else {
|
||||||
let index = event.currentTarget.attributes['data-action-index'].value;
|
let index = event.currentTarget.attributes['data-action-index'].value;
|
||||||
let action = actionsCombat[index];
|
let action = hudData.actions[index];
|
||||||
RdDCombatManager.rollInitiativeAction(combatantId, action);
|
RdDCombatManager.rollInitiativeAction(combatantId, action);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static async addExtensionHudCombat(html, combatant, actions) {
|
||||||
|
const hudData = { combatant, actions, commandes: [] };
|
||||||
const controlIconTarget = html.find('.control-icon[data-action=target]');
|
const controlIconTarget = html.find('.control-icon[data-action=target]');
|
||||||
// combat
|
|
||||||
await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData,
|
await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData,
|
||||||
(event) => {
|
(event) => {
|
||||||
const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
|
const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
|
||||||
const action = actionsCombat[actionIndex];
|
const action = hudData.actions[actionIndex];
|
||||||
if (action.action == 'conjurer') {
|
if (action.action == 'conjurer') {
|
||||||
actor.conjurerPossession(actor.getPossession(action.system.possessionid));
|
const possession = combatant.actor.getPossession(action.system.possessionid);
|
||||||
|
combatant.actor.conjurerPossession(possession);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
actor.rollArme(action);
|
combatant.actor.rollArme(action);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async addExtensionHudSoins(html, sourceActor) {
|
||||||
|
const target = Targets.getTarget({ warn: false });
|
||||||
|
if (target?.actor) {
|
||||||
|
const hudSoins = { blessures: target.actor.blessuresASoigner() ?? [] };
|
||||||
|
if (hudSoins.blessures.length > 0) {
|
||||||
|
// soins
|
||||||
|
const controlIconTarget = html.find('.control-icon[data-action=combat]');
|
||||||
|
await RdDTokenHud._configureSubMenu(controlIconTarget,
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-soins.hbs',
|
||||||
|
hudSoins,
|
||||||
|
(event) => {
|
||||||
|
const blessureId = event.currentTarget.attributes['data-blessure-id']?.value;
|
||||||
|
sourceActor.rollSoins(target.actor, blessureId)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static _initiativeCommand(initCommand, combatantId) {
|
static _initiativeCommand(initCommand, combatantId) {
|
||||||
switch (initCommand) {
|
switch (initCommand) {
|
||||||
case 'inc': return RdDCombatManager.incDecInit(combatantId, 0.01);
|
case 'inc': return RdDCombatManager.incDecInit(combatantId, 0.01);
|
||||||
@@ -83,16 +115,17 @@ export class RdDTokenHud {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async addTokenHudExtensions(app, html, tokenId) {
|
static async addTokenHudExtensions(app, html, tokenId) {
|
||||||
const controlIconCombat = html.find('.control-icon[data-action=combat]');
|
const controlIconCombat = html.find('.control-icon[data-action=combat]');
|
||||||
|
if (controlIconCombat.length > 0) {
|
||||||
controlIconCombat.click(event => {
|
controlIconCombat.click(event => {
|
||||||
if (event.currentTarget.className.includes('active')) {
|
if (event.currentTarget.className.includes('active')) {
|
||||||
RdDTokenHud.removeExtensionHud(app, html, tokenId);
|
RdDTokenHud.removeExtensionHud(app, html, tokenId);
|
||||||
} else {
|
} else {
|
||||||
setTimeout(function () { RdDTokenHud.addExtensionHud(app, html, tokenId) }, 200);
|
setTimeout(() => RdDTokenHud.addExtensionHud(app, html, tokenId), 200);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (controlIconCombat.length>0 && controlIconCombat[0].className.includes('active')) {
|
const isCombat = controlIconCombat[0].className.includes('active');
|
||||||
RdDTokenHud.addExtensionHud(app, html, tokenId);
|
RdDTokenHud.addExtensionHud(app, html, tokenId, isCombat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,6 +144,6 @@ export class RdDTokenHud {
|
|||||||
|
|
||||||
static _toggleHudListActive(hud, list) {
|
static _toggleHudListActive(hud, list) {
|
||||||
hud.toggleClass('active');
|
hud.toggleClass('active');
|
||||||
HtmlUtility._showControlWhen(list, hud.hasClass('active'));
|
HtmlUtility.showControlWhen(list, hud.hasClass('active'));
|
||||||
}
|
}
|
||||||
}
|
}
|
@@ -8,21 +8,22 @@ import { DialogItemAchat } from "./dialog-item-achat.js";
|
|||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { RdDItem } from "./item.js";
|
import { RdDItem } from "./item.js";
|
||||||
import { Monnaie } from "./item-monnaie.js";
|
|
||||||
import { RdDPossession } from "./rdd-possession.js";
|
import { RdDPossession } from "./rdd-possession.js";
|
||||||
import { RdDNameGen } from "./rdd-namegen.js";
|
import { RdDNameGen } from "./rdd-namegen.js";
|
||||||
import { RdDConfirm } from "./rdd-confirm.js";
|
import { RdDConfirm } from "./rdd-confirm.js";
|
||||||
import { Environnement } from "./environnement.js";
|
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
import { RdDTimestamp } from "./rdd-timestamp.js";
|
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
||||||
|
import { RdDRaretes } from "./item/raretes.js";
|
||||||
|
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
||||||
|
import { ExperienceLog } from "./actor/experience-log.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// This table starts at 0 -> niveau -10
|
// This table starts at 0 -> niveau -10
|
||||||
const carac_array = ["taille", "apparence", "constitution", "force", "agilite", "dexterite", "vue", "ouie", "odoratgout", "volonte", "intellect", "empathie", "reve", "chance", "melee", "tir", "lancer", "derobee"];
|
const carac_array = ["taille", "apparence", "constitution", "force", "agilite", "dexterite", "vue", "ouie", "odoratgout", "volonte", "intellect", "empathie", "reve", "chance", "melee", "tir", "lancer", "derobee"];
|
||||||
const difficultesLibres = [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10];
|
const difficultesLibres = Misc.intArray(0, -11);
|
||||||
const ajustementsConditions = [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10];
|
const ajustementsConditions = Misc.intArray(-10, 11);
|
||||||
const ajustementsEncaissement = [-10, -9, -8, -7, -6, -5, -4, -3, -2, -1, 0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10, +11, +12, +13, +14, +15, +16, +17, +18, +19, +20, +21, +22, +23, +24, +25];
|
const ajustementsEncaissement = Misc.intArray(-10, 26);
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
function _buildAllSegmentsFatigue(max) {
|
function _buildAllSegmentsFatigue(max) {
|
||||||
@@ -67,38 +68,31 @@ const fatigueMarche = {
|
|||||||
"tresdifficile": { "4": 4, "6": 6 }
|
"tresdifficile": { "4": 4, "6": 6 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
const definitionsBlessures = [
|
|
||||||
{ type: "legere", facteur: 2 },
|
|
||||||
{ type: "grave", facteur: 4 },
|
|
||||||
{ type: "critique", facteur: 6 }
|
|
||||||
]
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "Complètement fait", "Ivre mort"];
|
const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "Complètement fait", "Ivre mort"];
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const definitionsEncaissement = {
|
const definitionsEncaissement = {
|
||||||
"mortel": [
|
"mortel": [
|
||||||
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 },
|
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1},
|
||||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0},
|
||||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 },
|
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2},
|
||||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", eraflures: 0, legeres: 0, graves: 1, critiques: 0 },
|
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4},
|
||||||
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", eraflures: 0, legeres: 0, graves: 0, critiques: 1 },
|
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6},
|
||||||
],
|
],
|
||||||
"non-mortel": [
|
"non-mortel": [
|
||||||
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 },
|
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1},
|
||||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
|
||||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
|
||||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 },
|
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 },
|
||||||
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 },
|
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 },
|
||||||
],
|
],
|
||||||
"cauchemar": [
|
"entiteincarnee": [
|
||||||
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 },
|
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1},
|
||||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0},
|
||||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
|
||||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 0 },
|
||||||
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 0 },
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -140,9 +134,10 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/combat.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/combat.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/blessures.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/blessures.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/blessure.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/blessure.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/possessions.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/possessions.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/actor/resonances.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.html',
|
||||||
@@ -150,6 +145,7 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/jeux.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/jeux.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html',
|
||||||
@@ -202,6 +198,8 @@ export class RdDUtility {
|
|||||||
'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-tmr-effet.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html',
|
||||||
// Partials
|
// Partials
|
||||||
|
'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/common/timestamp.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
|
||||||
@@ -233,10 +231,10 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.html',
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html',
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html',
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html',
|
'systems/foundryvtt-reve-de-dragon/templates/sommeil/sommeil-actor-moral.hbs',
|
||||||
// Calendrier
|
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-gardien.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/calendar-template.html',
|
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-joueur.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html',
|
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-theme.hbs',
|
||||||
// HUD
|
// HUD
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
|
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html',
|
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html',
|
||||||
@@ -245,20 +243,6 @@ 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-demande-defense.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-appelchance.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-attaque.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-parade.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-esquive.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-competence.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-general.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-tache.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-sort.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-alchimie.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-possession.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html',
|
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html',
|
||||||
'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',
|
||||||
@@ -272,13 +256,15 @@ export class RdDUtility {
|
|||||||
Handlebars.registerHelper('computeResolutionChances', (row, col) => RdDResolutionTable.computeChances(row, col));
|
Handlebars.registerHelper('computeResolutionChances', (row, col) => RdDResolutionTable.computeChances(row, col));
|
||||||
Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null'));
|
Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null'));
|
||||||
Handlebars.registerHelper('lowerFirst', str => Misc.lowerFirst(str ?? 'Null'));
|
Handlebars.registerHelper('lowerFirst', str => Misc.lowerFirst(str ?? 'Null'));
|
||||||
Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? 'NULL');
|
Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? '');
|
||||||
|
Handlebars.registerHelper('lowercase', str => str?.toLowerCase() ?? '');
|
||||||
Handlebars.registerHelper('le', str => Grammar.articleDetermine(str));
|
Handlebars.registerHelper('le', str => Grammar.articleDetermine(str));
|
||||||
Handlebars.registerHelper('apostrophe', (article, str) => Grammar.apostrophe(article, str));
|
Handlebars.registerHelper('apostrophe', (article, str) => Grammar.apostrophe(article, str));
|
||||||
Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str));
|
Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str));
|
||||||
Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args));
|
Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args));
|
||||||
Handlebars.registerHelper('buildConteneur', (objet, templateItem, options) => { return new Handlebars.SafeString(RdDUtility.buildConteneur(objet, 1, templateItem, options)); });
|
Handlebars.registerHelper('buildLigneInventaire', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildLigneInventaire(item, options)); });
|
||||||
Handlebars.registerHelper('buildContenu', (objet) => { return new Handlebars.SafeString(RdDUtility.buildContenu(objet, 1, true)); });
|
Handlebars.registerHelper('buildInventaireConteneur', (actorId, itemId, options) => { return new Handlebars.SafeString(RdDUtility.buildInventaireConteneur(actorId, itemId, options)); });
|
||||||
|
Handlebars.registerHelper('buildContenuConteneur', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildContenuConteneur(item, options)); });
|
||||||
Handlebars.registerHelper('calculerPrixCommercant', item => item.calculerPrixCommercant());
|
Handlebars.registerHelper('calculerPrixCommercant', item => item.calculerPrixCommercant());
|
||||||
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
|
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
|
||||||
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
|
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
|
||||||
@@ -298,7 +284,10 @@ export class RdDUtility {
|
|||||||
Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name));
|
Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name));
|
||||||
Handlebars.registerHelper('uniteQuantite', (itemId, actorId) => RdDUtility.getItem(itemId, actorId)?.getUniteQuantite());
|
Handlebars.registerHelper('uniteQuantite', (itemId, actorId) => RdDUtility.getItem(itemId, actorId)?.getUniteQuantite());
|
||||||
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
|
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
|
||||||
Handlebars.registerHelper('getFrequenceRarete', (rarete, field) => Environnement.getFrequenceRarete(rarete, field));
|
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
|
||||||
|
|
||||||
|
Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic));
|
||||||
|
|
||||||
return loadTemplates(templatePaths);
|
return loadTemplates(templatePaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -393,40 +382,64 @@ export class RdDUtility {
|
|||||||
return conteneurs.filter((conteneur, index, arr) => !conteneur.estContenu);
|
return conteneurs.filter((conteneur, index, arr) => !conteneur.estContenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static prepareOptionsArbreInventaire(item, optionsArbre) {
|
||||||
|
if (!optionsArbre.profondeur) {
|
||||||
|
optionsArbre.profondeur = 1
|
||||||
|
};
|
||||||
|
if (!optionsArbre.templateItem) {
|
||||||
|
optionsArbre.templateItem = item.parent?.type == 'commerce'
|
||||||
|
? "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.html"
|
||||||
|
: "systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html";
|
||||||
|
}
|
||||||
|
item.niveau = optionsArbre.profondeur;
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/** Construit la structure récursive des conteneurs, avec imbrication potentielle
|
|
||||||
*
|
/**
|
||||||
|
* Construit la structure récursive des conteneurs, avec imbrication potentielle
|
||||||
*/
|
*/
|
||||||
static buildConteneur(objet, profondeur, templateItem, options) {
|
static buildLigneInventaire(item, options = {}, optionsArbre = { ouvert: false, profondeur: 1 }) {
|
||||||
if (!profondeur) profondeur = 1;
|
RdDUtility.prepareOptionsArbreInventaire(item, optionsArbre);
|
||||||
if (!templateItem) templateItem = 'actor/inventaire-item.html'
|
|
||||||
objet.niveau = profondeur;
|
|
||||||
|
|
||||||
const isConteneur = objet.type == 'conteneur';
|
const isConteneur = item.type == 'conteneur';
|
||||||
const isOuvert = isConteneur && this.getAfficheContenu(objet._id);
|
const inventaire = {
|
||||||
const isVide = isConteneur && objet.system.contenu.length == 0;
|
item: item,
|
||||||
const conteneur = Handlebars.partials[`systems/foundryvtt-reve-de-dragon/templates/${templateItem}`]({
|
vide: isConteneur && item.system.contenu.length == 0,
|
||||||
item: objet,
|
ouvert: isConteneur && RdDUtility.getAfficheContenu(item._id),
|
||||||
vide: isVide,
|
|
||||||
ouvert: isOuvert,
|
|
||||||
options: options
|
options: options
|
||||||
});
|
};
|
||||||
const contenu = isConteneur ? RdDUtility.buildContenu(objet, profondeur, isOuvert, templateItem, options) : '';
|
optionsArbre.ouvert = inventaire.ouvert
|
||||||
return conteneur + contenu;
|
const ligneObjet = Handlebars.partials[optionsArbre.templateItem](inventaire);
|
||||||
|
if (isConteneur) {
|
||||||
|
return ligneObjet + RdDUtility.buildContenuConteneur(item, options, optionsArbre);
|
||||||
|
}
|
||||||
|
return ligneObjet;
|
||||||
|
}
|
||||||
|
|
||||||
|
static buildInventaireConteneur(actorId, itemId, options) {
|
||||||
|
const actor = game.actors.get(actorId)
|
||||||
|
const item = actor?.items.get(itemId)
|
||||||
|
if (item) {
|
||||||
|
return RdDUtility.buildContenuConteneur(item, options, { ouvert: true, profondeur: 1 });
|
||||||
|
}
|
||||||
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static buildContenu(objet, profondeur, afficherContenu, templateItem, options) {
|
static buildContenuConteneur(conteneur, options = {}, optionsArbre = {}) {
|
||||||
if (!profondeur) profondeur = 1;
|
RdDUtility.prepareOptionsArbreInventaire(conteneur, optionsArbre);
|
||||||
if (!templateItem) templateItem = 'actor/inventaire-item.html'
|
const display = optionsArbre.ouvert ? 'item-display-show' : 'item-display-hide';
|
||||||
objet.niveau = profondeur;
|
const profondeur = optionsArbre.profondeur;
|
||||||
|
|
||||||
|
optionsArbre.profondeur++;
|
||||||
|
const lignesContenu = conteneur.subItems.sort(Misc.ascending(it => it.name))
|
||||||
|
.map(contenu => this.buildLigneInventaire(contenu, options, optionsArbre));
|
||||||
|
|
||||||
|
return `<ul class='item-list alterne-list ${display} list-item-margin${Math.min(profondeur, 6)}'>`
|
||||||
|
+ lignesContenu.reduce(Misc.joining(''), '')
|
||||||
|
+ "</ul>";
|
||||||
|
|
||||||
const display = afficherContenu ? 'item-display-show' : 'item-display-hide';
|
|
||||||
let strContenu = `<ul class='item-list alterne-list ${display} list-item-margin${Math.min(profondeur, 6)}'>`;
|
|
||||||
for (let subItem of objet.subItems) {
|
|
||||||
strContenu += this.buildConteneur(subItem, profondeur + 1, templateItem, options);
|
|
||||||
}
|
|
||||||
return strContenu + "</ul>";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@@ -443,10 +456,6 @@ export class RdDUtility {
|
|||||||
return ajustementsEncaissement;
|
return ajustementsEncaissement;
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDefinitionsBlessures() {
|
|
||||||
return definitionsBlessures;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getSegmentsFatigue(maxEnd) {
|
static getSegmentsFatigue(maxEnd) {
|
||||||
maxEnd = Math.max(maxEnd, 1);
|
maxEnd = Math.max(maxEnd, 1);
|
||||||
@@ -587,17 +596,10 @@ export class RdDUtility {
|
|||||||
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;';
|
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;';
|
||||||
encaissement.roll = roll;
|
encaissement.roll = roll;
|
||||||
encaissement.armure = armure;
|
encaissement.armure = armure;
|
||||||
|
encaissement.penetration = rollData.arme?.system.penetration ?? 0;
|
||||||
encaissement.total = jetTotal;
|
encaissement.total = jetTotal;
|
||||||
encaissement.vie = await RdDUtility._evaluatePerte(encaissement.vie, over20);
|
encaissement.vie = await RdDUtility._evaluatePerte(encaissement.vie, over20);
|
||||||
encaissement.endurance = await RdDUtility._evaluatePerte(encaissement.endurance, over20);
|
encaissement.endurance = await RdDUtility._evaluatePerte(encaissement.endurance, over20);
|
||||||
encaissement.penetration = rollData.arme?.system.penetration ?? 0;
|
|
||||||
encaissement.blessures = (
|
|
||||||
encaissement.critiques > 0 ? "Critique" :
|
|
||||||
encaissement.graves > 0 ? "Grave" :
|
|
||||||
encaissement.legeres > 0 ? "Légère" :
|
|
||||||
encaissement.eraflures > 0 ? "Contusions/Eraflures" :
|
|
||||||
'Aucune'
|
|
||||||
);
|
|
||||||
return encaissement;
|
return encaissement;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -692,6 +694,44 @@ 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);
|
||||||
@@ -824,17 +864,13 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete) {
|
static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete, onSuppression = ()=>{}) {
|
||||||
RdDConfirm.confirmer({
|
RdDConfirm.confirmer({
|
||||||
settingConfirmer: "confirmation-supprimer-lien-acteur",
|
settingConfirmer: "confirmation-supprimer-lien-acteur",
|
||||||
content: `<p>Etes vous certain de vouloir supprimer le lien vers ${subActor.name} ?</p>`,
|
content: `<p>Etes vous certain de vouloir supprimer le lien vers ${subActor.name} ?</p>`,
|
||||||
title: 'Confirmer la suppression',
|
title: 'Confirmer la suppression',
|
||||||
buttonLabel: 'Supprimer le lien',
|
buttonLabel: 'Supprimer le lien',
|
||||||
onAction: () => {
|
onAction: onSuppression
|
||||||
console.log('Delete : ', subActor.id);
|
|
||||||
sheet.actor.removeSubacteur(subActor.id);
|
|
||||||
RdDUtility.slideOnDelete(sheet, htmlToDelete);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -56,14 +56,14 @@ export const referenceAjustements = {
|
|||||||
getValue: (rollData, actor) => actor.getEtatGeneral({ ethylisme: rollData.forceAlcool != undefined })
|
getValue: (rollData, actor) => actor.getEtatGeneral({ ethylisme: rollData.forceAlcool != undefined })
|
||||||
},
|
},
|
||||||
malusArmure: {
|
malusArmure: {
|
||||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac),
|
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac),
|
||||||
isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac),
|
isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac),
|
||||||
getLabel: (rollData, actor) => 'Malus armure',
|
getLabel: (rollData, actor) => 'Malus armure',
|
||||||
getValue: (rollData, actor) => actor.getMalusArmure()
|
getValue: (rollData, actor) => actor.getMalusArmure()
|
||||||
},
|
},
|
||||||
encTotal: {
|
encTotal: {
|
||||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
||||||
isUsed: (rollData, actor) => !rollData.oeuvre && RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) && rollData.use.encTotal,
|
isUsed: (rollData, actor) => !rollData.oeuvre && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) && rollData.use.encTotal,
|
||||||
getLabel: (rollData, actor) => 'Encombrement total',
|
getLabel: (rollData, actor) => 'Encombrement total',
|
||||||
getValue: (rollData, actor) => -actor.getEncTotal()
|
getValue: (rollData, actor) => -actor.getEncTotal()
|
||||||
},
|
},
|
||||||
@@ -139,6 +139,12 @@ export const referenceAjustements = {
|
|||||||
isUsed: (rollData, actor) => rollData.ethylisme != undefined,
|
isUsed: (rollData, actor) => rollData.ethylisme != undefined,
|
||||||
getLabel: (rollData, actor) => "Ethylisme - " + RdDUtility.getNomEthylisme(rollData.ethylisme),
|
getLabel: (rollData, actor) => "Ethylisme - " + RdDUtility.getNomEthylisme(rollData.ethylisme),
|
||||||
getValue: (rollData, actor) => rollData.ethylisme,
|
getValue: (rollData, actor) => rollData.ethylisme,
|
||||||
|
},
|
||||||
|
tailleempoignade: {
|
||||||
|
isVisible: (rollData, actor) => rollData.isEmpoignade,
|
||||||
|
isUsed: (rollData, actor) => rollData.isEmpoignade,
|
||||||
|
getLabel: (rollData, actor) => "Malus de taille",
|
||||||
|
getValue: (rollData, actor) => rollData.malusTaille,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -17,6 +17,7 @@ const listeReglesOptionelles = [
|
|||||||
{ 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: '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: 'appliquer-fatigue', descr: "Appliquer les règles de fatigue"},
|
||||||
{ group: 'Règles générales', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false },
|
{ group: 'Règles générales', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false },
|
||||||
|
{ group: '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: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"},
|
||||||
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
|
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
|
||||||
|
@@ -52,12 +52,16 @@ export class SystemCompendiums extends FormApplication {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static getPack(compendium) {
|
static getPack(compendium) {
|
||||||
|
const pack = game.packs.get(compendium);
|
||||||
|
if (pack) {
|
||||||
|
return pack;
|
||||||
|
}
|
||||||
return game.packs.get(SystemCompendiums.getCompendium(compendium)) ?? game.packs.get(SystemCompendiums._getDefaultCompendium(compendium));
|
return game.packs.get(SystemCompendiums.getCompendium(compendium)) ?? game.packs.get(SystemCompendiums._getDefaultCompendium(compendium));
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getPackContent(compendium, docType) {
|
static async getPackContent(compendium, docType) {
|
||||||
const pack = SystemCompendiums.getPack(compendium);
|
const pack = SystemCompendiums.getPack(compendium);
|
||||||
if (pack.metadata.type == docType) {
|
if (pack?.metadata.type == docType) {
|
||||||
return await pack.getDocuments();
|
return await pack.getDocuments();
|
||||||
}
|
}
|
||||||
return [];
|
return [];
|
||||||
@@ -177,7 +181,7 @@ export class SystemCompendiums extends FormApplication {
|
|||||||
*/
|
*/
|
||||||
export class CompendiumTable {
|
export class CompendiumTable {
|
||||||
|
|
||||||
constructor(compendium, type, subTypes, sorting = undefined) {
|
constructor(compendium, type, subTypes = undefined, sorting = undefined) {
|
||||||
this.compendium = compendium;
|
this.compendium = compendium;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.subTypes = subTypes;
|
this.subTypes = subTypes;
|
||||||
@@ -187,13 +191,13 @@ export class CompendiumTable {
|
|||||||
async getContent(itemFrequence = it => it.system.frequence, filter = it => true) {
|
async getContent(itemFrequence = it => it.system.frequence, filter = it => true) {
|
||||||
return await SystemCompendiums.getContent(this.compendium,
|
return await SystemCompendiums.getContent(this.compendium,
|
||||||
this.type,
|
this.type,
|
||||||
it => this.subTypes.includes(it.type) && filter(it),
|
it => (!this.subTypes || this.subTypes.includes(it.type)) && itemFrequence(it) > 0 && filter(it),
|
||||||
itemFrequence,
|
itemFrequence,
|
||||||
this.sorting);
|
this.sorting);
|
||||||
}
|
}
|
||||||
|
|
||||||
async buildTable(itemFrequence = it => it.system.frequence, filter = it => true) {
|
async buildTable(itemFrequence = it => it.system.frequence, filter = it => true) {
|
||||||
const elements = await this.getContent(filter, itemFrequence);
|
const elements = await this.getContent(itemFrequence, filter);
|
||||||
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
|
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,9 +229,23 @@ export class CompendiumTableHelpers {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getRandom(table, type, subTypes, forcedRoll = undefined, localisation = undefined) {
|
static concatTables(...tables) {
|
||||||
|
const rows = tables.reduce((a, b) => a.concat(b));
|
||||||
|
let max = 0;
|
||||||
|
const total = rows.map(it => it.frequence).reduce(Misc.sum(), 0);
|
||||||
|
return rows.map(row => {
|
||||||
|
const frequence = row.frequence;
|
||||||
|
row.min = max + 1;
|
||||||
|
row.max = max + frequence;
|
||||||
|
row.total = total
|
||||||
|
max += frequence;
|
||||||
|
return row;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
static async getRandom(table, type, subTypes = ['objet'], forcedRoll = undefined, localisation = undefined) {
|
||||||
if (table.length == 0) {
|
if (table.length == 0) {
|
||||||
ui.notifications.warn(`Aucun ${Misc.typeName(type, subTypes[0])} trouvé dans ${localisation ?? ' les compendiums'}`);
|
const typeName = Misc.typeName(type, subTypes[0]);
|
||||||
|
ui.notifications.warn(`Aucun ${typeName} trouvé dans ${localisation ?? ' les compendiums'}`);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
return await CompendiumTableHelpers.selectRow(table, forcedRoll);
|
return await CompendiumTableHelpers.selectRow(table, forcedRoll);
|
||||||
@@ -260,7 +278,7 @@ export class CompendiumTableHelpers {
|
|||||||
roll: row.roll,
|
roll: row.roll,
|
||||||
document: row.document,
|
document: row.document,
|
||||||
percentages,
|
percentages,
|
||||||
typeName: Misc.typeName(type, row.document.type),
|
typeName: Misc.typeName(type, row.document?.type ?? 'objet'),
|
||||||
isGM: game.user.isGM,
|
isGM: game.user.isGM,
|
||||||
});
|
});
|
||||||
const messageData = {
|
const messageData = {
|
||||||
|
206
module/sommeil/app-astrologie.js
Normal file
206
module/sommeil/app-astrologie.js
Normal file
@@ -0,0 +1,206 @@
|
|||||||
|
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "../constants.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { RdDTimestamp } from "../time/rdd-timestamp.js";
|
||||||
|
|
||||||
|
export const APP_ASTROLOGIE_REFRESH = `${SYSTEM_RDD}-refresh-astrologie`
|
||||||
|
|
||||||
|
export class AppAstrologie extends Application {
|
||||||
|
static async create(actor = undefined, options = {}) {
|
||||||
|
if (actor == undefined && !game.user.isGM) {
|
||||||
|
actor = game.user.character
|
||||||
|
}
|
||||||
|
if (!actor && !game.user.isGM) {
|
||||||
|
console.error("AppAstrologie uniquement accessible pour le MJ, ou depuis un personnage pour un joueur")
|
||||||
|
}
|
||||||
|
new AppAstrologie(actor, options).render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static get defaultOptions() {
|
||||||
|
return mergeObject(super.defaultOptions, {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/sommeil/app-astrologie.hbs",
|
||||||
|
title: "Astrologie",
|
||||||
|
width: 'fit-content',
|
||||||
|
height: 'fit-content',
|
||||||
|
classes: ['calendar-astrologie'],
|
||||||
|
popOut: true,
|
||||||
|
resizable: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(actor, options = {}) {
|
||||||
|
super(options);
|
||||||
|
this.actor = actor;
|
||||||
|
this.hookReference = Hooks.on(APP_ASTROLOGIE_REFRESH, () => this.refreshAstrologie());
|
||||||
|
}
|
||||||
|
|
||||||
|
getData(options) {
|
||||||
|
this.appData = super.getData(options)
|
||||||
|
const calendrier = game.system.rdd.calendrier;
|
||||||
|
mergeObject(this.appData, {
|
||||||
|
isGM: game.user.isGM,
|
||||||
|
isActor: this.actor != undefined,
|
||||||
|
calendrier: calendrier.getTimestamp().toCalendrier(),
|
||||||
|
dates: calendrier.getJoursSuivants(10),
|
||||||
|
heures: RdDTimestamp.definitions(),
|
||||||
|
actorAstrologie: this.getActorAstrologie(),
|
||||||
|
gmAstrologie: this.getGMAstrologie(calendrier),
|
||||||
|
theme: {
|
||||||
|
signeAstral: RdDTimestamp.definition(0),
|
||||||
|
signeNaissance: RdDTimestamp.definition(0)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return this.appData;
|
||||||
|
}
|
||||||
|
|
||||||
|
getActorAstrologie() {
|
||||||
|
if (this.actor) {
|
||||||
|
return {
|
||||||
|
actor: this.actor,
|
||||||
|
nombres: this._organizeNombresAstraux(this.actor.itemTypes['nombreastral']),
|
||||||
|
ajustements: CONFIG.RDD.difficultesLibres,
|
||||||
|
etat: this.actor.getEtatGeneral(),
|
||||||
|
astrologie: this.actor.getCompetence('Astrologie')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
_organizeNombresAstraux(nombresAstraux) {
|
||||||
|
let organized = {};
|
||||||
|
nombresAstraux.forEach(na => {
|
||||||
|
if (!organized[na.system.jourindex]) {
|
||||||
|
organized[na.system.jourindex] = {
|
||||||
|
listValues: [],
|
||||||
|
jourlabel: na.system.jourlabel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
organized[na.system.jourindex].listValues.push(na.system.value);
|
||||||
|
})
|
||||||
|
return organized;
|
||||||
|
}
|
||||||
|
|
||||||
|
getGMAstrologie(calendrier) {
|
||||||
|
if (game.user.isGM) {
|
||||||
|
const nbAstral = calendrier.getNombreAstral()
|
||||||
|
const heures = RdDTimestamp.heures();
|
||||||
|
return {
|
||||||
|
ajustementsActors: game.actors.filter(it => it.isPersonnage() && it.hasPlayerOwner)
|
||||||
|
.map(actor => this.getAjustementActor(actor, nbAstral, heures)),
|
||||||
|
nombresAstraux: calendrier.getNombresAstraux().map(na => this.getDetailNombreAstral(na))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {}
|
||||||
|
}
|
||||||
|
|
||||||
|
getAjustementActor(actor, nbAstral, heures) {
|
||||||
|
const hn = RdDTimestamp.findHeure(actor.getHeureNaissance())?.heure ?? 0;
|
||||||
|
return {
|
||||||
|
actor,
|
||||||
|
ajustements: heures.map(heure => {
|
||||||
|
return { heure, ajustement: RdDTimestamp.ajustementAstrologiqueHeure(hn, nbAstral, heure) };
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getDetailNombreAstral(nombreAstral) {
|
||||||
|
const detail = duplicate(nombreAstral);
|
||||||
|
const timestamp = new RdDTimestamp({ indexDate: nombreAstral.index });
|
||||||
|
detail.date = { mois: timestamp.mois, jour: timestamp.jour + 1 };
|
||||||
|
detail.valeursFausses.forEach(fausse => fausse.actorName = game.actors.get(fausse.actorId).name ?? "Inconnu");
|
||||||
|
return detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
this.html = html;
|
||||||
|
this.html.find('select[name="signe-astral"]').change(event => {
|
||||||
|
this.selectNombreAstral(this.html.find('select[name="signe-astral"]').val());
|
||||||
|
})
|
||||||
|
this.html.find('select[name="signe-naissance"]').change(event => {
|
||||||
|
this.selectHeureNaissance(this.html.find('select[name="signe-naissance"]').val());
|
||||||
|
})
|
||||||
|
this.html.find('td.nombre-astral').click(event => {
|
||||||
|
this.selectNombreAstral(Number.parseInt(event.currentTarget.attributes['data-nombre-astral'].value) - 1);
|
||||||
|
})
|
||||||
|
this.html.find('tr.heure-naissance').click(event => {
|
||||||
|
this.selectHeureNaissance(event.currentTarget.attributes['data-heure-naissance'].value);
|
||||||
|
})
|
||||||
|
this.html.find('[name="jet-astrologie"]').click(event => this.requestJetAstrologie());
|
||||||
|
this.html.find('[name="rebuild-nombres-astraux"]').click(event => this.rebuildNombresAstraux());
|
||||||
|
|
||||||
|
this.onCalculThemeAstral();
|
||||||
|
}
|
||||||
|
|
||||||
|
selectHeureNaissance(heureNaissance) {
|
||||||
|
this.appData.theme.signeNaissance = RdDTimestamp.definition(heureNaissance);
|
||||||
|
this.onCalculThemeAstral();
|
||||||
|
}
|
||||||
|
|
||||||
|
selectNombreAstral(nombreAstral) {
|
||||||
|
this.appData.theme.signeAstral = RdDTimestamp.definition(nombreAstral);
|
||||||
|
this.onCalculThemeAstral();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async rebuildNombresAstraux() {
|
||||||
|
game.system.rdd.calendrier.resetNombresAstraux();
|
||||||
|
|
||||||
|
await game.system.rdd.calendrier.rebuildNombresAstraux();
|
||||||
|
}
|
||||||
|
|
||||||
|
onCalculThemeAstral() {
|
||||||
|
const chiffreAstral = this.appData.theme.signeAstral.heure + 1;
|
||||||
|
const heureNaissance = this.appData.theme.signeNaissance.heure + 1;
|
||||||
|
RdDTimestamp.definitions().forEach(dh => {
|
||||||
|
const ajustement = RdDTimestamp.ajustementAstrologiqueHeure(heureNaissance, chiffreAstral, dh.heure + 1);
|
||||||
|
const txtAjustement = ajustement == 0 ? '' : Misc.toSignedString(ajustement);
|
||||||
|
this.html.find(`div.horloge-ajustement.heure-${dh.hh}`).text(txtAjustement)
|
||||||
|
});
|
||||||
|
|
||||||
|
this.html.find(`select[name="signe-astral"]`).val(this.appData.theme.signeAstral.key)
|
||||||
|
this.html.find(`select[name="signe-naissance"]`).val(this.appData.theme.signeNaissance.key)
|
||||||
|
|
||||||
|
const angleAstrologie = ((chiffreAstral + heureNaissance) * 30) % 360 - 45;
|
||||||
|
this.html.find(`div.horloge-roue div.disque-astro img`).css(Misc.cssRotation(angleAstrologie));
|
||||||
|
|
||||||
|
const timestamp = game.system.rdd.calendrier.getTimestamp();
|
||||||
|
|
||||||
|
this.html.find(`div.horloge-roue div.horloge-aiguille-heure img`).css(Misc.cssRotation(timestamp.angleHeure));
|
||||||
|
this.html.find(`div.horloge-roue div.horloge-aiguille-minute img`).css(Misc.cssRotation(timestamp.angleMinute));
|
||||||
|
}
|
||||||
|
|
||||||
|
requestJetAstrologie() {
|
||||||
|
if (!this.appData?.isActor) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
let socketData = {
|
||||||
|
id: this.appData.actorAstrologie.actor.id,
|
||||||
|
carac_vue: this.actor.system.carac['vue'].value,
|
||||||
|
etat: this.actor.getEtatGeneral(),
|
||||||
|
astrologie: this.actor.getCompetence('Astrologie'),
|
||||||
|
conditions: this.html.find('[name="diffConditions"]').val(),
|
||||||
|
date: this.html.find('[name="joursAstrologie"]').val(),
|
||||||
|
userId: game.user.id
|
||||||
|
}
|
||||||
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
|
game.system.rdd.calendrier.requestNombreAstral(socketData);
|
||||||
|
} else {
|
||||||
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
|
msg: "msg_request_nombre_astral",
|
||||||
|
data: socketData
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
refreshAstrologie() {
|
||||||
|
this.render(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
async close(options) {
|
||||||
|
Hooks.off(APP_ASTROLOGIE_REFRESH, this.hookReference);
|
||||||
|
this.hookReference = undefined
|
||||||
|
await super.close(options)
|
||||||
|
}
|
||||||
|
}
|
105
module/sommeil/dialog-chateau-dormant.js
Normal file
105
module/sommeil/dialog-chateau-dormant.js
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
|
||||||
|
export class DialogChateauDormant extends Dialog {
|
||||||
|
|
||||||
|
static async create() {
|
||||||
|
const date = game.system.rdd.calendrier.dateCourante();
|
||||||
|
const actors = game.actors.filter(actor => actor.hasPlayerOwner && actor.isPersonnage());
|
||||||
|
|
||||||
|
const dialogData = {
|
||||||
|
actors: actors,
|
||||||
|
date: date,
|
||||||
|
motifStress: `Nuit du ${date}`,
|
||||||
|
finChateauDormant: game.system.rdd.calendrier.getTimestampFinChateauDormant()
|
||||||
|
};
|
||||||
|
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-chateau-dormant.hbs",
|
||||||
|
dialogData);
|
||||||
|
|
||||||
|
new DialogChateauDormant(dialogData, html)
|
||||||
|
.render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(dialogData, html) {
|
||||||
|
const options = {
|
||||||
|
classes: ["rdd-dialog-chateau-dormant"],
|
||||||
|
width: 600,
|
||||||
|
height: 'fit-content',
|
||||||
|
'z-index': 99999
|
||||||
|
};
|
||||||
|
const conf = {
|
||||||
|
title: "De Chateau dormant à Vaisseau",
|
||||||
|
content: html,
|
||||||
|
buttons: {
|
||||||
|
chateauDormant: { label: "Passer à Vaisseau!", callback: it => { this.onChateauDormant(); } }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
super(conf, options);
|
||||||
|
this.dialogData = dialogData;
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
this.html = html;
|
||||||
|
this.html.find('input.sommeil-insomnie').change(event => this.onInsomnie(event));
|
||||||
|
this._activateListenerOnActorMoral(this.html);
|
||||||
|
}
|
||||||
|
|
||||||
|
_activateListenerOnActorMoral(html) {
|
||||||
|
html.find(`span.sommeil-actor-moral a`).click(event => this.onActorMoral(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
onInsomnie(event) {
|
||||||
|
const sommeilInsomnie = this.html.find(event.currentTarget);
|
||||||
|
const isInsomnie = sommeilInsomnie.is(':checked');
|
||||||
|
const sommeilHeures = sommeilInsomnie.parents('.set-sommeil-actor').find('input.sommeil-heures');
|
||||||
|
sommeilHeures.prop('disabled', isInsomnie);
|
||||||
|
if (isInsomnie) {
|
||||||
|
sommeilHeures.val('0');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async onActorMoral(event) {
|
||||||
|
const selected = this.html.find(event.currentTarget);
|
||||||
|
const actorRow = selected.parents('.set-sommeil-actor');
|
||||||
|
const actorId = actorRow.data('actor-id');
|
||||||
|
const actor = this.getActor(actorId);
|
||||||
|
actor.system.sommeil.moral = selected.data('moral');
|
||||||
|
const htmlMoral = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/sommeil/sommeil-actor-moral.hbs', actor.system.sommeil)
|
||||||
|
actorRow.find('.sommeil-actor-moral').html(htmlMoral);
|
||||||
|
// re-attach listeners for actor row
|
||||||
|
this._activateListenerOnActorMoral(actorRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
getActor(actorId) {
|
||||||
|
return this.dialogData.actors.find(it => it.id == actorId);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onChateauDormant() {
|
||||||
|
const motifStress = this.html.find("form input[name='motifStress']").val();
|
||||||
|
jQuery.map(
|
||||||
|
this.html.find('li.set-sommeil-actor'),
|
||||||
|
it => this.extractConsigneActor(this.html.find(it), motifStress)
|
||||||
|
).forEach(async consigne => await consigne.actor.prepareChateauDormant(consigne))
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extractConsigneActor(actorRow, motifStress) {
|
||||||
|
const actorId = actorRow.data('actor-id');
|
||||||
|
const actor = this.getActor(actorId);
|
||||||
|
const insomnie = actorRow.find('input.sommeil-insomnie').is(':checked');
|
||||||
|
return {
|
||||||
|
actor,
|
||||||
|
ignorer: actorRow.find('input.sommeil-ignorer').is(':checked'),
|
||||||
|
stress: {
|
||||||
|
motif: motifStress,
|
||||||
|
valeur: Number.parseInt(actorRow.find('input.sommeil-stress').val()),
|
||||||
|
},
|
||||||
|
sommeil: {
|
||||||
|
nouveaujour: true,
|
||||||
|
date: this.dialogData.finChateauDormant,
|
||||||
|
insomnie: insomnie,
|
||||||
|
heures: insomnie ? 0 : Number.parseInt(actorRow.find('input.sommeil-heures').val()),
|
||||||
|
moral: actor.system.sommeil.moral ?? 'neutre',
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
87
module/sommeil/dialog-repos.js
Normal file
87
module/sommeil/dialog-repos.js
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
import { ReglesOptionelles } from "../settings/regles-optionelles.js";
|
||||||
|
import { EffetsDraconiques } from "../tmr/effets-draconiques.js";
|
||||||
|
|
||||||
|
export class DialogRepos extends Dialog {
|
||||||
|
|
||||||
|
static async create(actor) {
|
||||||
|
if (!actor.isPersonnage()) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (!ReglesOptionelles.isUsing("chateau-dormant-gardien") || !actor.hasPlayerOwner) {
|
||||||
|
actor.system.sommeil = {
|
||||||
|
"nouveaujour": true,
|
||||||
|
"insomnie": EffetsDraconiques.isSujetInsomnie(actor),
|
||||||
|
"moral": "neutre",
|
||||||
|
"heures": 4
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-repos.html", actor);
|
||||||
|
const dialog = new DialogRepos(html, actor);
|
||||||
|
dialog.render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(html, actor) {
|
||||||
|
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 400, height: 'fit-content', 'z-index': 99999 };
|
||||||
|
let conf = {
|
||||||
|
title: "Se reposer",
|
||||||
|
content: html,
|
||||||
|
default: "repos",
|
||||||
|
buttons: {
|
||||||
|
"repos": { label: "Se reposer", callback: async it => { this.repos(); } }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
super(conf, options);
|
||||||
|
this.actor = actor;
|
||||||
|
}
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
this.html = html;
|
||||||
|
this.html.find(`.sommeil-actor-moral a`).click(event => this.onActorMoral(event));
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
async repos() {
|
||||||
|
const selection = await this.html.find("[name='repos']:checked").val();
|
||||||
|
switch (selection) {
|
||||||
|
case "sieste": return await this.sieste();
|
||||||
|
case "nuit": return await this.nuit();
|
||||||
|
case "chateau-dormant": return await this.chateauDormant();
|
||||||
|
case "gris-reve": return await this.grisReve();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async grisReve() {
|
||||||
|
await this.html.find("[name='nb-jours']").change();
|
||||||
|
const nbJours = Number.parseInt(await this.html.find("[name='nb-jours']").val());
|
||||||
|
await this.actor.grisReve(nbJours);
|
||||||
|
}
|
||||||
|
|
||||||
|
async chateauDormant() {
|
||||||
|
await this.actor.dormirChateauDormant();
|
||||||
|
}
|
||||||
|
|
||||||
|
async nuit() {
|
||||||
|
await this.html.find("[name='sommeil.heures']").change();
|
||||||
|
const val = await this.html.find("[name='sommeil.heures']").val();
|
||||||
|
const sommeilHeures = Number.parseInt(val ?? '0');
|
||||||
|
await this.actor.dormir(sommeilHeures, { chateauDormant: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
async sieste() {
|
||||||
|
await this.html.find("[name='sieste.heures']").change();
|
||||||
|
const siesteHeures = Number.parseInt(await this.html.find("[name='sieste.heures']").val());
|
||||||
|
await this.actor.dormir(siesteHeures);
|
||||||
|
}
|
||||||
|
|
||||||
|
async onActorMoral(event) {
|
||||||
|
const selected = this.html.find(event.currentTarget);
|
||||||
|
const parentDiv = selected.parents().find('.sommeil-actor-moral');
|
||||||
|
const situationMoral = selected.data('moral');
|
||||||
|
await this.actor.setInfoSommeilMoral(situationMoral);
|
||||||
|
const htmlMoral = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/sommeil/sommeil-actor-moral.hbs', {
|
||||||
|
moral: situationMoral
|
||||||
|
});
|
||||||
|
parentDiv.html(htmlMoral);
|
||||||
|
this.html.find(`.sommeil-actor-moral a`).click(event => this.onActorMoral(event));
|
||||||
|
}
|
||||||
|
}
|
@@ -15,7 +15,7 @@ export class DialogStress extends Dialog {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-stress.html", dialogData);
|
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-stress.html", dialogData);
|
||||||
new DialogStress(dialogData, html)
|
new DialogStress(dialogData, html)
|
||||||
.render(true);
|
.render(true);
|
||||||
}
|
}
|
||||||
@@ -50,7 +50,7 @@ export class DialogStress extends Dialog {
|
|||||||
|
|
||||||
this.dialogData.actors.filter(it => it.selected)
|
this.dialogData.actors.filter(it => it.selected)
|
||||||
.map(it => game.actors.get(it.id))
|
.map(it => game.actors.get(it.id))
|
||||||
.forEach(actor => actor.distribuerStress(compteur, stress, motif));
|
.forEach(async actor => await actor.distribuerStress(compteur, stress, motif));
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSelectActor(event) {
|
async onSelectActor(event) {
|
@@ -39,18 +39,18 @@ export class Targets {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static getTarget() {
|
static getTarget(options = { warn: true }) {
|
||||||
const targets = Targets.listTargets();
|
const targets = Targets.listTargets();
|
||||||
switch (targets.length) {
|
switch (targets.length) {
|
||||||
case 1:
|
case 1:
|
||||||
return targets[0];
|
return targets[0];
|
||||||
case 0:
|
case 0:
|
||||||
ui.notifications.warn("Vous devez choisir une cible à attaquer!");
|
if (options.warn) ui.notifications.warn("Vous devez choisir une cible à attaquer!");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
ui.notifications.warn("Vous devez choisir une cible (et <strong>une seule</strong>) à attaquer!");
|
if (options.warn) ui.notifications.warn("Vous devez choisir une cible (et <strong>une seule</strong>) à attaquer!");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
@@ -4,7 +4,7 @@ import { RdDTimestamp } from "./rdd-timestamp.js";
|
|||||||
* Extend the base Dialog entity by defining a custom window to perform roll.
|
* Extend the base Dialog entity by defining a custom window to perform roll.
|
||||||
* @extends {Dialog}
|
* @extends {Dialog}
|
||||||
*/
|
*/
|
||||||
export class RdDCalendrierEditeur extends Dialog {
|
export class RdDCalendrierEditor extends Dialog {
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(html, calendrier, calendrierData) {
|
constructor(html, calendrier, calendrierData) {
|
||||||
@@ -30,8 +30,8 @@ export class RdDCalendrierEditeur extends Dialog {
|
|||||||
this.html.find("input[name='calendar.annee']").val(this.calendrierData.annee);
|
this.html.find("input[name='calendar.annee']").val(this.calendrierData.annee);
|
||||||
this.html.find("select[name='calendar.mois']").val(this.calendrierData.mois.key);
|
this.html.find("select[name='calendar.mois']").val(this.calendrierData.mois.key);
|
||||||
this.html.find("select[name='calendar.heure']").val(this.calendrierData.heure.key);
|
this.html.find("select[name='calendar.heure']").val(this.calendrierData.heure.key);
|
||||||
RdDCalendrierEditeur.setLimited(this.html.find("input[name='calendar.jourDuMois']"), this.calendrierData.jourDuMois, 1, 28);
|
RdDCalendrierEditor.setLimited(this.html.find("input[name='calendar.jourDuMois']"), this.calendrierData.jourDuMois, 1, 28);
|
||||||
RdDCalendrierEditeur.setLimited(this.html.find("input[name='calendar.minute']"), this.calendrierData.minute, 0, 119);
|
RdDCalendrierEditor.setLimited(this.html.find("input[name='calendar.minute']"), this.calendrierData.minute, 0, 119);
|
||||||
}
|
}
|
||||||
|
|
||||||
static setLimited(input, init, min, max) {
|
static setLimited(input, init, min, max) {
|
455
module/time/rdd-calendrier.js
Normal file
455
module/time/rdd-calendrier.js
Normal file
@@ -0,0 +1,455 @@
|
|||||||
|
import { MAX_NOMBRE_ASTRAL, RdDTimestamp, WORLD_TIMESTAMP_SETTING } from "./rdd-timestamp.js";
|
||||||
|
import { RdDCalendrierEditor } from "./rdd-calendrier-editor.js";
|
||||||
|
import { RdDResolutionTable } from "../rdd-resolution-table.js";
|
||||||
|
import { RdDUtility } from "../rdd-utility.js";
|
||||||
|
import { RdDDice } from "../rdd-dice.js";
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { DialogChronologie } from "../dialog-chronologie.js";
|
||||||
|
import { HIDE_DICE, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "../constants.js";
|
||||||
|
import { ReglesOptionelles } from "../settings/regles-optionelles.js";
|
||||||
|
import { DialogChateauDormant } from "../sommeil/dialog-chateau-dormant.js";
|
||||||
|
import { APP_ASTROLOGIE_REFRESH, AppAstrologie } from "../sommeil/app-astrologie.js";
|
||||||
|
|
||||||
|
const TEMPLATE_CALENDRIER = "systems/foundryvtt-reve-de-dragon/templates/time/calendar.hbs";
|
||||||
|
|
||||||
|
const INITIAL_CALENDAR_POS = { top: 200, left: 200, horlogeAnalogique: true };
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
export class RdDCalendrier extends Application {
|
||||||
|
static init() {
|
||||||
|
game.settings.register(SYSTEM_RDD, "liste-nombre-astral", {
|
||||||
|
name: "liste-nombre-astral",
|
||||||
|
scope: "world",
|
||||||
|
config: false,
|
||||||
|
default: [],
|
||||||
|
type: Object
|
||||||
|
});
|
||||||
|
|
||||||
|
game.settings.register(SYSTEM_RDD, "calendrier-pos", {
|
||||||
|
name: "calendrierPos",
|
||||||
|
scope: "client",
|
||||||
|
config: false,
|
||||||
|
default: INITIAL_CALENDAR_POS,
|
||||||
|
type: Object
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static get defaultOptions() {
|
||||||
|
return mergeObject(super.defaultOptions, {
|
||||||
|
title: "Calendrier",
|
||||||
|
template: TEMPLATE_CALENDRIER,
|
||||||
|
classes: ["calendar"],
|
||||||
|
popOut: true,
|
||||||
|
resizable: false,
|
||||||
|
width: 'fit-content',
|
||||||
|
height: 'fit-content',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.timestamp = RdDTimestamp.getWorldTime();
|
||||||
|
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
|
||||||
|
RdDTimestamp.setWorldTime(this.timestamp);
|
||||||
|
this.nombresAstraux = this.getNombresAstraux();
|
||||||
|
this.rebuildNombresAstraux(HIDE_DICE); // Ensure always up-to-date
|
||||||
|
}
|
||||||
|
Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id));
|
||||||
|
}
|
||||||
|
|
||||||
|
get title() {
|
||||||
|
const calendrier = this.timestamp.toCalendrier();
|
||||||
|
return `${calendrier.heure.label}, ${calendrier.jourDuMois} ${calendrier.mois.label} ${calendrier.annee} (${calendrier.mois.saison})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
savePosition() {
|
||||||
|
game.settings.set(SYSTEM_RDD, "calendrier-pos", {
|
||||||
|
top: this.position.top,
|
||||||
|
left: this.position.left,
|
||||||
|
horlogeAnalogique: this.horlogeAnalogique
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getSavePosition() {
|
||||||
|
const pos = game.settings.get(SYSTEM_RDD, "calendrier-pos");
|
||||||
|
if (pos?.top == undefined) {
|
||||||
|
return INITIAL_CALENDAR_POS;
|
||||||
|
}
|
||||||
|
this.horlogeAnalogique = pos.horlogeAnalogique;
|
||||||
|
return pos
|
||||||
|
}
|
||||||
|
|
||||||
|
setPosition(position) {
|
||||||
|
super.setPosition(position)
|
||||||
|
this.savePosition()
|
||||||
|
}
|
||||||
|
|
||||||
|
display() {
|
||||||
|
const pos = this.getSavePosition()
|
||||||
|
this.render(true, { left: pos.left, top: pos.top });
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
_getHeaderButtons() {
|
||||||
|
const buttons = [];
|
||||||
|
if (game.user.isGM) {
|
||||||
|
buttons.unshift({
|
||||||
|
class: "calendar-astrologie",
|
||||||
|
icon: "fa-solid fa-moon-over-sun",
|
||||||
|
onclick: ev => this.showAstrologieEditor()
|
||||||
|
},
|
||||||
|
{
|
||||||
|
class: "calendar-set-datetime",
|
||||||
|
icon: "fa-solid fa-calendar-pen",
|
||||||
|
onclick: ev => this.showCalendarEditor()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return buttons
|
||||||
|
}
|
||||||
|
|
||||||
|
/*async maximize() {
|
||||||
|
await super.maximize()
|
||||||
|
this.render(true)
|
||||||
|
}*/
|
||||||
|
|
||||||
|
async close() { }
|
||||||
|
|
||||||
|
async onUpdateSetting(setting, update, options, id) {
|
||||||
|
if (setting.key == SYSTEM_RDD + '.' + WORLD_TIMESTAMP_SETTING) {
|
||||||
|
this.timestamp = RdDTimestamp.getWorldTime();
|
||||||
|
this.positionAiguilles()
|
||||||
|
this.render(false);
|
||||||
|
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getData() {
|
||||||
|
const formData = super.getData();
|
||||||
|
this.fillCalendrierData(formData);
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
fillCalendrierData(formData = {}) {
|
||||||
|
mergeObject(formData, this.timestamp.toCalendrier());
|
||||||
|
formData.isGM = game.user.isGM;
|
||||||
|
formData.heures = RdDTimestamp.definitions()
|
||||||
|
formData.horlogeAnalogique = this.horlogeAnalogique;
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** @override */
|
||||||
|
async activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
this.html = html;
|
||||||
|
this.html.find('.ajout-chronologie').click(ev => DialogChronologie.create());
|
||||||
|
this.html.find('.toggle-horloge-analogique').click(ev => this.onToggleHorlogeAnalogique())
|
||||||
|
this.html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));
|
||||||
|
this.html.find('.horloge-roue .horloge-heure').click(event => {
|
||||||
|
const h = this.html.find(event.currentTarget)?.data('heure');
|
||||||
|
this.positionnerHeure(Number(h));
|
||||||
|
})
|
||||||
|
this.html.find('.calendar-set-datetime').click(ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.showCalendarEditor();
|
||||||
|
});
|
||||||
|
|
||||||
|
this.html.find('.calendar-astrologie').click(ev => {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.showAstrologieEditor();
|
||||||
|
});
|
||||||
|
this.positionAiguilles()
|
||||||
|
}
|
||||||
|
|
||||||
|
positionAiguilles() {
|
||||||
|
const timestamp = this.getTimestamp();
|
||||||
|
this.html.find(`div.horloge-roue div.horloge-aiguille-heure img`).css(Misc.cssRotation(timestamp.angleHeure));
|
||||||
|
this.html.find(`div.horloge-roue div.horloge-aiguille-minute img`).css(Misc.cssRotation(timestamp.angleMinute));
|
||||||
|
}
|
||||||
|
|
||||||
|
onToggleHorlogeAnalogique() {
|
||||||
|
this.horlogeAnalogique = !this.horlogeAnalogique;
|
||||||
|
this.savePosition()
|
||||||
|
this.display()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getNombresAstraux() {
|
||||||
|
return game.settings.get(SYSTEM_RDD, "liste-nombre-astral") ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
dateCourante() {
|
||||||
|
return this.timestamp.formatDate();
|
||||||
|
}
|
||||||
|
|
||||||
|
dateReel() {
|
||||||
|
return new Date().toLocaleString("sv-SE", {
|
||||||
|
year: "numeric",
|
||||||
|
month: "2-digit",
|
||||||
|
day: "2-digit",
|
||||||
|
hour: "2-digit",
|
||||||
|
minute: "2-digit"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
isAfterIndexDate(indexDate) {
|
||||||
|
// TODO: standardize
|
||||||
|
return indexDate < this.timestamp.indexDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
heureCourante() { return RdDTimestamp.definition(this.timestamp.heure); }
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getCurrentMinute() { return this.timestamp.indexMinute; }
|
||||||
|
|
||||||
|
getTimestamp() {
|
||||||
|
return this.timestamp;
|
||||||
|
}
|
||||||
|
getTimestampFinChateauDormant(nbJours = 0) {
|
||||||
|
return this.timestamp.nouveauJour().addJours(nbJours);
|
||||||
|
}
|
||||||
|
|
||||||
|
getTimestampFinHeure(nbHeures = 0) {
|
||||||
|
return this.timestamp.nouvelleHeure().addHeures(nbHeures);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getIndexFromDate(jour, mois) {
|
||||||
|
const addYear = mois < this.timestamp.mois || (mois == this.timestamp.mois && jour < this.timestamp.jour)
|
||||||
|
const time = RdDTimestamp.timestamp(this.timestamp.annee + (addYear ? 1 : 0), mois, jour);
|
||||||
|
return time.indexDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getJoursSuivants(count) {
|
||||||
|
return Misc.intArray(this.timestamp.indexDate, this.timestamp.indexDate + count)
|
||||||
|
.map(i => { return { label: RdDTimestamp.formatIndexDate(i), index: i } })
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async ajouterNombreAstral(indexDate, showDice = SHOW_DICE) {
|
||||||
|
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: showDice, 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 {
|
||||||
|
nombreAstral: nombreAstral,
|
||||||
|
valeursFausses: [],
|
||||||
|
index: indexDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
resetNombresAstraux() {
|
||||||
|
this.nombresAstraux = [];
|
||||||
|
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", []);
|
||||||
|
|
||||||
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
|
msg: "msg_reset_nombre_astral",
|
||||||
|
data: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} indexDate la date pour laquelle obtenir le nombre astral. Si undefined, on prend la date du jour
|
||||||
|
* @returns le nombre astral pour la date, ou pour la date du jour si la date n'est pas fournie.
|
||||||
|
* Si aucun nombre astral n'est trouvé, retourne 0 (cas où l'on demanderait un nombre astral en dehors des 12 jours courant et à venir)
|
||||||
|
*/
|
||||||
|
getNombreAstral(indexDate = undefined) {
|
||||||
|
if (indexDate == undefined) {
|
||||||
|
indexDate = this.timestamp.indexDate;
|
||||||
|
}
|
||||||
|
this.nombresAstraux = this.getNombresAstraux();
|
||||||
|
let astralData = this.nombresAstraux.find((nombreAstral, i) => nombreAstral.index == indexDate);
|
||||||
|
return astralData?.nombreAstral ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async rebuildNombresAstraux(showDice = HIDE_DICE) {
|
||||||
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
|
console.log("Astral rebuild")
|
||||||
|
let newList = [];
|
||||||
|
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
|
||||||
|
let dayIndex = this.timestamp.indexDate + i;
|
||||||
|
let na = this.nombresAstraux.find(n => n.index == dayIndex);
|
||||||
|
if (na) {
|
||||||
|
newList[i] = na;
|
||||||
|
} else {
|
||||||
|
newList[i] = await this.ajouterNombreAstral(dayIndex, showDice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.nombresAstraux = newList;
|
||||||
|
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", newList);
|
||||||
|
game.actors.filter(it => it.isPersonnage()).forEach(actor => actor.supprimerAnciensNombresAstraux());
|
||||||
|
this.notifyChangeNombresAstraux();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyChangeNombresAstraux() {
|
||||||
|
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||||
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
|
msg: "msg_refresh_nombre_astral",
|
||||||
|
data: {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async setNewTimestamp(newTimestamp) {
|
||||||
|
const oldTimestamp = this.timestamp;
|
||||||
|
await Promise.all(game.actors.map(async actor => await actor.onTimeChanging(oldTimestamp, newTimestamp)));
|
||||||
|
RdDTimestamp.setWorldTime(newTimestamp);
|
||||||
|
if (oldTimestamp.indexDate + 1 == newTimestamp.indexDate && ReglesOptionelles.isUsing("chateau-dormant-gardien")) {
|
||||||
|
await DialogChateauDormant.create();
|
||||||
|
}
|
||||||
|
this.timestamp = newTimestamp;
|
||||||
|
await this.rebuildNombresAstraux();
|
||||||
|
this.positionAiguilles()
|
||||||
|
this.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async onCalendarButton(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
const calendarAvance = ev.currentTarget.attributes['data-calendar-avance'];
|
||||||
|
const calendarSet = ev.currentTarget.attributes['data-calendar-set'];
|
||||||
|
if (calendarAvance) {
|
||||||
|
await this.incrementTime(Number(calendarAvance.value));
|
||||||
|
}
|
||||||
|
else if (calendarSet) {
|
||||||
|
this.positionnerHeure(Number(calendarSet.value));
|
||||||
|
}
|
||||||
|
this.positionAiguilles()
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async incrementTime(minutes = 0) {
|
||||||
|
if (game.user.isGM) {
|
||||||
|
await this.setNewTimestamp(this.timestamp.addMinutes(minutes));
|
||||||
|
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async incrementerJour() {
|
||||||
|
await this.setNewTimestamp(this.timestamp.nouveauJour());
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async positionnerHeure(heure) {
|
||||||
|
if (game.user.isGM) {
|
||||||
|
const indexDate = this.timestamp.indexDate;
|
||||||
|
const addDay = this.timestamp.heure < heure ? 0 : 1;
|
||||||
|
const newTimestamp = new RdDTimestamp({ indexDate: indexDate + addDay }).addHeures(heure);
|
||||||
|
await this.setNewTimestamp(newTimestamp)
|
||||||
|
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getLectureAstrologieDifficulte(dateIndex) {
|
||||||
|
let indexNow = this.timestamp.indexDate;
|
||||||
|
let diffDay = dateIndex - indexNow;
|
||||||
|
return - Math.floor(diffDay / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async requestNombreAstral(request) {
|
||||||
|
const actor = game.actors.get(request.id);
|
||||||
|
if (Misc.isUniqueConnectedGM()) { // Only once
|
||||||
|
console.log(request);
|
||||||
|
let jourDiff = this.getLectureAstrologieDifficulte(request.date);
|
||||||
|
let niveau = Number(request.astrologie.system.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat);
|
||||||
|
let rollData = {
|
||||||
|
caracValue: request.carac_vue,
|
||||||
|
finalLevel: niveau,
|
||||||
|
showDice: HIDE_DICE,
|
||||||
|
rollMode: "blindroll"
|
||||||
|
};
|
||||||
|
await RdDResolutionTable.rollData(rollData);
|
||||||
|
request.rolled = rollData.rolled;
|
||||||
|
request.isValid = request.rolled.isSuccess;
|
||||||
|
request.nbAstral = this.getNombreAstral(request.date);
|
||||||
|
|
||||||
|
if (request.rolled.isSuccess) {
|
||||||
|
if (request.rolled.isPart) {
|
||||||
|
// Gestion expérience (si existante)
|
||||||
|
request.competence = actor.getCompetence("astrologie")
|
||||||
|
request.selectedCarac = actor.system.carac["vue"];
|
||||||
|
actor.appliquerAjoutExperience(request, 'hide');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
request.nbAstral = await RdDDice.rollTotal("1dhr" + request.nbAstral, {
|
||||||
|
rollMode: "selfroll", showDice: HIDE_DICE
|
||||||
|
});
|
||||||
|
// Mise à jour des nombres astraux du joueur
|
||||||
|
this.addNbAstralIncorect(request.id, request.date, request.nbAstral);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Misc.getActiveUser(request.userId)?.isGM) {
|
||||||
|
RdDUtility.responseNombreAstral(request);
|
||||||
|
} else {
|
||||||
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
|
msg: "msg_response_nombre_astral",
|
||||||
|
data: request
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addNbAstralIncorect(actorId, date, nbAstral) {
|
||||||
|
const astralData = this.nombresAstraux.find((nombreAstral, i) => nombreAstral.index == date);
|
||||||
|
astralData.valeursFausses.push({ actorId: actorId, nombreAstral: nbAstral });
|
||||||
|
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.nombresAstraux);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getAjustementAstrologique(heureNaissance, name = undefined) {
|
||||||
|
const defHeure = RdDTimestamp.findHeure(heureNaissance);
|
||||||
|
if (defHeure) {
|
||||||
|
return RdDTimestamp.ajustementAstrologiqueHeure(defHeure.heure, this.getNombreAstral(), this.timestamp.heure);
|
||||||
|
}
|
||||||
|
else if (name) {
|
||||||
|
ui.notifications.warn(name + " n'a pas d'heure de naissance, ou elle est incorrecte : " + heureNaissance);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.warn(heureNaissance + " ne correspond pas à une heure de naissance");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async saveEditeur(calendrierData) {
|
||||||
|
const newTimestamp = RdDTimestamp.timestamp(
|
||||||
|
Number.parseInt(calendrierData.annee),
|
||||||
|
calendrierData.mois.heure,
|
||||||
|
Number.parseInt(calendrierData.jourMois),
|
||||||
|
calendrierData.heure.heure,
|
||||||
|
Number.parseInt(calendrierData.minutes)
|
||||||
|
);
|
||||||
|
await this.setNewTimestamp(newTimestamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async showCalendarEditor() {
|
||||||
|
const calendrierData = this.fillCalendrierData();
|
||||||
|
if (this.editeur == undefined) {
|
||||||
|
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/time/calendar-editor.hbs', calendrierData);
|
||||||
|
this.editeur = new RdDCalendrierEditor(html, this, calendrierData)
|
||||||
|
}
|
||||||
|
this.editeur.updateData(calendrierData);
|
||||||
|
this.editeur.render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async showAstrologieEditor() {
|
||||||
|
await AppAstrologie.create();
|
||||||
|
}
|
||||||
|
}
|
@@ -1,16 +1,17 @@
|
|||||||
import { SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
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";
|
||||||
|
|
||||||
export const WORLD_TIMESTAMP_SETTING = "calendrier";
|
export const WORLD_TIMESTAMP_SETTING = "calendrier";
|
||||||
|
|
||||||
const RDD_MOIS_PAR_AN = 12;
|
|
||||||
const RDD_JOURS_PAR_MOIS = 28;
|
|
||||||
const RDD_JOURS_PAR_AN = 336; //RDD_JOURS_PAR_MOIS * RDD_MOIS_PAR_AN;
|
const RDD_JOURS_PAR_AN = 336; //RDD_JOURS_PAR_MOIS * RDD_MOIS_PAR_AN;
|
||||||
const RDD_HEURES_PAR_JOUR = 12;
|
const RDD_MOIS_PAR_AN = 12;
|
||||||
const RDD_MINUTES_PAR_HEURES = 120;
|
export const RDD_JOURS_PAR_MOIS = 28;
|
||||||
const RDD_MINUTES_PAR_JOUR = 1440; //RDD_HEURES_PAR_JOUR * RDD_MINUTES_PAR_HEURES;
|
export const RDD_HEURES_PAR_JOUR = 12;
|
||||||
|
export const MAX_NOMBRE_ASTRAL = 12;
|
||||||
|
export const RDD_MINUTES_PAR_HEURES = 120;
|
||||||
|
export const RDD_MINUTES_PAR_JOUR = 1440; //RDD_HEURES_PAR_JOUR * RDD_MINUTES_PAR_HEURES;
|
||||||
const ROUNDS_PAR_MINUTE = 10;
|
const ROUNDS_PAR_MINUTE = 10;
|
||||||
|
|
||||||
const DEFINITION_HEURES = [
|
const DEFINITION_HEURES = [
|
||||||
@@ -48,10 +49,6 @@ const FORMULES_PERIODE = [
|
|||||||
|
|
||||||
export class RdDTimestamp {
|
export class RdDTimestamp {
|
||||||
|
|
||||||
static iconeHeure(heure) {
|
|
||||||
return `systems/foundryvtt-reve-de-dragon/icons/heures/hd${heure < 9 ? '0' : ''}${heure + 1}.svg`;
|
|
||||||
}
|
|
||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
game.settings.register(SYSTEM_RDD, WORLD_TIMESTAMP_SETTING, {
|
game.settings.register(SYSTEM_RDD, WORLD_TIMESTAMP_SETTING, {
|
||||||
name: WORLD_TIMESTAMP_SETTING,
|
name: WORLD_TIMESTAMP_SETTING,
|
||||||
@@ -63,24 +60,23 @@ export class RdDTimestamp {
|
|||||||
|
|
||||||
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].icon = RdDTimestamp.iconeHeure(i);
|
DEFINITION_HEURES[i].icon = RdDTimestamp.iconeHeure(i);
|
||||||
DEFINITION_HEURES[i].webp = DEFINITION_HEURES[i].icon.replace(".svg", ".webp");
|
DEFINITION_HEURES[i].webp = DEFINITION_HEURES[i].icon.replace(".svg", ".webp");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @param signe
|
static hh(heure) {
|
||||||
* @returns L'entrée de DEFINITION_HEURES correspondant au signe
|
return heure < 9 ? `0${heure + 1}` : `${heure + 1}`;
|
||||||
*/
|
|
||||||
static definition(signe) {
|
|
||||||
if (Number.isInteger(signe)) {
|
|
||||||
return DEFINITION_HEURES[signe % RDD_HEURES_PAR_JOUR];
|
|
||||||
}
|
}
|
||||||
let definition = DEFINITION_HEURES.find(it => it.key == signe);
|
|
||||||
if (!definition) {
|
static iconeHeure(heure) {
|
||||||
definition = Misc.findFirstLike(signe, DEFINITION_HEURES, { mapper: it => it.label, description: 'signe' });
|
return `systems/foundryvtt-reve-de-dragon/icons/heures/hd${RdDTimestamp.hh(heure)}.svg`;
|
||||||
}
|
}
|
||||||
return definition
|
|
||||||
|
static definitions() {
|
||||||
|
return DEFINITION_HEURES
|
||||||
}
|
}
|
||||||
|
|
||||||
static formulesDuree() {
|
static formulesDuree() {
|
||||||
@@ -91,12 +87,48 @@ export class RdDTimestamp {
|
|||||||
return FORMULES_PERIODE
|
return FORMULES_PERIODE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static heures() {
|
||||||
|
return Misc.intArray(0, RDD_HEURES_PAR_JOUR)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param signe
|
||||||
|
* @returns L'entrée de DEFINITION_HEURES correspondant au signe
|
||||||
|
*/
|
||||||
|
static definition(signe) {
|
||||||
|
if (signe == undefined) {
|
||||||
|
signe = 0;
|
||||||
|
}
|
||||||
|
if (Number.isInteger(signe)) {
|
||||||
|
return DEFINITION_HEURES[signe % RDD_HEURES_PAR_JOUR];
|
||||||
|
}
|
||||||
|
let definition = DEFINITION_HEURES.find(it => it.key == signe);
|
||||||
|
if (!definition) {
|
||||||
|
definition = Misc.findFirstLike(signe, DEFINITION_HEURES, { mapper: it => it.label, description: 'signe' });
|
||||||
|
}
|
||||||
|
return definition
|
||||||
|
}
|
||||||
|
|
||||||
static imgSigneHeure(heure) {
|
static imgSigneHeure(heure) {
|
||||||
return RdDTimestamp.imgSigne(RdDTimestamp.definition(heure));
|
return RdDTimestamp.imgSigne(RdDTimestamp.definition(heure));
|
||||||
}
|
}
|
||||||
|
|
||||||
static imgSigne(signe) {
|
static imgSigne(signe) {
|
||||||
return `<img class="img-signe-heure" src="${signe.webp}" alt="${signe.label}"/>`
|
return signe == undefined ? '' : `<img class="img-signe-heure" src="${signe.webp}" alt="${signe.label}" title="${signe.label}"/>`
|
||||||
|
}
|
||||||
|
|
||||||
|
static ajustementAstrologiqueHeure(hn, nbAstral, heure) {
|
||||||
|
let ecart = (hn + nbAstral - heure) % RDD_HEURES_PAR_JOUR;
|
||||||
|
if (ecart < 0) {
|
||||||
|
ecart = (ecart + RDD_HEURES_PAR_JOUR) % RDD_HEURES_PAR_JOUR;
|
||||||
|
}
|
||||||
|
switch (ecart) {
|
||||||
|
case 0: return 4;
|
||||||
|
case 4: case 8: return 2;
|
||||||
|
case 6: return -4;
|
||||||
|
case 3: case 9: return -2;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static handleTimestampEditor(html, path, consumeTimestamp = async (path, timestamp) => { }) {
|
static handleTimestampEditor(html, path, consumeTimestamp = async (path, timestamp) => { }) {
|
||||||
@@ -196,6 +228,14 @@ export class RdDTimestamp {
|
|||||||
this.indexMinute = indexMinute ?? 0
|
this.indexMinute = indexMinute ?? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get annee() { return Math.floor(this.indexDate / RDD_JOURS_PAR_AN) }
|
||||||
|
get mois() { return Math.floor((this.indexDate % RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) }
|
||||||
|
get jour() { return (this.indexDate % RDD_JOURS_PAR_AN) % RDD_JOURS_PAR_MOIS }
|
||||||
|
get heure() { return Math.floor(this.indexMinute / RDD_MINUTES_PAR_HEURES) }
|
||||||
|
get minute() { return this.indexMinute % RDD_MINUTES_PAR_HEURES }
|
||||||
|
get round() { return ROUNDS_PAR_MINUTE * (this.indexMinute - Math.floor(this.indexMinute)) }
|
||||||
|
get angleHeure() { return this.indexMinute / RDD_MINUTES_PAR_JOUR * 360 - 45 }
|
||||||
|
get angleMinute() { return this.indexMinute / RDD_MINUTES_PAR_HEURES * 360 + 45 }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convertit le timestamp en une structure avec les informations utiles
|
* Convertit le timestamp en une structure avec les informations utiles
|
||||||
@@ -213,13 +253,6 @@ export class RdDTimestamp {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
get annee() { return Math.floor(this.indexDate / RDD_JOURS_PAR_AN) }
|
|
||||||
get mois() { return Math.floor((this.indexDate % RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) }
|
|
||||||
get jour() { return (this.indexDate % RDD_JOURS_PAR_AN) % RDD_JOURS_PAR_MOIS }
|
|
||||||
get heure() { return Math.floor(this.indexMinute / RDD_MINUTES_PAR_HEURES) }
|
|
||||||
get minute() { return this.indexMinute % RDD_MINUTES_PAR_HEURES }
|
|
||||||
get round() { return ROUNDS_PAR_MINUTE * (this.indexMinute - Math.floor(this.indexMinute)) }
|
|
||||||
|
|
||||||
formatDate() {
|
formatDate() {
|
||||||
const jour = this.jour + 1;
|
const jour = this.jour + 1;
|
||||||
const mois = RdDTimestamp.definition(this.mois).label;
|
const mois = RdDTimestamp.definition(this.mois).label;
|
||||||
@@ -227,6 +260,10 @@ export class RdDTimestamp {
|
|||||||
return `${jour} ${mois}` + (annee ? ' ' + annee : '');
|
return `${jour} ${mois}` + (annee ? ' ' + annee : '');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
formatDateHeure() {
|
||||||
|
return `${RdDTimestamp.definition(this.heure).label}, ${this.formatDate()}`;
|
||||||
|
}
|
||||||
|
|
||||||
nouveauJour() { return new RdDTimestamp({ indexDate: this.indexDate + 1, indexMinute: 0 }) }
|
nouveauJour() { return new RdDTimestamp({ indexDate: this.indexDate + 1, indexMinute: 0 }) }
|
||||||
|
|
||||||
nouvelleHeure() {
|
nouvelleHeure() {
|
||||||
@@ -250,7 +287,7 @@ export class RdDTimestamp {
|
|||||||
const heure = this.heure + heures;
|
const heure = this.heure + heures;
|
||||||
return new RdDTimestamp({
|
return new RdDTimestamp({
|
||||||
indexDate: this.indexDate + Math.floor(heure / RDD_HEURES_PAR_JOUR),
|
indexDate: this.indexDate + Math.floor(heure / RDD_HEURES_PAR_JOUR),
|
||||||
indexMinute: (this.indexMinute + (heure % RDD_HEURES_PAR_JOUR)) % (RDD_MINUTES_PAR_JOUR)
|
indexMinute: this.indexMinute + (heure % RDD_HEURES_PAR_JOUR) * RDD_MINUTES_PAR_HEURES
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
335
module/tirage/fenetre-recherche-tirage.js
Normal file
335
module/tirage/fenetre-recherche-tirage.js
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
import { RdDItem } from '../item.js';
|
||||||
|
import { HtmlUtility } from '../html-utility.js';
|
||||||
|
import { Misc } from "../misc.js";
|
||||||
|
import { CompendiumTableHelpers } from '../settings/system-compendiums.js';
|
||||||
|
import { RdDRaretes } from '../item/raretes.js';
|
||||||
|
import { Grammar } from '../grammar.js';
|
||||||
|
|
||||||
|
const FILTER_GROUPS = [
|
||||||
|
{ group: 'type', label: "Type d'objet" },
|
||||||
|
{ group: 'comestible', label: 'Alimentaire' },
|
||||||
|
{ group: 'utilisation', label: 'Utilisation' },
|
||||||
|
{ group: 'rarete', label: 'Rarete' },
|
||||||
|
{ group: 'qualite', label: 'Qualité' },
|
||||||
|
{ group: 'enc', label: 'Encombrement' },
|
||||||
|
{ group: 'prix', label: 'Prix' },
|
||||||
|
]
|
||||||
|
|
||||||
|
const FILTERS = [
|
||||||
|
{ group: 'comestible', code: 'comestible', label: 'Comestible', check: (item, milieux) => item.getUtilisation() == 'cuisine' },
|
||||||
|
{ group: 'comestible', code: 'pret', label: 'Préparé', check: (item, milieux) => item.getUtilisationCuisine() == 'pret' },
|
||||||
|
{ group: 'comestible', code: 'brut', label: 'A préparer', check: (item, milieux) => item.getUtilisationCuisine() == 'brut' },
|
||||||
|
{ group: 'comestible', code: 'boisson', label: 'Boisson', check: (item, milieux) => item.isBoisson() },
|
||||||
|
{ group: 'comestible', code: 'alcool', label: 'Alcool', check: (item, milieux) => item.isAlcool() },
|
||||||
|
{ group: 'comestible', code: 'immangeable', label: 'Immangeable', check: (item, milieux) => item.isInventaire() && item.getUtilisation() != 'cuisine' },
|
||||||
|
|
||||||
|
{ group: 'utilisation', code: 'alchimie', label: 'Alchimique', check: (item, milieux) => item.isInventaire() && item.getUtilisation() == 'alchimie' },
|
||||||
|
{ group: 'utilisation', code: 'soins', label: 'Médical', check: (item, milieux) => item.isInventaire() && item.getUtilisation() == 'soins' },
|
||||||
|
{ group: 'utilisation', code: 'poison', label: 'Toxique', check: (item, milieux) => item.isInventaire() && item.getUtilisation() == 'poison' },
|
||||||
|
{ group: 'utilisation', code: 'cuisine', label: 'Cuisine', check: (item, milieux) => item.isInventaire() && item.getUtilisation() == 'cuisine' },
|
||||||
|
{ group: 'utilisation', code: 'autres', label: 'Autres/inconnu', check: (item, milieux) => !item.isInventaire() || item.getUtilisation() == '' },
|
||||||
|
|
||||||
|
{ group: "qualite", code: "mauvaise", label: "Mauvaise (négative)", check: (item, milieux) => item.isInventaire() && item.system.qualite < 0 },
|
||||||
|
{ group: "qualite", code: "quelconque", label: "Quelconque (0)", check: (item, milieux) => item.isInventaire() && item.system.qualite == 0 },
|
||||||
|
{ group: "qualite", code: "correcte", label: "Correcte (1-3)", check: (item, milieux) => item.isInventaire() && 1 <= item.system.qualite && item.system.qualite <= 3 },
|
||||||
|
{ group: "qualite", code: "bonne", label: "Bonne (4-6)", check: (item, milieux) => item.isInventaire() && 4 <= item.system.qualite && item.system.qualite <= 6 },
|
||||||
|
{ group: "qualite", code: "excellente", label: "Excellente (7-9)", check: (item, milieux) => item.isInventaire() && 7 <= item.system.qualite && item.system.qualite <= 9 },
|
||||||
|
{ group: "qualite", code: "mythique", label: "Mythique (10+)", check: (item, milieux) => item.isInventaire() && 10 <= item.system.qualite },
|
||||||
|
|
||||||
|
{ group: "enc", code: "negligeable", label: "Négligeable (jusqu'à 0.1)", check: (item, milieux) => item.isInventaire() && item.system.encombrement <= 0.1 },
|
||||||
|
{ group: "enc", code: "leger", label: "Léger (0.1 à 0.5)", check: (item, milieux) => item.isInventaire() && 0.1 < item.system.encombrement && item.system.encombrement <= 0.5 },
|
||||||
|
{ group: "enc", code: "moyen", label: "Moyen (0.5 à 1.5)", check: (item, milieux) => item.isInventaire() && 0.5 < item.system.encombrement && item.system.encombrement <= 1.5 },
|
||||||
|
{ group: "enc", code: "lourd", label: "Lourd (1.5 à 3)", check: (item, milieux) => item.isInventaire() && 1.5 < item.system.encombrement && item.system.encombrement <= 3 },
|
||||||
|
{ group: "enc", code: "massif", label: "Massif (3 à 10)", check: (item, milieux) => item.isInventaire() && 3 < item.system.encombrement && item.system.encombrement <= 10 },
|
||||||
|
{ group: "enc", code: "anemort", label: "Un âne mort (plus de 10)", check: (item, milieux) => item.isInventaire() && 10 < item.system.encombrement },
|
||||||
|
|
||||||
|
{ group: "prix", code: "gratuit", label: "Gratuit", check: (item, milieux) => item.isInventaire() && item.system.cout == 0 },
|
||||||
|
{ group: "prix", code: "deniers", label: "Deniers (étain)", check: (item, milieux) => item.isInventaire() && 0 < item.system.cout && item.system.cout < 0.1 },
|
||||||
|
{ group: "prix", code: "bronze", label: "Sous (bronze)", check: (item, milieux) => item.isInventaire() && 0.1 <= item.system.cout && item.system.cout < 1 },
|
||||||
|
{ group: "prix", code: "sols", label: "Sols (argent)", check: (item, milieux) => item.isInventaire() && 1 <= item.system.cout && item.system.cout < 10 },
|
||||||
|
{ group: "prix", code: "dragons", label: "Dragons (or)", check: (item, milieux) => item.isInventaire() && 10 <= item.system.cout },
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
function $filterMilieux(milieux) {
|
||||||
|
return milieux.map(m => {
|
||||||
|
return {
|
||||||
|
code: m,
|
||||||
|
label: m,
|
||||||
|
check: (item, milieux) => item.isPresentDansMilieux(m)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function $filterRarete() {
|
||||||
|
return RdDRaretes.raretes()
|
||||||
|
.filter(it => it.frequence > 0)
|
||||||
|
.map(r => {
|
||||||
|
return {
|
||||||
|
group: 'rarete',
|
||||||
|
code: r.code,
|
||||||
|
label: r.label,
|
||||||
|
check: (item, milieux) => item.getRaretes(milieux).map(it => it.code).includes(r.code)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function $filterTypes() {
|
||||||
|
return RdDItem.getItemTypesInventaire().map(type => {
|
||||||
|
return {
|
||||||
|
group: 'type',
|
||||||
|
code: type,
|
||||||
|
label: Misc.typeName('Item', type),
|
||||||
|
check: (item, milieux) => item.type == type
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function $getAllFilters() {
|
||||||
|
return FILTERS
|
||||||
|
.concat($filterTypes())
|
||||||
|
.concat($filterRarete());
|
||||||
|
}
|
||||||
|
|
||||||
|
function $addFilterToGroup(groups, filter) {
|
||||||
|
if (filter.group && filter.code && filter.label) {
|
||||||
|
let fg = groups.find(g => g.group == filter.group);
|
||||||
|
if (fg == undefined) {
|
||||||
|
groups.push({ group: filter.group, label: filter.group, filters: [filter] })
|
||||||
|
}
|
||||||
|
else if (fg.filters == undefined) {
|
||||||
|
fg.filters = [filter];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fg.filters.push(filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
console.warn("Filtre incorrect, pas de groupe/code/label", filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function $loadFilters(parameters) {
|
||||||
|
$getAllFilters(parameters.milieux).forEach(f => $addFilterToGroup(parameters.filterGroups, f));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
export class FenetreRechercheTirage extends Application {
|
||||||
|
static get defaultOptions() {
|
||||||
|
return mergeObject(super.defaultOptions, {
|
||||||
|
template: "systems/foundryvtt-reve-de-dragon/templates/tirage/fenetre-recherche-tirage.hbs",
|
||||||
|
title: `Recherches et tirages`,
|
||||||
|
width: 600,
|
||||||
|
height: 600,
|
||||||
|
popOut: true,
|
||||||
|
dragDrop: [{ dragSelector: "a.content-link" }],
|
||||||
|
resizable: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static async create() {
|
||||||
|
const milieux = await game.system.rdd.environnement.milieux();
|
||||||
|
const parameters = {
|
||||||
|
milieux: milieux,
|
||||||
|
filterMilieux: $filterMilieux(milieux),
|
||||||
|
filterGroups: duplicate(FILTER_GROUPS).filter(it => it.group),
|
||||||
|
}
|
||||||
|
const options = {}
|
||||||
|
$loadFilters(parameters);
|
||||||
|
|
||||||
|
new FenetreRechercheTirage(parameters, options).render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(parameters, options) {
|
||||||
|
super(options);
|
||||||
|
this.parameters = parameters;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getData() {
|
||||||
|
return mergeObject(await super.getData(), this.parameters)
|
||||||
|
}
|
||||||
|
|
||||||
|
_canDragStart() { return true; }
|
||||||
|
_onDragStart(event) { }
|
||||||
|
|
||||||
|
_getHeaderButtons() {
|
||||||
|
let buttons = super._getHeaderButtons();
|
||||||
|
if (game.user.isGM) {
|
||||||
|
buttons.unshift({
|
||||||
|
class: "configurer",
|
||||||
|
label: "Configurer",
|
||||||
|
icon: "fas fa-cogs",
|
||||||
|
onclick: ev => this.configurer()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return buttons
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
this.html = html;
|
||||||
|
|
||||||
|
this.showFilterGroup(this.html, false);
|
||||||
|
|
||||||
|
this.html.find("a.section-filters-toggle").click(event => {
|
||||||
|
const groupDiv = this.html.find(event.currentTarget)?.parents('div.section-filters-root').first();
|
||||||
|
const visible = groupDiv.find('div.section-filters-content').first().is(":visible");
|
||||||
|
this.showFilterGroup(groupDiv, !visible)
|
||||||
|
});
|
||||||
|
|
||||||
|
this.html.find("input:is(.activate-filter-group,.activate-filter-milieu)").change(event => this.changeListeFiltresActifs())
|
||||||
|
|
||||||
|
this.html.find("a.supprimer-filtres").click(async event => this.supprimerFiltres())
|
||||||
|
|
||||||
|
this.html.find("a.recherche-filtres").click(async event => await this.recherche())
|
||||||
|
|
||||||
|
this.html.find("a.tirage-filtres").click(async event => {
|
||||||
|
const table = await this.buildTable();
|
||||||
|
const row = await CompendiumTableHelpers.getRandom(table, 'Item')
|
||||||
|
await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item');
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
showFilterGroup(groupDiv, show) {
|
||||||
|
if (groupDiv) {
|
||||||
|
HtmlUtility.showControlWhen(groupDiv.find('div.section-filters-content'), show);
|
||||||
|
HtmlUtility.showControlWhen(groupDiv.find('i.section-filters-hide'), show);
|
||||||
|
HtmlUtility.showControlWhen(groupDiv.find('i.section-filters-show'), !show);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
supprimerFiltres() {
|
||||||
|
this.html.find('input:is(.activate-filter-group,.activate-filter-milieu)').prop("checked", false);
|
||||||
|
this.html.find('div.liste-resultats-recherche').html('');
|
||||||
|
this.html.find('.section-filters-text input.recherche').val('');
|
||||||
|
}
|
||||||
|
|
||||||
|
async recherche() {
|
||||||
|
const table = await this.buildTable();
|
||||||
|
const htmlResultats = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs`, { resultats: table });
|
||||||
|
this.html.find('div.liste-resultats-recherche').html(htmlResultats);
|
||||||
|
this._dragDrop.forEach(dragDropHandler => dragDropHandler.bind(this.element[0]))
|
||||||
|
}
|
||||||
|
|
||||||
|
async buildTable() {
|
||||||
|
const milieux = this.getSelectedMilieux();
|
||||||
|
const filterItemMilieux = this.buildCheckedGroupFilter(milieux);
|
||||||
|
const filter = it => filterItemMilieux(it, milieux);
|
||||||
|
const itemFrequence = it => it.getFrequence(milieux);
|
||||||
|
return await game.system.rdd.environnement.buildTable(itemFrequence, filter)
|
||||||
|
}
|
||||||
|
|
||||||
|
buildMilieuxFilter(milieux) {
|
||||||
|
if (milieux) {
|
||||||
|
return this.buildOrFilter(this.parameters.filterMilieux.filter(it => milieux.includes(it.code)).map(f => f.check));
|
||||||
|
}
|
||||||
|
return (it, mi) => true;
|
||||||
|
}
|
||||||
|
buildFilterRechercheName() {
|
||||||
|
const recherche = this.html.find('.section-filters-text input.recherche').val();
|
||||||
|
if (recherche) {
|
||||||
|
return (it, mi) => Grammar.includesLowerCaseNoAccent(it.name, recherche);
|
||||||
|
}
|
||||||
|
return (it, mi) => true;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildCheckedGroupFilter(milieux) {
|
||||||
|
const filtersList = this.getGroupCheckedFilters()
|
||||||
|
.map(gf => this.buildOrFilter(gf.filters.map(f => f.check)));
|
||||||
|
filtersList.push(this.buildMilieuxFilter(milieux));
|
||||||
|
filtersList.push(this.buildFilterRechercheName());
|
||||||
|
return this.buildAndFilter(filtersList)
|
||||||
|
}
|
||||||
|
|
||||||
|
buildAndFilter(filters) { return filters.reduce((f1, f2) => { return (it, mi) => f1(it, mi) && f2(it, mi); }); }
|
||||||
|
buildOrFilter(filters) { return filters.reduce((f1, f2) => { return (it, mi) => f1(it, mi) || f2(it, mi); }); }
|
||||||
|
|
||||||
|
changeListeFiltresActifs() {
|
||||||
|
const milieux = this.getSelectedMilieux();
|
||||||
|
const summariesList = this.getGroupCheckedFilters()
|
||||||
|
.map(gf => {
|
||||||
|
return gf.group.label + ': ' + gf.filters
|
||||||
|
.map(f => f.label)
|
||||||
|
.reduce(Misc.joining(', '))
|
||||||
|
});
|
||||||
|
if (milieux) {
|
||||||
|
summariesList.push('Milieux: ' + this.parameters.filterMilieux.filter(f => milieux.includes(f.code)).map(f => f.label).reduce(Misc.joining(', ')))
|
||||||
|
}
|
||||||
|
const fullText = summariesList.length == 0 ? "" : summariesList.reduce(Misc.joining(' - '));
|
||||||
|
this.html.find('span.liste-filtres-actifs').text(fullText);
|
||||||
|
}
|
||||||
|
|
||||||
|
getGroupCheckedFilters() {
|
||||||
|
const checkedGroupFilters = jQuery.map(this.html.find('input.activate-filter-group:checked'), it => this.html.find(it))
|
||||||
|
.map(element => {
|
||||||
|
return {
|
||||||
|
group: element.data('group'),
|
||||||
|
code: element.data('code')
|
||||||
|
};
|
||||||
|
}).filter(it => it.group);
|
||||||
|
|
||||||
|
const entries = Object.entries(Misc.classify(checkedGroupFilters, it => it.group));
|
||||||
|
return entries.map(([key, list]) => {
|
||||||
|
const group = this.parameters.filterGroups.find(g => g.group == key);
|
||||||
|
const filters = list.map(it => group.filters.find(f => it.code == f.code));
|
||||||
|
return { group, filters };
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
getSelectedMilieux() {
|
||||||
|
const milieux = jQuery.map(this.html.find('input.activate-filter-milieu:checked'), it => {
|
||||||
|
return this.html.find(it).data('code');
|
||||||
|
});
|
||||||
|
return milieux.length == 0 ? undefined : milieux
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async configurer() {
|
||||||
|
FenetreRechercheConfiguration.create();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FenetreRechercheConfiguration extends Dialog {
|
||||||
|
static async create() {
|
||||||
|
const configuration = {
|
||||||
|
compendiums: game.packs.filter(it => it.metadata.type == 'Item').map(it => it.metadata)
|
||||||
|
.map(it => mergeObject({ selected: game.system.rdd.environnement.compendiums.includes(it.id) }, it))
|
||||||
|
}
|
||||||
|
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/tirage/fenetre-recherche-configuration.hbs", configuration);
|
||||||
|
new FenetreRechercheConfiguration(html).render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor(html) {
|
||||||
|
const options = {
|
||||||
|
classes: ["fenetre-recherche-configuration"],
|
||||||
|
width: 600,
|
||||||
|
height: 'fit-content',
|
||||||
|
'max-height': 600,
|
||||||
|
height: 'fit-content',
|
||||||
|
'z-index': 99999
|
||||||
|
};
|
||||||
|
const conf = {
|
||||||
|
title: 'Configuration de la recherche',
|
||||||
|
content: html,
|
||||||
|
buttons: {
|
||||||
|
"Sauvegarder": { label: "Sauvegarder", callback: async it => { await this.sauvegarder(); } }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
super(conf, options)
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
this.html = html;
|
||||||
|
super.activateListeners(html);
|
||||||
|
this.html.find("button.configuration-save").click(event => this.sauvegarder())
|
||||||
|
}
|
||||||
|
|
||||||
|
async sauvegarder() {
|
||||||
|
const compendiumIds = jQuery.map(this.html.find("input.select-compendium:checked"), it => {
|
||||||
|
return this.html.find(it).data('id');
|
||||||
|
});
|
||||||
|
await game.system.rdd.environnement.saveCompendiums(compendiumIds);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
}
|
@@ -226,9 +226,6 @@ export const TMRType = {
|
|||||||
desolation: { name: "désolation", genre: "f" }
|
desolation: { name: "désolation", genre: "f" }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
const caseSpecificModes = ["attache", "trounoir", "debordement", "reserve_extensible", "maitrisee"];
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const tmrRandomMovePatten =
|
const tmrRandomMovePatten =
|
||||||
[{ name: 'top', col: 0, row: -1 },
|
[{ name: 'top', col: 0, row: -1 },
|
||||||
@@ -239,8 +236,6 @@ const tmrRandomMovePatten =
|
|||||||
{ name: 'topleft', col: -1, row: -1 }
|
{ name: 'topleft', col: -1, row: -1 }
|
||||||
]
|
]
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class TMRUtility {
|
export class TMRUtility {
|
||||||
static init() {
|
static init() {
|
||||||
@@ -258,32 +253,25 @@ export class TMRUtility {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static verifyTMRCoord(coord) {
|
static verifyTMRCoord(coord) {
|
||||||
let TMRregexp = new RegExp(/([A-M])(\d+)/g);
|
return Grammar.equalsInsensitive(coord, 'Fleuve') || TMRUtility.getTMR(coord);
|
||||||
let res = TMRregexp.exec(coord);
|
|
||||||
if (res && res[1] && res[2]) {
|
|
||||||
if (res[2] > 0 && res[2] < 16) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getTMR(coord) {
|
static getTMR(coord) {
|
||||||
return TMRMapping[coord];
|
return coord == 'Fleuve' ? TMRMapping['D1'] : TMRMapping[coord];
|
||||||
}
|
}
|
||||||
|
|
||||||
static getTMRLabel(coord) {
|
static getTMRLabel(coord) {
|
||||||
return TMRMapping[coord]?.label ?? (coord + ": case inconnue");
|
return TMRUtility.getTMR(coord)?.label ?? (coord + ": case inconnue");
|
||||||
}
|
}
|
||||||
|
|
||||||
static getTMRType(coord) {
|
static getTMRType(coord) {
|
||||||
const tmr = TMRMapping[coord];
|
const tmr = TMRUtility.getTMR(coord);
|
||||||
return Misc.upperFirst(TMRType[tmr.type].name);
|
return Misc.upperFirst(TMRType[tmr.type].name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getTMRDescr(coord) {
|
static getTMRDescr(coord) {
|
||||||
const tmr = TMRMapping[coord];
|
const tmr = TMRUtility.getTMR(coord);
|
||||||
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label;
|
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,8 +1,10 @@
|
|||||||
import { Draconique } from "./draconique.js";
|
import { Draconique } from "./draconique.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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import { Misc } from "../misc.js";
|
import { TYPES } from "../item.js";
|
||||||
import { TMRUtility } from "../tmr-utility.js";
|
import { TMRUtility } from "../tmr-utility.js";
|
||||||
import { PixiTMR } from "./pixi-tmr.js";
|
import { PixiTMR } from "./pixi-tmr.js";
|
||||||
|
|
||||||
@@ -9,10 +9,10 @@ const registeredEffects = [
|
|||||||
* Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR
|
* Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR
|
||||||
*/
|
*/
|
||||||
export class Draconique {
|
export class Draconique {
|
||||||
static isCaseTMR(item) { return item.type == 'casetmr'; }
|
static isCaseTMR(item) { return item.type == TYPES.casetmr; }
|
||||||
static isQueueDragon(item) { return item.type == 'queue' || item.type == 'ombre'; }
|
static isQueueDragon(item) { return item.isQueueDragon(); }
|
||||||
static isSouffleDragon(item) { return item.type == 'souffle'; }
|
static isSouffleDragon(item) {return item.type == TYPES.souffle; }
|
||||||
static isTeteDragon(item) { return item.type == '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); }
|
||||||
|
|
||||||
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.system.coord); }
|
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.system.coord); }
|
||||||
@@ -91,6 +91,8 @@ export class Draconique {
|
|||||||
coordTMR: coordTMR
|
coordTMR: coordTMR
|
||||||
};
|
};
|
||||||
token[type ?? this.code()] = linkData;
|
token[type ?? this.code()] = linkData;
|
||||||
|
console.log("SPRITE: ", token.sprite)
|
||||||
|
//PixiTMR.getImgFromCode()
|
||||||
pixiTMR.addTooltip(token.sprite, this.tooltip(linkData));
|
pixiTMR.addTooltip(token.sprite, this.tooltip(linkData));
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
@@ -18,6 +18,7 @@ import { Periple } from "./periple.js";
|
|||||||
import { UrgenceDraconique } from "./urgence-draconique.js";
|
import { UrgenceDraconique } from "./urgence-draconique.js";
|
||||||
import { Grammar } from "../grammar.js";
|
import { Grammar } from "../grammar.js";
|
||||||
import { AugmentationSeuil } from "./augmentation-seuil.js";
|
import { AugmentationSeuil } from "./augmentation-seuil.js";
|
||||||
|
import { TYPES } from "../item.js";
|
||||||
|
|
||||||
|
|
||||||
export class EffetsDraconiques {
|
export class EffetsDraconiques {
|
||||||
@@ -114,45 +115,56 @@ export class EffetsDraconiques {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static filterItems(actor, filter, name) {
|
static tetesDragon(actor, name) {
|
||||||
return actor.filterItems(filter)
|
return actor.itemTypes[TYPES.tete].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
|
||||||
.filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
|
}
|
||||||
|
|
||||||
|
static soufflesDragon(actor, name) {
|
||||||
|
return actor.itemTypes[TYPES.souffle].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static queuesDragon(actor, name) {
|
||||||
|
return actor.filterItems(it => it.isQueueDragon() && Grammar.includesLowerCaseNoAccent(it.name, name));
|
||||||
|
}
|
||||||
|
|
||||||
|
static queuesSoufflesDragon(actor, name) {
|
||||||
|
return actor.filterItems(it => [TYPES.queue, TYPES.ombre, TYPES.souffle].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, name));
|
||||||
}
|
}
|
||||||
|
|
||||||
static countAugmentationSeuil(actor) {
|
static countAugmentationSeuil(actor) {
|
||||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'Augmentation du seuil de rêve').length;
|
return EffetsDraconiques.tetesDragon(actor, 'Augmentation du seuil de rêve').length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isDonDoubleReve(actor) {
|
static isDonDoubleReve(actor) {
|
||||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'Don de double-rêve').length>0;
|
return EffetsDraconiques.tetesDragon(actor, 'Don de double-rêve').length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isConnaissanceFleuve(actor) {
|
static isConnaissanceFleuve(actor) {
|
||||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'connaissance du fleuve').length>0;
|
return EffetsDraconiques.tetesDragon(actor, 'connaissance du fleuve').length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isReserveEnSecurite(actor) {
|
static isReserveEnSecurite(actor) {
|
||||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, 'réserve en sécurité').length>0;
|
return EffetsDraconiques.tetesDragon(actor, 'réserve en sécurité').length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isDeplacementAccelere(actor) {
|
static isDeplacementAccelere(actor) {
|
||||||
return EffetsDraconiques.filterItems(actor, Draconique.isTeteDragon, ' déplacement accéléré').length>0;
|
return EffetsDraconiques.tetesDragon(actor, 'déplacement accéléré').length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isDoubleResistanceFleuve(actor) {
|
static isDoubleResistanceFleuve(actor) {
|
||||||
return EffetsDraconiques.filterItems(actor, Draconique.isSouffleDragon, 'résistance du fleuve').length>0;
|
return EffetsDraconiques.soufflesDragon(actor, 'résistance du fleuve').length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static countInertieDraconique(actor) {
|
static countInertieDraconique(actor) {
|
||||||
return EffetsDraconiques.filterItems(actor, Draconique.isQueueDragon, 'inertie draconique').length;
|
return EffetsDraconiques.queuesDragon(actor, 'inertie draconique').length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static countMonteeLaborieuse(actor) {
|
static countMonteeLaborieuse(actor) {
|
||||||
return EffetsDraconiques.filterItems(actor, Draconique.isQueueSouffle, 'montée laborieuse').length;
|
return EffetsDraconiques.queuesSoufflesDragon(actor, 'montée laborieuse').length;
|
||||||
}
|
}
|
||||||
|
|
||||||
static mauvaiseRencontre(actor) {
|
static mauvaiseRencontre(actor) {
|
||||||
const mauvaisesRencontres = EffetsDraconiques.filterItems(actor, Draconique.isQueueSouffle, 'mauvaise rencontre');
|
const mauvaisesRencontres = EffetsDraconiques.queuesSoufflesDragon(actor, 'mauvaise rencontre');
|
||||||
return mauvaisesRencontres.length > 0 ? mauvaisesRencontres[0] : undefined;
|
return mauvaisesRencontres.length > 0 ? mauvaisesRencontres[0] : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,8 +176,12 @@ export class EffetsDraconiques {
|
|||||||
return actor.items.find(it => EffetsDraconiques.urgenceDraconique.match(it));
|
return actor.items.find(it => EffetsDraconiques.urgenceDraconique.match(it));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static isSujetInsomnie(actor) {
|
||||||
|
return EffetsDraconiques.queuesDragon(actor, 'Insomnie').length > 0 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
static isPeage(actor) {
|
static isPeage(actor) {
|
||||||
return EffetsDraconiques.filterItems(actor, Draconique.isSouffleDragon, 'péage').length > 0;
|
return EffetsDraconiques.soufflesDragon(actor, 'péage').length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -1,7 +1,8 @@
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ExperienceLog, XP_TOPIC } from "../actor/experience-log.js";
|
||||||
import { Poetique } from "./poetique.js";
|
import { ChatUtility } from "../chat-utility.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { Poetique } from "../poetique.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { RdDDice } from "../rdd-dice.js";
|
||||||
|
import { TMRUtility } from "../tmr-utility.js";
|
||||||
|
|
||||||
export class EffetsRencontre {
|
export class EffetsRencontre {
|
||||||
|
|
||||||
@@ -53,9 +54,10 @@ export class EffetsRencontre {
|
|||||||
static xp_sort_force = async (dialog, context) => {
|
static xp_sort_force = async (dialog, context) => {
|
||||||
let competence = context.competence;
|
let competence = context.competence;
|
||||||
if (competence) {
|
if (competence) {
|
||||||
const xpSort = Misc.toInt(competence.system.xp_sort) + context.rencontre.system.force;
|
const fromXpSort = Number(competence.system.xp_sort);
|
||||||
await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': xpSort }]);
|
const toXpSort = fromXpSort + context.rencontre.system.force;
|
||||||
await this.updateExperienceLog("XP Sort", xpSort, `Rencontre d'un ${context.rencontre.name} en TMR`);
|
await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': toXpSort }]);
|
||||||
|
await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXpSort, toXpSort, `${competence.name} - ${context.rencontre.name} en TMR`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@@ -20,18 +20,20 @@ export class PixiTMR {
|
|||||||
this.callbacksOnAnimate = [];
|
this.callbacksOnAnimate = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
load( onLoad = (loader, resources) => {} ) {
|
async load( onLoad = (loader, resources) => {} ) {
|
||||||
let loader = this.pixiApp.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)) {
|
||||||
loader = loader.add(name, img);
|
const texture = await PIXI.Assets.load(img);
|
||||||
|
let image = PIXI.Sprite.from(texture);
|
||||||
}
|
}
|
||||||
loader.onError.add((error, reason) => { console.log("ERROR", error, reason) });
|
onLoad();
|
||||||
loader.load( (loader, resources) => {
|
|
||||||
onLoad(loader, resources);
|
|
||||||
for (let onAnimate of this.callbacksOnAnimate) {
|
for (let onAnimate of this.callbacksOnAnimate) {
|
||||||
onAnimate();
|
onAnimate();
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
static getImgFromCode(code) {
|
||||||
|
return PixiTMR.textures[code]
|
||||||
}
|
}
|
||||||
|
|
||||||
static register(name, img) {
|
static register(name, img) {
|
||||||
@@ -44,7 +46,9 @@ export class PixiTMR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
carteTmr(code) {
|
carteTmr(code) {
|
||||||
const carteTmr = new PIXI.Sprite(PIXI.utils.TextureCache[code]);
|
let img = PixiTMR.getImgFromCode(code)
|
||||||
|
const carteTmr = new PIXI.Sprite(PIXI.utils.TextureCache[img]);
|
||||||
|
console.log(code, carteTmr)
|
||||||
// Setup the position of the TMR
|
// Setup the position of the TMR
|
||||||
carteTmr.x = 0;
|
carteTmr.x = 0;
|
||||||
carteTmr.y = 0;
|
carteTmr.y = 0;
|
||||||
@@ -52,7 +56,8 @@ export class PixiTMR {
|
|||||||
carteTmr.height = 860;
|
carteTmr.height = 860;
|
||||||
// Rotate around the center
|
// Rotate around the center
|
||||||
carteTmr.anchor.set(0);
|
carteTmr.anchor.set(0);
|
||||||
carteTmr.interactive = true;
|
carteTmr.eventMode = 'dynamic'; // PIXI 7 : Not sure ..
|
||||||
|
// This one is deprecated ; carteTmr.interactive = true;
|
||||||
carteTmr.buttonMode = true;
|
carteTmr.buttonMode = true;
|
||||||
carteTmr.tmrObject = this;
|
carteTmr.tmrObject = this;
|
||||||
if (!this.tmrObject.viewOnly) {
|
if (!this.tmrObject.viewOnly) {
|
||||||
@@ -63,9 +68,10 @@ export class PixiTMR {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sprite(code, options = {}) {
|
sprite(code, options = {}) {
|
||||||
const texture = PIXI.utils.TextureCache[code];
|
let img = PixiTMR.getImgFromCode(code)
|
||||||
|
const texture = PIXI.utils.TextureCache[img];
|
||||||
if (!texture) {
|
if (!texture) {
|
||||||
console.error("Texture manquante", code)
|
console.error("Texture manquante", code, PIXI.utils.TextureCache)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let sprite = new PIXI.Sprite(texture);
|
let sprite = new PIXI.Sprite(texture);
|
||||||
@@ -97,7 +103,8 @@ export class PixiTMR {
|
|||||||
sprite.tooltip = new PIXI.Text(text, tooltipStyle);
|
sprite.tooltip = new PIXI.Text(text, tooltipStyle);
|
||||||
sprite.tooltip.zIndex = tmrTokenZIndex.tooltip;
|
sprite.tooltip.zIndex = tmrTokenZIndex.tooltip;
|
||||||
sprite.isOver = false;
|
sprite.isOver = false;
|
||||||
sprite.interactive = true;
|
// Deprecated : sprite.interactive = true;
|
||||||
|
sprite.eventMode = 'dynamic'; // PIXI 7 To be checked
|
||||||
sprite.on('pointerdown', event => this.onClickBackground(event))
|
sprite.on('pointerdown', event => this.onClickBackground(event))
|
||||||
.on('pointerover', () => this.onShowTooltip(sprite))
|
.on('pointerover', () => this.onShowTooltip(sprite))
|
||||||
.on('pointerout', () => this.onHideTooltip(sprite));
|
.on('pointerout', () => this.onHideTooltip(sprite));
|
||||||
|
File diff suppressed because one or more lines are too long
BIN
packs/animaux/000028.ldb
Normal file
BIN
packs/animaux/000028.ldb
Normal file
Binary file not shown.
0
packs/animaux/000047.log
Normal file
0
packs/animaux/000047.log
Normal file
1
packs/animaux/CURRENT
Normal file
1
packs/animaux/CURRENT
Normal file
@@ -0,0 +1 @@
|
|||||||
|
MANIFEST-000045
|
0
packs/animaux/LOCK
Normal file
0
packs/animaux/LOCK
Normal file
7
packs/animaux/LOG
Normal file
7
packs/animaux/LOG
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
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)
|
7
packs/animaux/LOG.old
Normal file
7
packs/animaux/LOG.old
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
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)
|
BIN
packs/animaux/MANIFEST-000045
Normal file
BIN
packs/animaux/MANIFEST-000045
Normal file
Binary file not shown.
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user