Compare commits
No commits in common. "v10" and "foundryvtt-reve-de-dragon-10.3.17" have entirely different histories.
v10
...
foundryvtt
5
.gitignore
vendored
@ -1,10 +1,5 @@
|
|||||||
.vscode/settings.json
|
.vscode/settings.json
|
||||||
.idea
|
.idea
|
||||||
.history
|
|
||||||
todo.md
|
todo.md
|
||||||
/.vscode
|
/.vscode
|
||||||
/ignored/
|
/ignored/
|
||||||
/node_modules/
|
|
||||||
/jsconfig.json
|
|
||||||
/package.json
|
|
||||||
/package-lock.json
|
|
||||||
|
302
changelog.md
@ -1,298 +1,10 @@
|
|||||||
# v10.7 - L'os de Sémolosse
|
==================================================================
|
||||||
|
v0.9.2 - 05/09/2020
|
||||||
|
|
||||||
## v10.7.20 - la poigne de Sémolosse
|
Erreur de calcul sur points de vie
|
||||||
- correction de méthodes qui filtrent les items
|
Gestion différente des compétences "troncs"
|
||||||
- recherche de cases TMR
|
|
||||||
- recherche de tâches de lecture
|
|
||||||
- recherche d'armure (pour le malus armure)
|
|
||||||
- recherche de potions
|
|
||||||
|
|
||||||
## v10.7.20 - la poigne de Sémolosse
|
==================================================================
|
||||||
- correction de l'empoignade
|
v0.9.1 - 03/09/2020
|
||||||
- les items d'empoignade sont ajoutés par le MJ quand nécessaire
|
|
||||||
- seul le joueur propriétaire du personnage peut effectuer ses choix et actions d'empoignade
|
|
||||||
- les caractéristiques du défenseur sont utilisées pour la défense
|
|
||||||
- la difficulté d'attaque est imposée au défenseur
|
|
||||||
- les attaques particulières sont en finesse (p133)
|
|
||||||
- on peut entraîner au sol dès 2 points d'empoignade
|
|
||||||
- les actions liée à l'immobilisation sont proposées en fin de round
|
|
||||||
|
|
||||||
## v10.7.19 - les fantômes de Sémolosse
|
Initial official release
|
||||||
- les créatures ont maintenant le droit d'avoir des compétences de tir, lancer, mêlée, armes naturelles, parade.
|
|
||||||
- les créatures armées utilisent la bonne phase d'initiative
|
|
||||||
- correction des possessions
|
|
||||||
- la difficulté de la défense est imposée par l'attaque
|
|
||||||
- une attaque particulière de possession est en finesse
|
|
||||||
- le rêve actuel des personnages est bien utilisé
|
|
||||||
- correction des achats par le MJ sans acteur sélectionné
|
|
||||||
|
|
||||||
## v10.7.18 - le repos de Sémolosse
|
|
||||||
- correction des dates de blessures qui ne marchaient plus
|
|
||||||
|
|
||||||
## v10.7.17 - le doigt du destin de Sémolosse
|
|
||||||
- correction de la validation d'encaissement par le MJ
|
|
||||||
|
|
||||||
## v10.7.16 - la morsure de Sémolosse
|
|
||||||
- correction de l'affichage des objets suite à confusion
|
|
||||||
- correction de liens dans la liste des équipements
|
|
||||||
|
|
||||||
## v10.7.14 - l'expérience de Sémolosse
|
|
||||||
- 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 Sémolosse
|
|
||||||
- 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 Sémolosse
|
|
||||||
- Fix sur la projection au sol.
|
|
||||||
|
|
||||||
## v10.7.10 - Le Pugilat de Sémolosse
|
|
||||||
- Gestion de l'empoignade
|
|
||||||
- Corrections sur l'initiative
|
|
||||||
- Correction sur l'equipement des vêtements et bijoux
|
|
||||||
|
|
||||||
## v10.7.9 - Le Pugilat de Sémolosse
|
|
||||||
|
|
||||||
- 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 Sémolosse
|
|
||||||
- correction des récupérations de blessures
|
|
||||||
- la fin de château dormant se passe normalement
|
|
||||||
|
|
||||||
## v10.7.1 - L'os de Sémolosse
|
|
||||||
- Fix rapide sur les jets de carac qui n'étaient plus possibles
|
|
||||||
|
|
||||||
## v10.7.0 - L'os de Sémolosse
|
|
||||||
- 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
|
|
||||||
|
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 4.8 KiB |
Before Width: | Height: | Size: 7.6 KiB |
Before Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 6.0 KiB |
Before Width: | Height: | Size: 6.2 KiB |
Before Width: | Height: | Size: 6.4 KiB |
Before Width: | Height: | Size: 7.0 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.9 KiB |
Before Width: | Height: | Size: 5.1 KiB |
Before Width: | Height: | Size: 5.5 KiB |
64
lang/fr.json
@ -3,52 +3,48 @@
|
|||||||
"TypePersonnage": "Personnage",
|
"TypePersonnage": "Personnage",
|
||||||
"TypeCreature": "Créature",
|
"TypeCreature": "Créature",
|
||||||
"TypeEntite": "Entité de cauchemar",
|
"TypeEntite": "Entité de cauchemar",
|
||||||
"TypeCommerce": "Commerce",
|
|
||||||
"TypeVehicule": "Véhicule"
|
"TypeVehicule": "Véhicule"
|
||||||
},
|
},
|
||||||
"ITEM": {
|
"ITEM": {
|
||||||
"TypeArme": "Arme",
|
"TypeObjet": "Objet",
|
||||||
"TypeArmure": "Armure",
|
"TypeGemme": "Gemme",
|
||||||
"TypeBlessure": "Blessure",
|
|
||||||
"TypeCasetmr": "TMR spéciale",
|
|
||||||
"TypeChant": "Chant",
|
|
||||||
"TypeCompetence": "Compétence",
|
"TypeCompetence": "Compétence",
|
||||||
"TypeCompetencecreature": "Compétence de créature",
|
"TypeCompetencecreature": "Compétence de créature",
|
||||||
"TypeConteneur": "Conteneur",
|
|
||||||
"TypeDanse": "Danse",
|
|
||||||
"TypeExtraitpoetique": "Extrait poetique",
|
|
||||||
"TypeFaune": "Faune",
|
|
||||||
"TypeGemme": "Gemme",
|
|
||||||
"TypeHerbe": "Herbe",
|
|
||||||
"TypeIngredient": "Ingrédient",
|
|
||||||
"TypeJeu": "Jeu",
|
|
||||||
"TypeLivre": "Livre",
|
|
||||||
"TypeMaladie": "Maladie",
|
"TypeMaladie": "Maladie",
|
||||||
"TypeMeditation": "Méditation",
|
|
||||||
"TypeMonnaie": "Monnaie",
|
|
||||||
"TypeMunition": "Munition",
|
|
||||||
"TypeMusique": "Musique",
|
|
||||||
"TypeNombreastral": "Nombre astral",
|
|
||||||
"TypeNourritureboisson": "Nourriture & boisson",
|
|
||||||
"TypeObjet": "Objet",
|
|
||||||
"TypeOeuvre": "Oeuvre",
|
|
||||||
"TypeOmbre": "Ombre de Thanatos",
|
|
||||||
"TypePlante": "Plante",
|
|
||||||
"TypePoison": "Poison",
|
"TypePoison": "Poison",
|
||||||
"TypePossession": "Possession",
|
"TypeNombreastral": "Nombre astral",
|
||||||
|
"TypeTarot": "Carte de tarot",
|
||||||
|
"TypeCasetmr": "TMR spéciale",
|
||||||
|
"TypeRencontre": "Rencontre TMR",
|
||||||
|
"TypeMunition": "Munition",
|
||||||
|
"TypeMonnaie": "Monnaie",
|
||||||
|
"TypeHerbe": "Herbe ou plante",
|
||||||
|
"TypeIngredient": "Ingrédient",
|
||||||
|
"TypeFaune": "Faune",
|
||||||
|
"TypeLivre": "Livre",
|
||||||
"TypePotion": "Potion",
|
"TypePotion": "Potion",
|
||||||
"TypeQueue": "Queue de Dragon",
|
"TypeArme": "Arme",
|
||||||
|
"TypeArmure": "Armure",
|
||||||
|
"TypeConteneur": "Conteneur",
|
||||||
|
"TypeNourritureboisson": "Nourriture & boisson",
|
||||||
|
"TypeChant": "Chant",
|
||||||
|
"TypeDanse": "Danse",
|
||||||
|
"TypeMusique": "Musique",
|
||||||
|
"TypeOeuvre": "Oeuvre",
|
||||||
|
"TypeTache": "Tâche",
|
||||||
|
"TypeJeu": "Jeu",
|
||||||
"TypeRecettealchimique": "Recette alchimique",
|
"TypeRecettealchimique": "Recette alchimique",
|
||||||
"TypeRecettecuisine": "Recette de cuisine",
|
"TypeRecettecuisine": "Recette de cuisine",
|
||||||
"TypeRencontre": "Rencontre TMR",
|
|
||||||
"TypeService": "Service",
|
|
||||||
"TypeSignedraconique": "Signe draconique",
|
|
||||||
"TypeSort": "Sort",
|
"TypeSort": "Sort",
|
||||||
"TypeSortreserve": "Sort en réserve",
|
"TypeMeditation": "Méditation",
|
||||||
|
"TypeSignedraconique": "Signe draconique",
|
||||||
|
"TypeQueue": "Queue de Dragon",
|
||||||
|
"TypeOmbre": "Ombre de Thanatos",
|
||||||
"TypeSouffle": "Souffle de Dragon",
|
"TypeSouffle": "Souffle de Dragon",
|
||||||
"TypeTache": "Tâche",
|
"TypeTete": "Tête de Dragon",
|
||||||
"TypeTarot": "Carte de tarot",
|
"TypePossession": "Possession",
|
||||||
"TypeTete": "Tête de Dragon"
|
"TypeSortreserve": "Sort en réserve",
|
||||||
|
"TypeExtraitpoetique": "Extrait poetique"
|
||||||
},
|
},
|
||||||
"EFFECT": {
|
"EFFECT": {
|
||||||
"StatusStunned": "Sonné",
|
"StatusStunned": "Sonné",
|
||||||
|
@ -40,4 +40,11 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
|
|||||||
this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value));
|
this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** @override */
|
||||||
|
_updateObject(event, formData) {
|
||||||
|
// Update the Actor
|
||||||
|
return this.object.update(formData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
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 {
|
||||||
|
|
||||||
@ -11,16 +9,10 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
|
|||||||
template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html",
|
template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html",
|
||||||
width: 640,
|
width: 640,
|
||||||
height: 720,
|
height: 720,
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac"}],
|
||||||
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 */
|
||||||
@ -33,33 +25,16 @@ export class RdDActorEntiteSheet extends RdDActorSheet {
|
|||||||
// On competence change
|
// On competence change
|
||||||
this.html.find('.creature-carac').change(async event => {
|
this.html.find('.creature-carac').change(async event => {
|
||||||
let compName = event.currentTarget.attributes.compname.value;
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
this.actor.updateCreatureCompetence(compName, "carac_value", parseInt(event.target.value));
|
this.actor.updateCreatureCompetence( compName, "carac_value", parseInt(event.target.value) );
|
||||||
});
|
} );
|
||||||
this.html.find('.creature-niveau').change(async event => {
|
this.html.find('.creature-niveau').change(async event => {
|
||||||
let compName = event.currentTarget.attributes.compname.value;
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
this.actor.updateCreatureCompetence(compName, "niveau", parseInt(event.target.value));
|
this.actor.updateCreatureCompetence( compName, "niveau", parseInt(event.target.value) );
|
||||||
});
|
} );
|
||||||
this.html.find('.creature-dommages').change(async event => {
|
this.html.find('.creature-dommages').change(async event => {
|
||||||
let compName = event.currentTarget.attributes.compname.value;
|
let compName = event.currentTarget.attributes.compname.value;
|
||||||
this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value));
|
this.actor.updateCreatureCompetence( compName, "dommages", parseInt(event.target.value) );
|
||||||
});
|
} );
|
||||||
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 });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -10,18 +10,15 @@ import { DialogSplitItem } from "./dialog-split-item.js";
|
|||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||||
import { STATUSES } from "./settings/status-effects.js";
|
import { STATUSES } from "./settings/status-effects.js";
|
||||||
|
import { Monnaie } from "./item-monnaie.js";
|
||||||
import { MAINS_DIRECTRICES } from "./actor.js";
|
import { MAINS_DIRECTRICES } from "./actor.js";
|
||||||
import { RdDBaseActorSheet } from "./actor/base-actor-sheet.js";
|
|
||||||
import { RdDItem } from "./item.js";
|
|
||||||
import { RdDItemBlessure } from "./item/blessure.js";
|
|
||||||
import { RdDEmpoignade } from "./rdd-empoignade.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/**
|
/**
|
||||||
* Extend the basic ActorSheet with some very simple modifications
|
* Extend the basic ActorSheet with some very simple modifications
|
||||||
* @extends {ActorSheet}
|
* @extends {ActorSheet}
|
||||||
*/
|
*/
|
||||||
export class RdDActorSheet extends RdDBaseActorSheet {
|
export class RdDActorSheet extends ActorSheet {
|
||||||
|
|
||||||
/** @override */
|
/** @override */
|
||||||
static get defaultOptions() {
|
static get defaultOptions() {
|
||||||
@ -39,26 +36,42 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getData() {
|
async getData() {
|
||||||
let formData = await super.getData();
|
this.timerRecherche = undefined;
|
||||||
mergeObject(formData,
|
this.actor.computeEtatGeneral();
|
||||||
{
|
|
||||||
|
let formData = {
|
||||||
|
title: this.title,
|
||||||
|
id: this.actor.id,
|
||||||
|
type: this.actor.type,
|
||||||
|
img: this.actor.img,
|
||||||
|
name: this.actor.name,
|
||||||
editable: this.isEditable,
|
editable: this.isEditable,
|
||||||
cssClass: this.isEditable ? "editable" : "locked",
|
cssClass: this.isEditable ? "editable" : "locked",
|
||||||
|
system: foundry.utils.deepClone(this.actor.system),
|
||||||
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
|
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)),
|
||||||
limited: this.actor.limited,
|
limited: this.actor.limited,
|
||||||
|
options: this.options,
|
||||||
owner: this.actor.isOwner,
|
owner: this.actor.isOwner,
|
||||||
biographie: await TextEditor.enrichHTML(this.actor.system.biographie, { async: true }),
|
description: await TextEditor.enrichHTML(this.object.system.description, { async: true }),
|
||||||
notes: await TextEditor.enrichHTML(this.actor.system.notes, { async: true }),
|
biographie: await TextEditor.enrichHTML(this.object.system.biographie, { async: true }),
|
||||||
});
|
notes: await TextEditor.enrichHTML(this.object.system.notes, { async: true }),
|
||||||
mergeObject(formData.calc, {
|
notesmj: await TextEditor.enrichHTML(this.object.system.notesmj, { async: true }),
|
||||||
|
calc: {
|
||||||
|
fortune: Monnaie.getFortune(this.actor),
|
||||||
|
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
|
||||||
surenc: this.actor.computeMalusSurEncombrement(),
|
surenc: this.actor.computeMalusSurEncombrement(),
|
||||||
|
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
||||||
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
|
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
|
||||||
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
|
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
|
||||||
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
|
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
|
||||||
surEncombrementMessage: this.actor.getMessageSurEncombrement(),
|
surEncombrementMessage: this.actor.getMessageSurEncombrement(),
|
||||||
})
|
},
|
||||||
|
}
|
||||||
|
formData.options.isGM = game.user.isGM;
|
||||||
|
|
||||||
this.timerRecherche = undefined;
|
RdDUtility.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
||||||
|
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||||
|
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||||
|
|
||||||
if (formData.type == 'personnage') {
|
if (formData.type == 'personnage') {
|
||||||
formData.options.mainsDirectrices = MAINS_DIRECTRICES;
|
formData.options.mainsDirectrices = MAINS_DIRECTRICES;
|
||||||
@ -68,9 +81,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.isHidden = this.options.recherche
|
item.system.isVisible = this.options.recherche
|
||||||
? !item.isNomLike(this.options.recherche.text)
|
? RdDItemCompetence.nomContientTexte(item, 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);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -84,7 +97,6 @@ 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;
|
||||||
|
|
||||||
@ -113,27 +125,28 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
/* -------------------------------------------- */ /** @override */
|
/* -------------------------------------------- */ /** @override */
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
this.html = 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 => {
|
this.html.find('.item-split').click(async event => {
|
||||||
const item = RdDSheetUtility.getItem(event, this.actor);
|
const item = RdDSheetUtility.getItem(event, this.actor);
|
||||||
item?.actionPrincipale(this.actor, async () => this.render())
|
RdDSheetUtility.splitItem(item, this.actor);
|
||||||
});
|
});
|
||||||
|
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.confirmerSuppressionItem(this, RdDSheetUtility.getItem(event, this.actor)));
|
||||||
|
this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente());
|
||||||
|
this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItem());
|
||||||
|
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor));
|
||||||
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 => {
|
||||||
@ -146,13 +159,6 @@ 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();
|
||||||
})
|
})
|
||||||
@ -168,31 +174,39 @@ 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-un-objet').click(async event => {
|
||||||
this.html.find('.creer-tache-blessure-grave').click(async event => RdDItemBlessure.createTacheSoinBlessure(this.actor, 4));
|
RdDUtility.selectObjetType(this);
|
||||||
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();
|
RdDUtility.selectTypeOeuvre(this);
|
||||||
|
});
|
||||||
|
this.html.find('.nettoyer-conteneurs').click(async event => {
|
||||||
|
this.actor.nettoyerConteneurs();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.blessure-premierssoins-done').change(async event => {
|
// Blessure control
|
||||||
const blessure = this.getBlessure(event);
|
this.html.find('.blessure-control').click(async event => {
|
||||||
await blessure?.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } });
|
const tr = this.html.find(event.currentTarget).parents(".item");
|
||||||
|
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 => {
|
|
||||||
const blessure = this.getBlessure(event);
|
// Blessure data
|
||||||
await blessure?.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } })
|
this.html.find('.blessure-soins').change(async event => {
|
||||||
});
|
const tr = this.html.find(event.currentTarget).parents(".item");
|
||||||
this.html.find('.blessure-premierssoins-bonus').change(async event => {
|
let btype = tr.data('blessure-type');
|
||||||
const blessure = this.getBlessure(event);
|
let index = tr.data('blessure-index');
|
||||||
await blessure?.setSoinsBlessure({ premierssoins: { bonus: Number(event.currentTarget.value) } })
|
let psoins = tr.find('.blessure-premiers_soins').val();
|
||||||
});
|
let pcomplets = tr.find('.blessure-soins_complets').val();
|
||||||
this.html.find('.blessure-soinscomplets-bonus').change(async event => {
|
let jours = tr.find('.blessure-jours').val();
|
||||||
const blessure = this.getBlessure(event);
|
let loc = tr.find('.blessure-localisation').val();
|
||||||
await blessure?.setSoinsBlessure({ soinscomplets: { bonus: Number(event.currentTarget.value) } })
|
let psdone = tr.find('.blessure-psdone:checked').val();
|
||||||
|
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
|
||||||
@ -264,14 +278,9 @@ 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', true);
|
this.actor.rollCarac('reve-actuel');
|
||||||
});
|
});
|
||||||
|
|
||||||
// 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);
|
||||||
@ -316,6 +325,10 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
await this.actor.removeEffects();
|
await this.actor.removeEffects();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
this.html.find('.conteneur-name a').click(async event => {
|
||||||
|
RdDUtility.toggleAfficheContenu(RdDSheetUtility.getItemId(event));
|
||||||
|
this.render(true);
|
||||||
|
});
|
||||||
this.html.find('.carac-xp-augmenter').click(async event => {
|
this.html.find('.carac-xp-augmenter').click(async event => {
|
||||||
let caracName = event.currentTarget.name.replace("augmenter.", "");
|
let caracName = event.currentTarget.name.replace("augmenter.", "");
|
||||||
this.actor.updateCaracXPAuto(caracName);
|
this.actor.updateCaracXPAuto(caracName);
|
||||||
@ -365,6 +378,29 @@ 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);
|
||||||
@ -382,12 +418,19 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
this.actor.setPointsDeSeuil(event.currentTarget.value);
|
this.actor.setPointsDeSeuil(event.currentTarget.value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.html.find('#attribut-protection-edit').change(async event => {
|
||||||
|
this.actor.updateAttributeValue(event.currentTarget.attributes.name.value, parseInt(event.target.value));
|
||||||
|
});
|
||||||
|
|
||||||
// On stress change
|
// On stress change
|
||||||
this.html.find('.compteur-edit').change(async event => {
|
this.html.find('.compteur-edit').change(async event => {
|
||||||
let fieldName = event.currentTarget.attributes.name.value;
|
let fieldName = event.currentTarget.attributes.name.value;
|
||||||
this.actor.updateCompteurValue(fieldName, parseInt(event.target.value));
|
this.actor.updateCompteurValue(fieldName, parseInt(event.target.value));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.html.find('#ethylisme').change(async event => {
|
||||||
|
this.actor.setEthylisme(parseInt(event.target.value));
|
||||||
|
});
|
||||||
this.html.find('.stress-test').click(async event => {
|
this.html.find('.stress-test').click(async event => {
|
||||||
this.actor.transformerStress();
|
this.actor.transformerStress();
|
||||||
});
|
});
|
||||||
@ -411,6 +454,13 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
this.actor.jetEndurance();
|
this.actor.jetEndurance();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.html.find('.monnaie-plus').click(async event => {
|
||||||
|
this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), 1);
|
||||||
|
});
|
||||||
|
this.html.find('.monnaie-moins').click(async event => {
|
||||||
|
this.actor.monnaieIncDec(RdDSheetUtility.getItemId(event), -1);
|
||||||
|
});
|
||||||
|
|
||||||
this.html.find('.vie-plus').click(async event => {
|
this.html.find('.vie-plus').click(async event => {
|
||||||
this.actor.santeIncDec("vie", 1);
|
this.actor.santeIncDec("vie", 1);
|
||||||
});
|
});
|
||||||
@ -437,12 +487,6 @@ 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);
|
||||||
}
|
}
|
||||||
@ -455,30 +499,36 @@ export class RdDActorSheet extends RdDBaseActorSheet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async selectTypeOeuvreToCreate() {
|
async _onDropItem(event, dragData) {
|
||||||
let types = RdDItem.getTypesOeuvres();
|
const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id')
|
||||||
let content = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`;
|
const dropParams = RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor, dragData, this.objetVersConteneur)
|
||||||
for (let typeName of types) {
|
if (dropParams) {
|
||||||
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
const callSuper = await this.actor.processDropItem(dropParams)
|
||||||
}
|
if (callSuper) {
|
||||||
content += '</select>';
|
await super._onDropItem(event, dragData)
|
||||||
let dialog = new Dialog({
|
|
||||||
title: "Créer une oeuvre",
|
|
||||||
content: content,
|
|
||||||
buttons: {
|
|
||||||
create: {
|
|
||||||
icon: '<i class="fas fa-check"></i>',
|
|
||||||
label: "Créer l'oeuvre",
|
|
||||||
callback: () => this.actor.createItem($(".item-type").val())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
dialog.render(true);
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async createItem(name, type) {
|
||||||
|
await this.actor.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async createEmptyTache() {
|
async createEmptyTache() {
|
||||||
await this.actor.createItem('tache', 'Nouvelle tache');
|
await this.createItem('Nouvelle tache', 'tache');
|
||||||
|
}
|
||||||
|
|
||||||
|
_optionRecherche(target) {
|
||||||
|
if (!target.value?.length) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
text: target.value,
|
||||||
|
start: target.selectionStart,
|
||||||
|
end: target.selectionEnd,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
_getEventArmeCombat(event) {
|
_getEventArmeCombat(event) {
|
||||||
|
2085
module/actor.js
@ -1,301 +0,0 @@
|
|||||||
import { RdDUtility } from "../rdd-utility.js";
|
|
||||||
import { Misc } from "../misc.js";
|
|
||||||
import { DialogSplitItem } from "../dialog-split-item.js";
|
|
||||||
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
|
|
||||||
import { Monnaie } from "../item-monnaie.js";
|
|
||||||
import { RdDItem, TYPES } from "../item.js";
|
|
||||||
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/**
|
|
||||||
* Extend the basic ActorSheet with some very simple modifications
|
|
||||||
* @extends {ActorSheet}
|
|
||||||
*/
|
|
||||||
export class RdDBaseActorSheet extends ActorSheet {
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
static get defaultOptions() {
|
|
||||||
RdDUtility.initAfficheContenu();
|
|
||||||
return mergeObject(super.defaultOptions, {
|
|
||||||
classes: ["rdd", "sheet", "actor"],
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html",
|
|
||||||
width: 550,
|
|
||||||
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
|
|
||||||
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
|
|
||||||
showCompNiveauBase: false,
|
|
||||||
vueDetaillee: false
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async getData() {
|
|
||||||
Monnaie.validerMonnaies(this.actor.itemTypes['monnaie']);
|
|
||||||
|
|
||||||
this.actor.recompute();
|
|
||||||
let formData = {
|
|
||||||
title: this.title,
|
|
||||||
id: this.actor.id,
|
|
||||||
type: this.actor.type,
|
|
||||||
img: this.actor.img,
|
|
||||||
name: this.actor.name,
|
|
||||||
system: this.actor.system,
|
|
||||||
description: await TextEditor.enrichHTML(this.actor.system.description, { async: true }),
|
|
||||||
notesmj: await TextEditor.enrichHTML(this.actor.system.notesmj, { async: true }),
|
|
||||||
options: RdDSheetUtility.mergeDocumentRights(this.options, this.actor, this.isEditable)
|
|
||||||
}
|
|
||||||
|
|
||||||
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
|
||||||
formData.calc = {
|
|
||||||
fortune: Monnaie.toSolsDeniers(this.actor.getFortune()),
|
|
||||||
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
|
||||||
encTotal: await this.actor.computeEncTotal(),
|
|
||||||
}
|
|
||||||
|
|
||||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
|
|
||||||
this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires);
|
|
||||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
|
||||||
formData.competences.filter(it => it.type == TYPES.competencecreature)
|
|
||||||
.forEach(it => it.isdommages = RdDItemCompetenceCreature.isDommages(it))
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
_appliquerRechercheObjets(conteneurs, inventaires) {
|
|
||||||
if (this.options.recherche?.text) {
|
|
||||||
const recherche = this.options.recherche;
|
|
||||||
const allVisible = inventaires.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id);
|
|
||||||
let addVisible = conteneurs.filter(it => it.isNomTypeLike(recherche.text)).map(it => it.id)
|
|
||||||
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)
|
|
||||||
inventaires.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
|
||||||
conteneurs.forEach(it => it.system.isHidden = !allVisible.includes(it.id))
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
inventaires.forEach(it => it.system.isHidden = false)
|
|
||||||
conteneurs.forEach(it => it.system.isHidden = false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static filterItemsPerTypeForSheet(formData, itemTypes) {
|
|
||||||
formData.blessures = Misc.arrayOrEmpty(itemTypes['blessure']);
|
|
||||||
formData.recettescuisine = Misc.arrayOrEmpty(itemTypes['recettecuisine']);
|
|
||||||
formData.recettesAlchimiques = Misc.arrayOrEmpty(itemTypes['recettealchimique']);
|
|
||||||
formData.maladies = Misc.arrayOrEmpty(itemTypes['maladie']);
|
|
||||||
formData.poisons = Misc.arrayOrEmpty(itemTypes['poison']);
|
|
||||||
formData.possessions = Misc.arrayOrEmpty(itemTypes['possession']);
|
|
||||||
formData.maladiesPoisons = formData.maladies.concat(formData.poisons);
|
|
||||||
formData.competences = (itemTypes['competence'] ?? []).concat(itemTypes['competencecreature'] ?? []);
|
|
||||||
formData.sortsReserve = Misc.arrayOrEmpty(itemTypes['sortreserve']);
|
|
||||||
|
|
||||||
formData.sorts = Misc.arrayOrEmpty(itemTypes['sort']);
|
|
||||||
formData.rencontres = Misc.arrayOrEmpty(itemTypes['rencontre']);
|
|
||||||
formData.casestmr = Misc.arrayOrEmpty(itemTypes['casetmr']);
|
|
||||||
formData.signesdraconiques = Misc.arrayOrEmpty(itemTypes['signedraconique']);
|
|
||||||
formData.queues = Misc.arrayOrEmpty(itemTypes['queue']);
|
|
||||||
formData.souffles = Misc.arrayOrEmpty(itemTypes['souffle']);
|
|
||||||
formData.ombres = Misc.arrayOrEmpty(itemTypes['ombre']);
|
|
||||||
formData.tetes = Misc.arrayOrEmpty(itemTypes['tete']);
|
|
||||||
formData.taches = Misc.arrayOrEmpty(itemTypes['tache']);
|
|
||||||
formData.meditations = Misc.arrayOrEmpty(itemTypes['meditation']);
|
|
||||||
formData.chants = Misc.arrayOrEmpty(itemTypes['chant']);
|
|
||||||
formData.danses = Misc.arrayOrEmpty(itemTypes['danse']);
|
|
||||||
formData.musiques = Misc.arrayOrEmpty(itemTypes['musique']);
|
|
||||||
formData.oeuvres = Misc.arrayOrEmpty(itemTypes['oeuvre']);
|
|
||||||
formData.jeux = Misc.arrayOrEmpty(itemTypes['jeu']);
|
|
||||||
|
|
||||||
formData.services = Misc.arrayOrEmpty(itemTypes['service']);
|
|
||||||
formData.conteneurs = Misc.arrayOrEmpty(itemTypes['conteneur']);
|
|
||||||
formData.materiel = Misc.arrayOrEmpty(itemTypes['objet']);
|
|
||||||
formData.armes = Misc.arrayOrEmpty(itemTypes['arme']);
|
|
||||||
formData.armures = Misc.arrayOrEmpty(itemTypes['armure']);
|
|
||||||
formData.munitions = Misc.arrayOrEmpty(itemTypes['munition']);
|
|
||||||
formData.livres = Misc.arrayOrEmpty(itemTypes['livre']);
|
|
||||||
formData.potions = Misc.arrayOrEmpty(itemTypes['potion']);
|
|
||||||
formData.plantes = Misc.arrayOrEmpty(itemTypes['plante']);
|
|
||||||
formData.ingredients = Misc.arrayOrEmpty(itemTypes['ingredient']);
|
|
||||||
formData.faunes = Misc.arrayOrEmpty(itemTypes['faune']);
|
|
||||||
formData.herbes = Misc.arrayOrEmpty(itemTypes['herbe']);
|
|
||||||
formData.nourritureboissons = Misc.arrayOrEmpty(itemTypes['nourritureboisson']);
|
|
||||||
formData.gemmes = Misc.arrayOrEmpty(itemTypes['gemme']);
|
|
||||||
formData.monnaies = Misc.arrayOrEmpty(itemTypes['monnaie']).sort(Monnaie.triValeurEntiere());
|
|
||||||
formData.objets = Misc.arrayOrEmpty(itemTypes['objet'])
|
|
||||||
|
|
||||||
formData.inventaires = RdDItem.getItemTypesInventaire('all')
|
|
||||||
.map(t => Misc.arrayOrEmpty(itemTypes[t]))
|
|
||||||
.reduce((a, b) => a.concat(b), [])
|
|
||||||
.sort(Misc.ascending(it => it.name));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */ /** @override */
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
this.html = html;
|
|
||||||
|
|
||||||
this.html.find('.conteneur-name a').click(async event => {
|
|
||||||
RdDUtility.toggleAfficheContenu(this.getItemId(event));
|
|
||||||
this.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('.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
|
|
||||||
if (!this.options.editable) return;
|
|
||||||
|
|
||||||
this.html.find('.item-split').click(async event => {
|
|
||||||
const item = this.getItem(event);
|
|
||||||
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-vendre').click(async event => this.vendre(this.getItem(event)));
|
|
||||||
|
|
||||||
this.html.find('.creer-un-objet').click(async event => {
|
|
||||||
this.selectObjetTypeToCreate();
|
|
||||||
});
|
|
||||||
this.html.find('.nettoyer-conteneurs').click(async event => {
|
|
||||||
this.actor.nettoyerConteneurs();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_rechercherKeyup(event) {
|
|
||||||
const currentTarget = event.currentTarget;
|
|
||||||
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) {
|
|
||||||
return RdDSheetUtility.getItemId(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
getItem(event) {
|
|
||||||
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() {
|
|
||||||
let buttons = super._getHeaderButtons();
|
|
||||||
buttons.unshift({
|
|
||||||
class: "montrer",
|
|
||||||
icon: "fas fa-comment",
|
|
||||||
onclick: ev => this.actor.postActorToChat()
|
|
||||||
});
|
|
||||||
return buttons
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async _onDropItem(event, dragData) {
|
|
||||||
const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id')
|
|
||||||
const dropParams = await RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor, dragData, this.objetVersConteneur)
|
|
||||||
if (dropParams) {
|
|
||||||
const callSuper = await this.actor.processDropItem(dropParams)
|
|
||||||
if (callSuper) {
|
|
||||||
await super._onDropItem(event, dragData)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async selectObjetTypeToCreate() {
|
|
||||||
let types = this.getTypesInventaire().sort(Misc.ascending(type => Misc.typeName('Item', type)));
|
|
||||||
let content = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
|
|
||||||
for (let typeName of types) {
|
|
||||||
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
|
|
||||||
}
|
|
||||||
content += '</select>';
|
|
||||||
let d = new Dialog({
|
|
||||||
title: "Créer un équipement",
|
|
||||||
content: content,
|
|
||||||
buttons: {
|
|
||||||
create: {
|
|
||||||
icon: '<i class="fas fa-check"></i>',
|
|
||||||
label: "Créer l'objet",
|
|
||||||
callback: () => this.actor.createItem($(".item-type").val())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
d.render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
getTypesInventaire() {
|
|
||||||
return RdDItem.getItemTypesInventaire();
|
|
||||||
}
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
setPosition(options = {}) {
|
|
||||||
const position = super.setPosition(options);
|
|
||||||
const sheetHeader = this.element.find(".sheet-header");
|
|
||||||
const sheetTabs = this.element.find(".sheet-tabs");
|
|
||||||
const sheetBody = this.element.find(".sheet-body");
|
|
||||||
let bodyHeight = position.height - sheetHeader[0].clientHeight;
|
|
||||||
if (sheetTabs.length > 0) {
|
|
||||||
bodyHeight -= sheetTabs[0].clientHeight;
|
|
||||||
}
|
|
||||||
sheetBody.css("height", bodyHeight);
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** @override */
|
|
||||||
_updateObject(event, formData) {
|
|
||||||
// Update the Actor
|
|
||||||
return this.actor.update(formData);
|
|
||||||
}
|
|
||||||
|
|
||||||
async splitItem(item) {
|
|
||||||
const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split));
|
|
||||||
dialog.render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
async _onSplitItem(item, split) {
|
|
||||||
if (split >= 1 && split < item.system.quantite) {
|
|
||||||
await item.diminuerQuantite(split);
|
|
||||||
const splitItem = duplicate(item);
|
|
||||||
splitItem.system.quantite = split;
|
|
||||||
await this.actor.createEmbeddedDocuments('Item', [splitItem])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
vendre(item) {
|
|
||||||
item?.proposerVente(this.actor.getQuantiteDisponible(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,644 +0,0 @@
|
|||||||
import { ChatUtility } from "../chat-utility.js";
|
|
||||||
import { SYSTEM_SOCKET_ID } from "../constants.js";
|
|
||||||
import { Monnaie } from "../item-monnaie.js";
|
|
||||||
import { Misc } from "../misc.js";
|
|
||||||
import { RdDAudio } from "../rdd-audio.js";
|
|
||||||
import { RdDConfirm } from "../rdd-confirm.js";
|
|
||||||
import { RdDUtility } from "../rdd-utility.js";
|
|
||||||
import { SystemCompendiums } from "../settings/system-compendiums.js";
|
|
||||||
import { APP_ASTROLOGIE_REFRESH } from "../sommeil/app-astrologie.js";
|
|
||||||
|
|
||||||
export class RdDBaseActor extends Actor {
|
|
||||||
|
|
||||||
static getDefaultImg(itemType) {
|
|
||||||
return game.system.rdd.actorClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static init() {
|
|
||||||
Hooks.on("preUpdateItem", (item, change, options, id) => RdDBaseActor.getParentActor(item)?.onPreUpdateItem(item, change, options, id));
|
|
||||||
Hooks.on("createItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onCreateItem(item, options, id));
|
|
||||||
Hooks.on("deleteItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onDeleteItem(item, options, id));
|
|
||||||
Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId));
|
|
||||||
}
|
|
||||||
|
|
||||||
static onSocketMessage(sockmsg) {
|
|
||||||
switch (sockmsg.msg) {
|
|
||||||
case "msg_remote_actor_call":
|
|
||||||
return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId);
|
|
||||||
case "msg_reset_nombre_astral":
|
|
||||||
game.user.character.resetNombresAstraux();
|
|
||||||
game.system.rdd.calendrier.notifyChangeNombresAstraux();
|
|
||||||
return;
|
|
||||||
case "msg_refresh_nombre_astral":
|
|
||||||
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static remoteActorCall(callData, userId = undefined) {
|
|
||||||
userId = userId ?? Misc.firstConnectedGMId();
|
|
||||||
if (userId == game.user.id) {
|
|
||||||
RdDBaseActor.onRemoteActorCall(callData, userId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_remote_actor_call", data: callData, userId: userId });
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static onRemoteActorCall(callData, userId) {
|
|
||||||
if (userId == game.user.id) {
|
|
||||||
const actor = game.actors.get(callData?.actorId);
|
|
||||||
if (Misc.isOwnerPlayerOrUniqueConnectedGM(actor)) { // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
|
|
||||||
const args = callData.args;
|
|
||||||
console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')');
|
|
||||||
actor[callData.method](...args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static getParentActor(document) {
|
|
||||||
return document?.parent instanceof Actor ? document.parent : undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cet methode surcharge Actor.create() pour ajouter si besoin des Items par défaut:
|
|
||||||
* compétences et monnaies.
|
|
||||||
*
|
|
||||||
* @param {Object} actorData template d'acteur auquel ajouter des informations.
|
|
||||||
* @param {Object} options optionspour customiser la création
|
|
||||||
*/
|
|
||||||
static async create(actorData, options) {
|
|
||||||
// import depuis un compendium
|
|
||||||
if (actorData instanceof Array) {
|
|
||||||
return super.create(actorData, options);
|
|
||||||
}
|
|
||||||
// Création d'un acteur avec des items (uniquement en cas de duplication): pas besoin d'ajouter d'items
|
|
||||||
if (actorData.items) {
|
|
||||||
return await super.create(actorData, options);
|
|
||||||
}
|
|
||||||
actorData.items = [];
|
|
||||||
if (actorData.type == "personnage") {
|
|
||||||
const competences = await SystemCompendiums.getCompetences(actorData.type);
|
|
||||||
actorData.items = actorData.items.concat(competences.map(i => i.toObject()))
|
|
||||||
.concat(Monnaie.monnaiesStandard());
|
|
||||||
}
|
|
||||||
else if (actorData.type == "commerce") {
|
|
||||||
actorData.items = actorData.items.concat(Monnaie.monnaiesStandard());
|
|
||||||
}
|
|
||||||
return super.create(actorData, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(docData, context = {}) {
|
|
||||||
if (!context.rdd?.ready) {
|
|
||||||
mergeObject(context, { rdd: { ready: true } });
|
|
||||||
const ActorConstructor = game.system.rdd.actorClasses[docData.type];
|
|
||||||
if (ActorConstructor) {
|
|
||||||
if (!docData.img) {
|
|
||||||
docData.img = ActorConstructor.defaultIcon;
|
|
||||||
}
|
|
||||||
return new ActorConstructor(docData, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
super(docData, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
isCreatureEntite() { return this.type == 'creature' || this.type == 'entite'; }
|
|
||||||
isCreature() { return this.type == 'creature'; }
|
|
||||||
isEntite() { return this.type == 'entite'; }
|
|
||||||
isPersonnage() { return this.type == 'personnage'; }
|
|
||||||
isVehicule() { return this.type == 'vehicule'; }
|
|
||||||
getItem(id, type = undefined) {
|
|
||||||
const item = this.items.get(id);
|
|
||||||
if (type == undefined || (item?.type == type)) {
|
|
||||||
return item;
|
|
||||||
}
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); }
|
|
||||||
filterItems(filter, type = undefined) { return (type ? this.itemTypes[type] : this.items)?.filter(filter); }
|
|
||||||
findItemLike(idOrName, type) {
|
|
||||||
return this.getItem(idOrName, type)
|
|
||||||
?? Misc.findFirstLike(idOrName, this.listItems(type), { description: Misc.typeName('Item', type) });
|
|
||||||
}
|
|
||||||
|
|
||||||
getMonnaie(id) { return this.findItemLike(id, 'monnaie'); }
|
|
||||||
|
|
||||||
recompute() { }
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async onPreUpdateItem(item, change, options, id) { }
|
|
||||||
|
|
||||||
async onCreateItem(item, options, id) { }
|
|
||||||
|
|
||||||
async onDeleteItem(item, options, id) { }
|
|
||||||
|
|
||||||
async onUpdateActor(update, options, actorId) { }
|
|
||||||
|
|
||||||
async onTimeChanging(oldTimestamp, newTimestamp) {
|
|
||||||
this.items.filter(it => it.isFinPeriode(oldTimestamp, newTimestamp))
|
|
||||||
.forEach(async it => await it.onFinPeriodeTemporel(oldTimestamp, newTimestamp))
|
|
||||||
}
|
|
||||||
|
|
||||||
async creerObjetParMJ(object){
|
|
||||||
if (!Misc.isUniqueConnectedGM()) {
|
|
||||||
RdDBaseActor.remoteActorCall({
|
|
||||||
actorId: this.id,
|
|
||||||
method: 'creerObjetParMJ',
|
|
||||||
args: [object]
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await this.createEmbeddedDocuments('Item', [object])
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getFortune() {
|
|
||||||
return Monnaie.getFortune(this.itemTypes['monnaie']);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async itemQuantiteIncDec(id, value) {
|
|
||||||
let item = this.getItem(id);
|
|
||||||
if (item && item.isInventaire()) {
|
|
||||||
const quantite = Math.max(0, item.system.quantite + value);
|
|
||||||
await this.updateEmbeddedDocuments('Item', [{ _id: item.id, 'system.quantite': quantite }]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
computePrixTotalEquipement() {
|
|
||||||
return this.items.filter(it => it.isInventaire())
|
|
||||||
.filter(it => !it.isMonnaie())
|
|
||||||
.map(it => it.valeurTotale())
|
|
||||||
.reduce(Misc.sum(), 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
async payerSols(depense) {
|
|
||||||
depense = Number(depense);
|
|
||||||
if (depense == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let fortune = this.getFortune();
|
|
||||||
console.log("payer", game.user.character, depense, fortune);
|
|
||||||
let msg = "";
|
|
||||||
if (fortune >= depense) {
|
|
||||||
await Monnaie.optimiserFortune(this, fortune - depense);
|
|
||||||
msg = `Vous avez payé <strong>${depense} Sols</strong>, qui ont été soustraits de votre argent.`;
|
|
||||||
RdDAudio.PlayContextAudio("argent"); // Petit son
|
|
||||||
} else {
|
|
||||||
msg = "Vous n'avez pas assez d'argent pour payer cette somme !";
|
|
||||||
}
|
|
||||||
|
|
||||||
let message = {
|
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
|
||||||
content: msg
|
|
||||||
};
|
|
||||||
ChatMessage.create(message);
|
|
||||||
}
|
|
||||||
|
|
||||||
async depenserSols(sols) {
|
|
||||||
let reste = this.getFortune() - Number(sols);
|
|
||||||
if (reste >= 0) {
|
|
||||||
await Monnaie.optimiserFortune(this, reste);
|
|
||||||
}
|
|
||||||
return reste;
|
|
||||||
}
|
|
||||||
|
|
||||||
async ajouterSols(sols, fromActorId = undefined) {
|
|
||||||
sols = Number(sols);
|
|
||||||
if (sols == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (sols < 0) {
|
|
||||||
ui.notifications.error(`Impossible d'ajouter un gain de ${sols} <0`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (fromActorId && !game.user.isGM) {
|
|
||||||
RdDBaseActor.remoteActorCall({
|
|
||||||
userId: Misc.connectedGMOrUser(),
|
|
||||||
actorId: this.id,
|
|
||||||
method: 'ajouterSols', args: [sols, fromActorId]
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const fromActor = game.actors.get(fromActorId)
|
|
||||||
await Monnaie.optimiserFortune(this, sols + this.getFortune());
|
|
||||||
|
|
||||||
RdDAudio.PlayContextAudio("argent"); // Petit son
|
|
||||||
ChatMessage.create({
|
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
|
||||||
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
|
|
||||||
getQuantiteDisponible(item) {
|
|
||||||
return item?.isService() ? undefined : item?.getQuantite();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async achatVente(achat) {
|
|
||||||
if (achat.vendeurId == achat.acheteurId) {
|
|
||||||
ui.notifications.info("Inutile de se vendre à soi-même");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!Misc.isUniqueConnectedGM()) {
|
|
||||||
RdDBaseActor.remoteActorCall({
|
|
||||||
actorId: achat.vendeurId ?? achat.acheteurId,
|
|
||||||
method: 'achatVente',
|
|
||||||
args: [achat]
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const cout = Number(achat.prixTotal ?? 0);
|
|
||||||
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined;
|
|
||||||
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined;
|
|
||||||
const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
|
|
||||||
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id);
|
|
||||||
if (!itemVendu) {
|
|
||||||
ChatUtility.notifyUser(achat.userId, 'warn', vendeur ? `Le vendeur n'a pas plus de ${achat.vente.item.name} !`: `Impossible de retrouver: ${achat.vente.item.name} !`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (vendeur && !this.verifierQuantite(itemVendu, quantite)) {
|
|
||||||
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if (acheteur && !acheteur.verifierFortune(cout)) {
|
|
||||||
ChatUtility.notifyUser(achat.userId, 'warn', `Vous n'avez pas assez d'argent pour payer ${Math.ceil(cout / 100)} sols !`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await this.decrementerVente(vendeur, itemVendu, quantite, cout);
|
|
||||||
if (acheteur) {
|
|
||||||
await acheteur.depenserSols(cout);
|
|
||||||
const createdItemId = await acheteur.creerQuantiteItem(itemVendu, quantite);
|
|
||||||
await acheteur.consommerNourritureAchetee(achat, achat.vente, createdItemId);
|
|
||||||
}
|
|
||||||
if (cout > 0) {
|
|
||||||
RdDAudio.PlayContextAudio("argent");
|
|
||||||
}
|
|
||||||
const chatAchatItem = duplicate(achat.vente);
|
|
||||||
chatAchatItem.quantiteTotal = quantite;
|
|
||||||
ChatMessage.create({
|
|
||||||
user: achat.userId,
|
|
||||||
speaker: { alias: (acheteur ?? vendeur).name },
|
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
|
|
||||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.html', chatAchatItem)
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!achat.vente.quantiteIllimite) {
|
|
||||||
if (achat.vente.quantiteNbLots <= achat.choix.nombreLots) {
|
|
||||||
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
|
|
||||||
}
|
|
||||||
else if (achat.chatMessageIdVente) {
|
|
||||||
achat.vente.properties = itemVendu.getProprietes();
|
|
||||||
achat.vente.quantiteNbLots -= achat.choix.nombreLots;
|
|
||||||
achat.vente.jsondata = JSON.stringify(achat.vente.item);
|
|
||||||
const messageVente = game.messages.get(achat.chatMessageIdVente);
|
|
||||||
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', achat.vente) });
|
|
||||||
messageVente.render(true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async decrementerVente(vendeur, itemVendu, quantite, cout) {
|
|
||||||
if (vendeur) {
|
|
||||||
await vendeur.ajouterSols(cout);
|
|
||||||
await vendeur.decrementerQuantiteItem(itemVendu, quantite);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
verifierFortune(cout) {
|
|
||||||
return this.getFortune() >= cout;
|
|
||||||
}
|
|
||||||
|
|
||||||
verifierQuantite(item, quantiteDemande) {
|
|
||||||
const disponible = item?.getQuantite();
|
|
||||||
return disponible == undefined || disponible >= quantiteDemande;
|
|
||||||
}
|
|
||||||
|
|
||||||
async consommerNourritureAchetee(achat, vente, createdItemId) {
|
|
||||||
if (achat.choix.consommer && vente.item.type == 'nourritureboisson' && createdItemId != undefined) {
|
|
||||||
achat.choix.doses = achat.choix.nombreLots;
|
|
||||||
await this.consommerNourritureboisson(createdItemId, achat.choix, vente.actingUserId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async decrementerQuantiteItem(item, quantite, options = { supprimerSiZero: true }) {
|
|
||||||
if (item.isService()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let resteQuantite = (item.system.quantite ?? 1) - quantite;
|
|
||||||
if (resteQuantite <= 0) {
|
|
||||||
if (options.supprimerSiZero) {
|
|
||||||
await this.deleteEmbeddedDocuments("Item", [item.id]);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': 0 }]);
|
|
||||||
}
|
|
||||||
if (resteQuantite < 0) {
|
|
||||||
ui.notifications.warn(`La quantité de ${item.name} était insuffisante, l'objet a donc été supprimé`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (resteQuantite > 0) {
|
|
||||||
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': resteQuantite }]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async creerQuantiteItem(item, quantite) {
|
|
||||||
if (this.canReceive(item)) {
|
|
||||||
const isItemEmpilable = "quantite" in item.system;
|
|
||||||
const baseItem = {
|
|
||||||
type: item.type,
|
|
||||||
img: item.img,
|
|
||||||
name: item.name,
|
|
||||||
system: mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined })
|
|
||||||
};
|
|
||||||
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
|
|
||||||
const items = await this.createEmbeddedDocuments("Item", newItems);
|
|
||||||
return items.length > 0 ? items[0].id : undefined;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
computeMalusSurEncombrement() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
getEncombrementMax() {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
async computeEncTotal() {
|
|
||||||
if (!this.pack) {
|
|
||||||
this.encTotal = this.items.map(it => it.getEncTotal()).reduce(Misc.sum(), 0);
|
|
||||||
return this.encTotal;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
async createItem(type, name = undefined) {
|
|
||||||
if (!name) {
|
|
||||||
name = 'Nouveau ' + Misc.typeName('Item', type);
|
|
||||||
}
|
|
||||||
await this.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
canReceive(item) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
async processDropItem(params) {
|
|
||||||
const targetActorId = this.id;
|
|
||||||
const sourceActorId = params.sourceActorId;
|
|
||||||
const itemId = params.itemId;
|
|
||||||
const destId = params.destId;
|
|
||||||
const srcId = params.srcId;
|
|
||||||
if (sourceActorId && sourceActorId != targetActorId) {
|
|
||||||
console.log("Moving objects", sourceActorId, targetActorId, itemId);
|
|
||||||
this.moveItemsBetweenActors(itemId, sourceActorId);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
let result = true;
|
|
||||||
const item = this.getItem(itemId);
|
|
||||||
if (item?.isInventaire('all') && sourceActorId == targetActorId) {
|
|
||||||
// rangement
|
|
||||||
if (srcId != destId && itemId != destId) { // déplacement de l'objet
|
|
||||||
const src = this.getItem(srcId);
|
|
||||||
const dest = this.getItem(destId);
|
|
||||||
const cible = this.getContenantOrParent(dest);
|
|
||||||
const [empilable, message] = item.isInventaireEmpilable(dest);
|
|
||||||
if (empilable) {
|
|
||||||
await dest.empiler(item)
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
// changer de conteneur
|
|
||||||
else if (!cible || this.conteneurPeutContenir(cible, item)) {
|
|
||||||
await this.enleverDeConteneur(item, src, params.onEnleverConteneur);
|
|
||||||
await this.ajouterDansConteneur(item, cible, params.onAjouterDansConteneur);
|
|
||||||
if (message && !dest.isConteneur()) {
|
|
||||||
ui.notifications.info(cible
|
|
||||||
? `${message}<br>${item.name} a été déplacé dans: ${cible.name}`
|
|
||||||
: `${message}<br>${item.name} a été sorti du conteneur`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await this.computeEncTotal();
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
getContenantOrParent(dest) {
|
|
||||||
if (!dest || dest.isConteneur()) {
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
return this.getContenant(dest);
|
|
||||||
}
|
|
||||||
|
|
||||||
getContenant(item) {
|
|
||||||
return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
conteneurPeutContenir(dest, item) {
|
|
||||||
if (!dest) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (!dest.isConteneur()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const destData = dest
|
|
||||||
if (this._isConteneurContenu(item, dest)) {
|
|
||||||
ui.notifications.warn(`Impossible de déplacer un conteneur parent (${item.name}) dans un de ses contenus ${destData.name} !`);
|
|
||||||
return false; // Loop detected !
|
|
||||||
}
|
|
||||||
|
|
||||||
// Calculer le total actuel des contenus
|
|
||||||
let encContenu = this.getRecursiveEnc(dest) - Number(destData.system.encombrement);
|
|
||||||
let newEnc = this.getRecursiveEnc(item); // Calculer le total actuel du nouvel objet
|
|
||||||
|
|
||||||
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
|
|
||||||
if (Number(destData.system.capacite) < encContenu + newEnc) {
|
|
||||||
ui.notifications.warn(
|
|
||||||
`Le conteneur ${dest.name} a une capacité de ${destData.system.capacite}, et contient déjà ${encContenu}.
|
|
||||||
Impossible d'y ranger: ${item.name} d'encombrement ${newEnc}!`);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
_isConteneurContenu(item, conteneur) {
|
|
||||||
if (item?.isConteneur()) { // Si c'est un conteneur, il faut vérifier qu'on ne le déplace pas vers un sous-conteneur lui appartenant
|
|
||||||
for (let id of item.system.contenu) {
|
|
||||||
let subObjet = this.getItem(id);
|
|
||||||
if (subObjet?.id == conteneur.id) {
|
|
||||||
return true; // Loop detected !
|
|
||||||
}
|
|
||||||
if (subObjet?.isConteneur()) {
|
|
||||||
return this._isConteneurContenu(subObjet, conteneur);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
getRecursiveEnc(objet) {
|
|
||||||
if (!objet) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const tplData = objet.system;
|
|
||||||
if (objet.type != 'conteneur') {
|
|
||||||
return Number(tplData.encombrement) * Number(tplData.quantite);
|
|
||||||
}
|
|
||||||
const encContenus = tplData.contenu.map(idContenu => this.getRecursiveEnc(this.getItem(idContenu)));
|
|
||||||
return encContenus.reduce(Misc.sum(), 0)
|
|
||||||
+ Number(tplData.encombrement) /* TODO? Number(tplData.quantite) -- on pourrait avoir plusieurs conteneurs...*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** Ajoute un item dans un conteneur, sur la base
|
|
||||||
* de leurs ID */
|
|
||||||
async ajouterDansConteneur(item, conteneur, onAjouterDansConteneur) {
|
|
||||||
if (!conteneur) {
|
|
||||||
// TODO: afficher
|
|
||||||
item.estContenu = false;
|
|
||||||
}
|
|
||||||
else if (conteneur.isConteneur()) {
|
|
||||||
item.estContenu = true;
|
|
||||||
await this.updateEmbeddedDocuments('Item', [{
|
|
||||||
_id: conteneur.id,
|
|
||||||
'system.contenu': [...conteneur.system.contenu, item.id]
|
|
||||||
}]);
|
|
||||||
onAjouterDansConteneur(item.id, conteneur.id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** Fonction de remise à plat de l'équipement (ie vide les champs 'contenu') */
|
|
||||||
async nettoyerConteneurs() {
|
|
||||||
RdDConfirm.confirmer({
|
|
||||||
settingConfirmer: "confirmation-vider",
|
|
||||||
content: `<p>Etes vous certain de vouloir vider tous les conteneurs ?</p>`,
|
|
||||||
title: 'Vider les conteneurs',
|
|
||||||
buttonLabel: 'Vider',
|
|
||||||
onAction: async () => {
|
|
||||||
const corrections = [];
|
|
||||||
for (let item of this.items) {
|
|
||||||
if (item.estContenu) {
|
|
||||||
item.estContenu = undefined;
|
|
||||||
}
|
|
||||||
if (item.type == 'conteneur' && item.system.contenu.length > 0) {
|
|
||||||
corrections.push({ _id: item.id, 'system.contenu': [] });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (corrections.length > 0) {
|
|
||||||
await this.updateEmbeddedDocuments('Item', corrections);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
buildSubConteneurObjetList(conteneurId, deleteList) {
|
|
||||||
let conteneur = this.getItem(conteneurId);
|
|
||||||
if (conteneur?.type == 'conteneur') { // Si c'est un conteneur
|
|
||||||
for (let subId of conteneur.system.contenu) {
|
|
||||||
let subObj = this.getItem(subId);
|
|
||||||
if (subObj) {
|
|
||||||
if (subObj.type == 'conteneur') {
|
|
||||||
this.buildSubConteneurObjetList(subId, deleteList);
|
|
||||||
}
|
|
||||||
deleteList.push({ id: subId, conteneurId: conteneurId });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async deleteAllConteneur(itemId, options) {
|
|
||||||
let list = [];
|
|
||||||
list.push({ id: itemId, conteneurId: undefined }); // Init list
|
|
||||||
this.buildSubConteneurObjetList(itemId, list);
|
|
||||||
await this.deleteEmbeddedDocuments('Item', list.map(it => it.id), options);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/** Supprime un item d'un conteneur, sur la base
|
|
||||||
* de leurs ID */
|
|
||||||
async enleverDeConteneur(item, conteneur, onEnleverDeConteneur) {
|
|
||||||
if (conteneur?.isConteneur()) {
|
|
||||||
item.estContenu = false;
|
|
||||||
await this.updateEmbeddedDocuments('Item', [{
|
|
||||||
_id: conteneur.id,
|
|
||||||
'system.contenu': conteneur.system.contenu.filter(id => id != item.id)
|
|
||||||
}]);
|
|
||||||
onEnleverDeConteneur();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async moveItemsBetweenActors(itemId, sourceActorId) {
|
|
||||||
let itemsList = []
|
|
||||||
let sourceActor = game.actors.get(sourceActorId);
|
|
||||||
itemsList.push({ id: itemId, conteneurId: undefined }); // Init list
|
|
||||||
sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list
|
|
||||||
|
|
||||||
const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id))
|
|
||||||
.map(it => duplicate(it))
|
|
||||||
.map(it => { it.system.contenu = []; return it; });
|
|
||||||
let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate);
|
|
||||||
|
|
||||||
let itemMap = this._buildMapOldNewId(itemsList, newItems);
|
|
||||||
|
|
||||||
for (let item of itemsList) { // Second boucle pour traiter la remise en conteneurs
|
|
||||||
// gestion conteneur/contenu
|
|
||||||
if (item.conteneurId) { // l'Objet était dans un conteneur
|
|
||||||
let newConteneurId = itemMap[item.conteneurId]; // Get conteneur
|
|
||||||
let newConteneur = this.getItem(newConteneurId);
|
|
||||||
|
|
||||||
let newItemId = itemMap[item.id]; // Get newItem
|
|
||||||
|
|
||||||
console.log('New conteneur filling!', newConteneur, newItemId, item);
|
|
||||||
let contenu = duplicate(newConteneur.system.contenu);
|
|
||||||
contenu.push(newItemId);
|
|
||||||
await this.updateEmbeddedDocuments('Item', [{ _id: newConteneurId, 'system.contenu': contenu }]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (let item of itemsList) {
|
|
||||||
await sourceActor.deleteEmbeddedDocuments('Item', [item.id]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_buildMapOldNewId(itemsList, newItems) {
|
|
||||||
let itemMap = {};
|
|
||||||
for (let i = 0; i < itemsList.length; i++) {
|
|
||||||
itemMap[itemsList[i].id] = newItems[i].id; // Pour garder le lien ancien / nouveau
|
|
||||||
}
|
|
||||||
return itemMap;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async postActorToChat(modeOverride) {
|
|
||||||
let chatData = {
|
|
||||||
doctype: 'Actor',
|
|
||||||
id: this.id,
|
|
||||||
type: this.type,
|
|
||||||
img: this.img,
|
|
||||||
pack: this.pack,
|
|
||||||
name: this.name,
|
|
||||||
system: { description: this.system.description }
|
|
||||||
}
|
|
||||||
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.html', chatData)
|
|
||||||
.then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,95 +0,0 @@
|
|||||||
import { DialogItemAchat } from "../dialog-item-achat.js";
|
|
||||||
import { RdDItem } from "../item.js";
|
|
||||||
import { RdDSheetUtility } from "../rdd-sheet-utility.js";
|
|
||||||
import { RdDUtility } from "../rdd-utility.js";
|
|
||||||
import { RdDBaseActorSheet } from "./base-actor-sheet.js";
|
|
||||||
import { RdDCommerce } from "./commerce.js";
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extend the basic ActorSheet with some very simple modifications
|
|
||||||
* @extends {ActorSheet}
|
|
||||||
*/
|
|
||||||
export class RdDCommerceSheet extends RdDBaseActorSheet {
|
|
||||||
|
|
||||||
/** @override */
|
|
||||||
static get defaultOptions() {
|
|
||||||
return mergeObject(super.defaultOptions, {
|
|
||||||
classes: ["rdd", "sheet", "actor"],
|
|
||||||
template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.html",
|
|
||||||
width: 600,
|
|
||||||
height: 720,
|
|
||||||
tabs: [],
|
|
||||||
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 */
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
|
|
||||||
this.html.find('a.item-acheter').click(async event => await this.vente(this.getItem(event)));
|
|
||||||
|
|
||||||
if (!this.options.editable) return;
|
|
||||||
|
|
||||||
this.html.find('a.item-quantite-moins').click(async event => await this.getItem(event)?.quantiteIncDec(-1, { supprimerSiZero: false }));
|
|
||||||
this.html.find('a.item-quantite-plus').click(async event => await this.getItem(event)?.quantiteIncDec(1));
|
|
||||||
this.html.find('input.item-quantite').change(async event => {
|
|
||||||
const newQuantite = Math.max(0, Number.parseInt(this.html.find(event.currentTarget).val()));
|
|
||||||
await this.getItem(event)?.update({ "system.quantite": newQuantite });
|
|
||||||
})
|
|
||||||
this.html.find('input.item-cout').change(async event => {
|
|
||||||
const newCout = Math.max(0, Number(this.html.find(event.currentTarget).val()));
|
|
||||||
await this.getItem(event)?.update({ "system.cout": newCout });
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
getTypesInventaire() {
|
|
||||||
return RdDItem.getItemTypesInventaire('all');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async vente(item) {
|
|
||||||
const acheteur = RdDUtility.getSelectedActor();
|
|
||||||
if (!acheteur) {
|
|
||||||
ui.notifications.warn(`Pas d'acheteur sélectionné`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const disponible = this.actor.getQuantiteDisponible(item)
|
|
||||||
if (disponible == 0) {
|
|
||||||
ui.notifications.warn(`${this.name} n'a plus de ${item.name} en vente`);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await DialogItemAchat.onAcheter({
|
|
||||||
item,
|
|
||||||
vendeur: this.actor,
|
|
||||||
acheteur,
|
|
||||||
quantiteIllimite: disponible == undefined,
|
|
||||||
nbLots: disponible ?? 1,
|
|
||||||
tailleLot: 1,
|
|
||||||
prixLot: item.calculerPrixCommercant()
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,53 +0,0 @@
|
|||||||
import { Misc } from "../misc.js";
|
|
||||||
import { RdDBaseActor } from "./base-actor.js";
|
|
||||||
|
|
||||||
export class RdDCommerce extends RdDBaseActor {
|
|
||||||
|
|
||||||
static get defaultIcon() {
|
|
||||||
return "systems/foundryvtt-reve-de-dragon/icons/services/commerce.webp";
|
|
||||||
}
|
|
||||||
|
|
||||||
prepareData() {
|
|
||||||
super.prepareData();
|
|
||||||
}
|
|
||||||
prepareDerivedData() {
|
|
||||||
super.prepareDerivedData();
|
|
||||||
}
|
|
||||||
|
|
||||||
canReceive(item) {
|
|
||||||
if (item.isInventaire('all')) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.canReceive(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
getQuantiteDisponible(item) {
|
|
||||||
return (this.system.illimite || item?.isService()) ? undefined : item.getQuantite();
|
|
||||||
}
|
|
||||||
|
|
||||||
verifierFortune(cout) {
|
|
||||||
return this.system.illimite || super.verifierFortune(cout);
|
|
||||||
}
|
|
||||||
async depenserSols(cout) {
|
|
||||||
if (this.system.illimite) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
await super.depenserSols(cout)
|
|
||||||
}
|
|
||||||
|
|
||||||
async consommerNourritureAchetee(achat, vente, createdItemId) {
|
|
||||||
// ne pas consommer pour un commerce
|
|
||||||
}
|
|
||||||
|
|
||||||
async decrementerQuantiteItem(item, quantite) {
|
|
||||||
if (this.system.illimite) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await super.decrementerQuantiteItem(item, quantite, { supprimerSiZero: false });
|
|
||||||
}
|
|
||||||
|
|
||||||
calculerPrix(item) {
|
|
||||||
const pourcentage = this.system.pourcentage ?? 100;
|
|
||||||
return Misc.keepDecimals(Math.ceil(item.system.cout * pourcentage) / 100, 2);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,39 +0,0 @@
|
|||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
@ -78,7 +78,11 @@ export class ChatUtility {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async createChatWithRollMode(name, chatOptions) {
|
static async createChatWithRollMode(name, chatOptions) {
|
||||||
let rollMode = game.settings.get("core", "rollMode")
|
return await ChatUtility.createChatMessage(name, game.settings.get("core", "rollMode"), chatOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async createChatMessage(name, rollMode, chatOptions) {
|
||||||
switch (rollMode) {
|
switch (rollMode) {
|
||||||
case "blindroll": // GM only
|
case "blindroll": // GM only
|
||||||
if (!game.user.isGM) {
|
if (!game.user.isGM) {
|
||||||
|
@ -1,7 +1,5 @@
|
|||||||
import { SYSTEM_RDD } from "./constants.js";
|
import { SYSTEM_RDD } from "./constants.js";
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.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";
|
||||||
@ -18,75 +16,62 @@ export class DialogChronologie extends Dialog {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
static async create() {
|
static async create() {
|
||||||
|
const dateRdD = game.system.rdd.calendrier.getCalendrier();
|
||||||
const dialogData = {
|
const dialogData = {
|
||||||
auteur: game.user.name,
|
auteur: game.user.name,
|
||||||
isGM: game.user.isGM,
|
isGM: game.user.isGM,
|
||||||
information: "",
|
information: "",
|
||||||
journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID),
|
journalId: game.settings.get(SYSTEM_RDD, LATEST_USED_JOURNAL_ID),
|
||||||
journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)),
|
journaux: game.journal.filter(it => it.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)),
|
||||||
timestamp: game.system.rdd.calendrier.timestamp,
|
dateRdD: dateRdD,
|
||||||
dateReel: game.system.rdd.calendrier.dateReel()
|
jourRdD: dateRdD.jour +1,
|
||||||
|
heureRdD: game.system.rdd.calendrier.getCurrentHeure(),
|
||||||
|
dateReel: DialogChronologie.getCurrentDateTime()
|
||||||
};
|
};
|
||||||
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, dialogData);
|
const dialog = new DialogChronologie(html);
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor(html, dialogData) {
|
constructor(html) {
|
||||||
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 - ${timeData.jourDuMois} ${timeData.mois.label} - Heure ${timeData.heure.label}`,
|
title: "Chronologie",
|
||||||
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) {
|
||||||
this.html = html;
|
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
const journalPrecedent = game.journal.get(this.dialogData.journalId);
|
this.html = html;
|
||||||
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();
|
||||||
if (journalEntry?.canUserModify(game.user)) {
|
|
||||||
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
|
// ajouter à la page ou créer une page
|
||||||
this.addContentToJournal(journalEntry, section, content);
|
this.addContentToJournal(journalEntry, await this.prepareChronologieEntry());
|
||||||
|
|
||||||
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() {
|
||||||
@ -99,8 +84,8 @@ export class DialogChronologie extends Dialog {
|
|||||||
return { journalId, journalEntry };
|
return { journalId, journalEntry };
|
||||||
}
|
}
|
||||||
|
|
||||||
async prepareChronologieEntry(journalParameters) {
|
async prepareChronologieEntry() {
|
||||||
return await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chronologie-entry.html", journalParameters);
|
return await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chronologie-entry.html", this.extractJournalParameters());
|
||||||
}
|
}
|
||||||
|
|
||||||
extractJournalParameters() {
|
extractJournalParameters() {
|
||||||
@ -108,29 +93,28 @@ export class DialogChronologie extends Dialog {
|
|||||||
auteur: this.html.find("form.rdddialogchrono :input[name='auteur']").val(),
|
auteur: this.html.find("form.rdddialogchrono :input[name='auteur']").val(),
|
||||||
information: this.html.find("form.rdddialogchrono :input[name='information']").val(),
|
information: this.html.find("form.rdddialogchrono :input[name='information']").val(),
|
||||||
dateRdD: {
|
dateRdD: {
|
||||||
jour: this.html.find("form.rdddialogchrono :input[name='chronologie.jourDuMois']").val(),
|
jour: this.html.find("form.rdddialogchrono :input[name='jourRdD']").val(),
|
||||||
mois: RdDTimestamp.definition(this.html.find("form.rdddialogchrono :input[name='chronologie.mois']").val()),
|
moisRdD: this.html.find("form.rdddialogchrono :input[name='dateRdD.moisRdD.key']").val(),
|
||||||
annee: this.html.find("form.rdddialogchrono :input[name='chronologie.annee']").val(),
|
annee: this.html.find("form.rdddialogchrono :input[name='dateRdD.annee']").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(),
|
|
||||||
},
|
},
|
||||||
dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val()
|
heureRdD: this.html.find("form.rdddialogchrono :input[name='heureRdD']").val(),
|
||||||
|
dateReel: this.html.find("form.rdddialogchrono :input[name='dateReel']").val().replace('T', ' ')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
addContentToJournal(journalEntry, section, content) {
|
addContentToJournal(journalEntry, content) {
|
||||||
let page = journalEntry.pages.find(p => p.type == 'text' && Grammar.equalsInsensitive(p.name, section));
|
let page = journalEntry.pages.find(p => p.type == 'text' && Grammar.equalsInsensitive(p.name, 'Chronologie'));
|
||||||
if (page) {
|
if (page) {
|
||||||
page.update({ 'text.content': page.text.content + '\n' + content });
|
page.update({ 'text.content': content + '\n' + page.text.content });
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
journalEntry.createEmbeddedDocuments('JournalEntryPage', [this.newPageChronologie(section, content)]);
|
journalEntry.createEmbeddedDocuments('JournalEntryPage', [this.newPageChronologie(content)]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
newPageChronologie(section, content) {
|
newPageChronologie(content) {
|
||||||
return new JournalEntryPage({
|
return new JournalEntryPage({
|
||||||
name: section,
|
name: 'Chronologie',
|
||||||
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/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, onActionItem) {
|
static async create(actor, item, dialogConfig) {
|
||||||
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,10 +13,12 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
}
|
}
|
||||||
let potionData = DialogFabriquerPotion.prepareData(actor, item);
|
let potionData = DialogFabriquerPotion.prepareData(actor, item);
|
||||||
|
|
||||||
const html = await renderTemplate( 'systems/foundryvtt-reve-de-dragon/templates/dialog-fabriquer-potion-base.html', potionData);
|
const html = await renderTemplate(dialogConfig.html, potionData);
|
||||||
|
|
||||||
let options = { classes: ["dialogfabriquerpotion"], width: 600, height: 160, 'z-index': 99999 };
|
let options = { classes: ["dialogfabriquerpotion"], width: 600, height: 160, 'z-index': 99999 };
|
||||||
new DialogFabriquerPotion(actor, potionData, onActionItem, html, options).render(true);
|
mergeObject(options, dialogConfig.options ?? {}, { overwrite: true })
|
||||||
|
|
||||||
|
new DialogFabriquerPotion(actor, potionData, html, options).render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -32,14 +34,14 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(actor, potionData, onActionItem, html, options) {
|
constructor(actor, potionData, 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()
|
label: potionData.buttonName, callback: it => this.onFabriquer(html)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -48,7 +50,6 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
|
|
||||||
this.actor = actor;
|
this.actor = actor;
|
||||||
this.potionData = potionData;
|
this.potionData = potionData;
|
||||||
this.onActionItem = onActionItem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -63,11 +64,10 @@ export class DialogFabriquerPotion extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onFabriquer() {
|
async onFabriquer(html) {
|
||||||
await this.html.find("[name='nbBrins']").change();
|
await this.html.find("[name='nbBrins']").change();
|
||||||
await this.actor.fabriquerPotion(this.potionData);
|
this.actor.fabriquerPotion(this.potionData);
|
||||||
this.close();
|
this.close();
|
||||||
await this.onActionItem()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static nombreBrinsMinimum(herbeData) {
|
static nombreBrinsMinimum(herbeData) {
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
import { Misc } from "./misc.js";
|
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
|
||||||
export class DialogItemAchat extends Dialog {
|
export class DialogItemAchat extends Dialog {
|
||||||
|
|
||||||
static preparerAchat(chatButton) {
|
static venteData(button) {
|
||||||
const vendeurId = chatButton.attributes['data-vendeurId']?.value;
|
const vendeurId = button.attributes['data-vendeurId']?.value;
|
||||||
const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined;
|
const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined;
|
||||||
const acheteur = RdDUtility.getSelectedActor();
|
const acheteur = RdDUtility.getSelectedActor();
|
||||||
const json = chatButton.attributes['data-jsondata']?.value;
|
const json = button.attributes['data-jsondata']?.value;
|
||||||
if (!acheteur && !vendeur) {
|
if (!acheteur && !vendeur) {
|
||||||
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
|
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -17,66 +16,46 @@ export class DialogItemAchat extends Dialog {
|
|||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const prixLot = Number(button.attributes['data-prixLot']?.value ?? 0);
|
||||||
return {
|
return {
|
||||||
item: JSON.parse(json),
|
item: json ? JSON.parse(json) : undefined,
|
||||||
vendeur,
|
actingUserId: game.user.id,
|
||||||
acheteur,
|
vendeurId: vendeurId,
|
||||||
nbLots: parseInt(chatButton.attributes['data-quantiteNbLots']?.value),
|
vendeur: vendeur,
|
||||||
tailleLot: parseInt(chatButton.attributes['data-tailleLot']?.value ?? 1),
|
acheteur: acheteur,
|
||||||
prixLot: Number(chatButton.attributes['data-prixLot']?.value ?? 0),
|
tailleLot: parseInt(button.attributes['data-tailleLot']?.value ?? 1),
|
||||||
quantiteIllimite: chatButton.attributes['data-quantiteIllimite']?.value == 'true',
|
quantiteIllimite: button.attributes['data-quantiteIllimite']?.value == 'true',
|
||||||
chatMessageIdVente: RdDUtility.findChatMessageId(chatButton),
|
quantiteNbLots: parseInt(button.attributes['data-quantiteNbLots']?.value),
|
||||||
|
choix: {
|
||||||
|
nombreLots: 1,
|
||||||
|
seForcer: false,
|
||||||
|
supprimerSiZero: true
|
||||||
|
},
|
||||||
|
prixLot: prixLot,
|
||||||
|
prixTotal: prixLot,
|
||||||
|
isVente: prixLot > 0,
|
||||||
|
chatMessageIdVente: RdDUtility.findChatMessageId(button)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static async onAcheter(venteData) {
|
||||||
static async onAcheter({ item, vendeur, acheteur, tailleLot, prixLot, nbLots, quantiteIllimite, chatMessageIdVente }) {
|
|
||||||
const venteData = {
|
|
||||||
item,
|
|
||||||
actingUserId: game.user.id,
|
|
||||||
vendeur,
|
|
||||||
acheteur,
|
|
||||||
tailleLot,
|
|
||||||
quantiteIllimite,
|
|
||||||
quantiteNbLots: nbLots,
|
|
||||||
choix: { seForcer: false, supprimerSiZero: true },
|
|
||||||
prixLot,
|
|
||||||
isVente: prixLot > 0,
|
|
||||||
isConsommable: item.type == 'nourritureboisson' && acheteur?.isPersonnage(),
|
|
||||||
chatMessageIdVente
|
|
||||||
};
|
|
||||||
|
|
||||||
DialogItemAchat.changeNombreLots(venteData, 1);
|
|
||||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
|
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
|
||||||
new DialogItemAchat(html, venteData).render(true);
|
new DialogItemAchat(html, venteData).render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static changeNombreLots(venteData, nombreLots) {
|
|
||||||
venteData.choix.nombreLots = nombreLots;
|
|
||||||
venteData.prixTotal = (nombreLots * venteData.prixLot).toFixed(2);
|
|
||||||
if (venteData.isConsommable) {
|
|
||||||
const doses = nombreLots * venteData.tailleLot;
|
|
||||||
venteData.totalSust = Misc.keepDecimals(doses * (venteData.item.system.sust ?? 0), 2);
|
|
||||||
venteData.totalDesaltere = venteData.item.system.boisson
|
|
||||||
? Misc.keepDecimals(doses * (venteData.item.system.desaltere ?? 0), 2)
|
|
||||||
: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(html, venteData) {
|
constructor(html, venteData) {
|
||||||
|
const isConsommable = venteData.item.type == 'nourritureboisson' && venteData.acheteur?.isPersonnage();
|
||||||
let options = { classes: ["dialogachat"], width: 400, height: 'fit-content', 'z-index': 99999 };
|
let options = { classes: ["dialogachat"], width: 400, height: 'fit-content', 'z-index': 99999 };
|
||||||
|
|
||||||
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
|
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
|
||||||
const buttons = {};
|
const buttons = {};
|
||||||
if (venteData.isConsommable) {
|
if (isConsommable) {
|
||||||
buttons["consommer"] = { label: venteData.item.system.boisson ? "Boire" : "Manger", callback: it => this.onAchatConsommer() }
|
buttons["consommer"] = { label: venteData.item.system.boisson ? "Boire" : "Manger", callback: it => this.onAchatConsommer() }
|
||||||
}
|
}
|
||||||
buttons[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } };
|
buttons[actionAchat] = { label: actionAchat, callback: it => { this.onAchat(); } };
|
||||||
buttons["decliner"] = { label: "Décliner", callback: it => { } };
|
buttons["decliner"] = { label: "Décliner", callback: it => { } };
|
||||||
const acheteur = venteData.acheteur?.name ?? 'Un acheteur';
|
|
||||||
const vendeur = venteData.vendeur?.name ?? 'Un vendeur';
|
|
||||||
let conf = {
|
let conf = {
|
||||||
title: `${acheteur} - ${actionAchat} à ${vendeur}`,
|
title: venteData.acheteur ? venteData.acheteur.name + " - " + actionAchat : actionAchat,
|
||||||
content: html,
|
content: html,
|
||||||
default: actionAchat,
|
default: actionAchat,
|
||||||
buttons: buttons
|
buttons: buttons
|
||||||
@ -117,21 +96,13 @@ export class DialogItemAchat extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
setNombreLots(nombreLots) {
|
setNombreLots(nombreLots) {
|
||||||
|
if (nombreLots > this.venteData.quantiteNbLots) {
|
||||||
if (!this.venteData.quantiteIllimite) {
|
|
||||||
if (!this.venteData.quantiteIllimite && nombreLots > this.venteData.quantiteNbLots) {
|
|
||||||
ui.notifications.warn(`Seulement ${this.venteData.quantiteNbLots} lots disponibles, vous ne pouvez pas en prendre ${nombreLots}`)
|
ui.notifications.warn(`Seulement ${this.venteData.quantiteNbLots} lots disponibles, vous ne pouvez pas en prendre ${nombreLots}`)
|
||||||
}
|
}
|
||||||
nombreLots = Math.min(nombreLots, this.venteData.quantiteNbLots);
|
this.venteData.choix.nombreLots = Math.min(nombreLots, this.venteData.quantiteNbLots);
|
||||||
}
|
this.venteData.prixTotal = (nombreLots * this.venteData.prixLot).toFixed(2);
|
||||||
|
this.html.find(".nombreLots").val(this.venteData.choix.nombreLots);
|
||||||
DialogItemAchat.changeNombreLots(this.venteData, nombreLots);
|
|
||||||
|
|
||||||
this.html.find(".nombreLots").val(nombreLots);
|
|
||||||
this.html.find(".prixTotal").text(this.venteData.prixTotal);
|
this.html.find(".prixTotal").text(this.venteData.prixTotal);
|
||||||
this.html.find("span.total-sust").text(this.venteData.totalSust);
|
|
||||||
this.html.find("span.total-desaltere").text(this.venteData.totalDesaltere);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
@ -2,22 +2,21 @@ import { HtmlUtility } from "./html-utility.js";
|
|||||||
|
|
||||||
export class DialogItemVente extends Dialog {
|
export class DialogItemVente extends Dialog {
|
||||||
|
|
||||||
static async display({ item, callback, quantiteMax = undefined }) {
|
static async display(item, callback) {
|
||||||
const quantite = quantiteMax ?? item.getQuantite() ?? 1;
|
const quantite = item.isConteneur() ? 1 : item.system.quantite;
|
||||||
const isOwned = item.parent;
|
|
||||||
const venteData = {
|
const venteData = {
|
||||||
item: item,
|
item: item,
|
||||||
alias: item.actor?.name ?? game.user.name,
|
alias: item.actor?.name ?? game.user.name,
|
||||||
vendeurId: item.actor?.id,
|
vendeurId: item.actor?.id,
|
||||||
prixOrigine: item.calculerPrixCommercant(),
|
prixOrigine: item.system.cout,
|
||||||
prixUnitaire: item.calculerPrixCommercant(),
|
prixUnitaire: item.system.cout,
|
||||||
prixLot: item.calculerPrixCommercant(),
|
prixLot: item.system.cout,
|
||||||
tailleLot: 1,
|
tailleLot: 1,
|
||||||
quantiteNbLots: quantite,
|
quantiteNbLots: quantite,
|
||||||
quantiteMaxLots: quantite,
|
quantiteMaxLots: quantite,
|
||||||
quantiteMax: quantite,
|
quantiteMax: quantite ,
|
||||||
quantiteIllimite: item.isItemCommerce() ? quantiteMax == undefined : !isOwned,
|
quantiteIllimite: !item.isOwned,
|
||||||
isOwned: isOwned,
|
isOwned: item.isOwned,
|
||||||
};
|
};
|
||||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData);
|
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData);
|
||||||
return new DialogItemVente(venteData, html, callback).render(true);
|
return new DialogItemVente(venteData, html, callback).render(true);
|
||||||
@ -40,63 +39,55 @@ export class DialogItemVente extends Dialog {
|
|||||||
|
|
||||||
activateListeners(html) {
|
activateListeners(html) {
|
||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
|
|
||||||
this.html = html;
|
this.html = html;
|
||||||
|
HtmlUtility._showControlWhen(this.html.find(".quantiteNbLots"), !this.venteData.quantiteIllimite)
|
||||||
|
|
||||||
this.html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value)));
|
this.html.find(".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) {
|
||||||
this.updateVente(this.getChoixVente());
|
await this.html.find(".tailleLot").change();
|
||||||
|
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) {
|
||||||
const maxLots = Math.floor(this.venteData.quantiteMax / tailleLot);
|
// recalculer le prix du lot
|
||||||
this.updateVente({
|
if (tailleLot != this.venteData.tailleLot) {
|
||||||
tailleLot,
|
this.venteData.prixLot = (tailleLot * this.venteData.prixOrigine).toFixed(2);
|
||||||
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;
|
||||||
|
if (this.venteData.isOwned) {
|
||||||
|
// 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) {
|
||||||
this.updateVente({
|
if (this.venteData.isOwned) {
|
||||||
quantiteNbLots: this.venteData.isOwned ? Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots)) : nbLots
|
nbLots = Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots));
|
||||||
})
|
}
|
||||||
|
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.updateVente({ quantiteIllimite: checked })
|
this.venteData.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)
|
||||||
}
|
}
|
||||||
}
|
}
|
56
module/dialog-repos.js
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
|
||||||
|
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());
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -15,7 +15,7 @@ export class DialogStress extends Dialog {
|
|||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-stress.html", dialogData);
|
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/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(async actor => await actor.distribuerStress(compteur, stress, motif));
|
.forEach(actor => actor.distribuerStress(compteur, stress, motif));
|
||||||
}
|
}
|
||||||
|
|
||||||
async onSelectActor(event) {
|
async onSelectActor(event) {
|
@ -7,7 +7,7 @@ import { RdDUtility } from "./rdd-utility.js";
|
|||||||
*/
|
*/
|
||||||
export class DialogValidationEncaissement extends Dialog {
|
export class DialogValidationEncaissement extends Dialog {
|
||||||
|
|
||||||
static async validerEncaissement(actor, rollData, armure, show, attackerId, onEncaisser) {
|
static async validerEncaissement(actor, rollData, armure, show, onEncaisser) {
|
||||||
let encaissement = await RdDUtility.jetEncaissement(rollData, armure, { showDice: HIDE_DICE });
|
let encaissement = await RdDUtility.jetEncaissement(rollData, armure, { showDice: HIDE_DICE });
|
||||||
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', {
|
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', {
|
||||||
actor: actor,
|
actor: actor,
|
||||||
@ -15,15 +15,15 @@ export class DialogValidationEncaissement extends Dialog {
|
|||||||
encaissement: encaissement,
|
encaissement: encaissement,
|
||||||
show: show
|
show: show
|
||||||
});
|
});
|
||||||
const dialog = new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, show, attackerId, onEncaisser);
|
const dialog = new DialogValidationEncaissement(html, actor, rollData, armure, encaissement, show, onEncaisser);
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
constructor(html, actor, rollData, armure, encaissement, show, attackerId, onEncaisser) {
|
constructor(html, actor, rollData, armure, encaissement, show, onEncaisser) {
|
||||||
// Common conf
|
// Common conf
|
||||||
let buttons = {
|
let buttons = {
|
||||||
"valider": { label: "Valider", callback: html => this.onValider() },
|
"valider": { label: "Valider", callback: html => this.validerEncaissement() },
|
||||||
"annuler": { label: "Annuler", callback: html => { } },
|
"annuler": { label: "Annuler", callback: html => { } },
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -48,7 +48,6 @@ export class DialogValidationEncaissement extends Dialog {
|
|||||||
this.armure = armure;
|
this.armure = armure;
|
||||||
this.encaissement = encaissement;
|
this.encaissement = encaissement;
|
||||||
this.show = show;
|
this.show = show;
|
||||||
this.attackerId = attackerId;
|
|
||||||
this.onEncaisser = onEncaisser;
|
this.onEncaisser = onEncaisser;
|
||||||
this.forceDiceResult = {total: encaissement.roll.result };
|
this.forceDiceResult = {total: encaissement.roll.result };
|
||||||
}
|
}
|
||||||
@ -65,8 +64,8 @@ export class DialogValidationEncaissement extends Dialog {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async onValider() {
|
async validerEncaissement() {
|
||||||
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.attackerId)
|
this.onEncaisser(this.encaissement, this.show)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
import { ExperienceLog, XP_TOPIC } from "../actor/experience-log.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { ChatUtility } from "../chat-utility.js";
|
import { Poetique } from "./poetique.js";
|
||||||
import { Poetique } from "../poetique.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
import { RdDDice } from "../rdd-dice.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
import { TMRUtility } from "../tmr-utility.js";
|
|
||||||
|
|
||||||
export class EffetsRencontre {
|
export class EffetsRencontre {
|
||||||
|
|
||||||
@ -54,10 +53,9 @@ 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 fromXpSort = Number(competence.system.xp_sort);
|
const xpSort = Misc.toInt(competence.system.xp_sort) + context.rencontre.system.force;
|
||||||
const toXpSort = fromXpSort + context.rencontre.system.force;
|
await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': xpSort }]);
|
||||||
await this.updateEmbeddedDocuments("Item", [{ _id: compData._id, 'system.xp_sort': toXpSort }]);
|
await this.updateExperienceLog("XP Sort", xpSort, `Rencontre d'un ${context.rencontre.name} en TMR`);
|
||||||
await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXpSort, toXpSort, `${competence.name} - ${context.rencontre.name} en TMR`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1,78 +1,223 @@
|
|||||||
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, SystemCompendiums } from "./settings/system-compendiums.js";
|
import { CompendiumTableHelpers, CompendiumTable } from "./settings/system-compendiums.js";
|
||||||
|
|
||||||
|
const RARETES = [
|
||||||
|
{ name: 'Commune', frequence: 54, min: 27, max: 108 },
|
||||||
|
{ name: 'Frequente', frequence: 18, min: 9, max: 36 },
|
||||||
|
{ name: 'Rare', frequence: 6, min: 3, max: 12 },
|
||||||
|
{ name: 'Rarissime', frequence: 2, min: 1, max: 4 }]
|
||||||
|
const DEFAULT_RARETE = 1;
|
||||||
|
|
||||||
const COMPENDIUMS_RECHERCHE = 'compendiums-recherche';
|
const SETTINGS_LISTE_MILIEUX = "liste-milieux";
|
||||||
|
const MILIEUX = [
|
||||||
|
"Collines",
|
||||||
|
"Cours d'eau",
|
||||||
|
"Déserts",
|
||||||
|
"Forêts",
|
||||||
|
"Marais",
|
||||||
|
"Maritimes",
|
||||||
|
"Montagnes",
|
||||||
|
"Plaines",
|
||||||
|
"Sous-sols"
|
||||||
|
]
|
||||||
|
const ITEM_ENVIRONNEMENT_TYPES = [
|
||||||
|
'herbe', 'ingredient', 'faune'
|
||||||
|
]
|
||||||
|
|
||||||
export class Environnement {
|
export class Environnement {
|
||||||
static init() {
|
|
||||||
game.settings.register(SYSTEM_RDD, COMPENDIUMS_RECHERCHE, {
|
|
||||||
name: COMPENDIUMS_RECHERCHE,
|
|
||||||
default: [
|
|
||||||
SystemCompendiums.getCompendium('faune-flore-mineraux'),
|
|
||||||
SystemCompendiums.getCompendium('meditations-et-ecrits'),
|
|
||||||
SystemCompendiums.getCompendium('equipement')
|
|
||||||
],
|
|
||||||
scope: "world",
|
|
||||||
config: false,
|
|
||||||
type: Object
|
|
||||||
});
|
|
||||||
|
|
||||||
|
static init() {
|
||||||
|
game.settings.register(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX, {
|
||||||
|
name: "Liste des milieux proposés",
|
||||||
|
hint: "Liste des milieux proposés pour la faune&flore, séparés par des virgules",
|
||||||
|
scope: "world",
|
||||||
|
config: true,
|
||||||
|
default: MILIEUX.reduce(Misc.joining(',')),
|
||||||
|
type: String
|
||||||
|
});
|
||||||
game.system.rdd.environnement = new Environnement();
|
game.system.rdd.environnement = new Environnement();
|
||||||
Hooks.once('ready', () => game.system.rdd.environnement.onReady());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
this.compendiums = [];
|
this.table = new CompendiumTable('faune-flore-mineraux', 'Item', ITEM_ENVIRONNEMENT_TYPES)
|
||||||
this.compendiumTables = [];
|
|
||||||
this.mapMilieux = {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onReady() {
|
static getRarete(name = undefined) {
|
||||||
await this.$prepareCompendiums()
|
return RARETES.find(it => it.name == name) ?? RARETES[DEFAULT_RARETE];
|
||||||
|
}
|
||||||
|
|
||||||
|
static getFrequenceRarete(rarete, field = undefined) {
|
||||||
|
const selected = this.getRarete(rarete);
|
||||||
|
return selected[field];
|
||||||
}
|
}
|
||||||
|
|
||||||
async milieux() {
|
async milieux() {
|
||||||
return Object.values(this.mapMilieux);
|
return Object.values(await this.mapMilieux());
|
||||||
}
|
}
|
||||||
|
|
||||||
async saveCompendiums(compendiumIds) {
|
async mapMilieux() {
|
||||||
game.settings.set(SYSTEM_RDD, COMPENDIUMS_RECHERCHE, compendiumIds);
|
const compendiumItems = await this.getElements(it => 1, it => ITEM_ENVIRONNEMENT_TYPES.includes(it.type));
|
||||||
await this.$prepareCompendiums();
|
return Misc.indexLowercase(this.getMilieuxSettings().concat(Environnement.listMilieux(compendiumItems)));
|
||||||
}
|
}
|
||||||
|
|
||||||
async $prepareCompendiums() {
|
static listMilieux(items) {
|
||||||
this.compendiums = game.settings.get(SYSTEM_RDD, COMPENDIUMS_RECHERCHE).filter(c => SystemCompendiums.getPack(c));
|
return Misc.concat(items.map(it => Environnement.$itemToMilieux(it).filter(m => m)));
|
||||||
|
|
||||||
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 milieuxExistants = item.getMilieux().map(it => Grammar.toLowerCaseNoAccent(it));
|
const mapMilieux = await this.mapMilieux();
|
||||||
return Object.keys(this.mapMilieux)
|
const milieuxExistants = Environnement.$itemToMilieux(item).map(it => Grammar.toLowerCaseNoAccent(it));
|
||||||
|
return Object.keys(mapMilieux)
|
||||||
.filter(it => !milieuxExistants.includes(it))
|
.filter(it => !milieuxExistants.includes(it))
|
||||||
.map(it => this.mapMilieux[it]);
|
.map(it => mapMilieux[it]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static $itemToMilieux(item) {
|
||||||
|
return item.system.environnement.map(env => env.milieu);
|
||||||
|
}
|
||||||
|
|
||||||
|
getMilieuxSettings() {
|
||||||
|
return game.settings.get(SYSTEM_RDD, SETTINGS_LISTE_MILIEUX).split(',').map(it => it.trim()).filter(it => it != '');
|
||||||
|
}
|
||||||
|
|
||||||
|
async findEnvironnementsLike(search) {
|
||||||
|
const milieux = await this.mapMilieux();
|
||||||
|
const searchLower = Grammar.toLowerCaseNoAccent(search);
|
||||||
|
const keys = Object.keys(milieux).filter(it => it.includes(searchLower));
|
||||||
|
if (keys.length > 1) {
|
||||||
|
const milieuExact = milieux[searchLower];
|
||||||
|
if (milieuExact) {
|
||||||
|
return [milieuExact];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keys.map(k => milieux[k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async searchToChatMessage(milieux, typeName) {
|
||||||
|
const table = await this.buildEnvironnementTable(milieux);
|
||||||
|
await CompendiumTableHelpers.tableToChatMessage(table, 'Item', ITEM_ENVIRONNEMENT_TYPES, typeName);
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
async getRandom(milieux, typeName) {
|
||||||
|
const table = await this.buildEnvironnementTable(milieux);
|
||||||
|
return await CompendiumTableHelpers.getRandom(table, 'Item', ITEM_ENVIRONNEMENT_TYPES, undefined, typeName);
|
||||||
|
}
|
||||||
|
|
||||||
|
async buildEnvironnementTable(milieux) {
|
||||||
|
const filterMilieux = item => item.system?.environnement.filter(env => milieux.includes(env.milieu));
|
||||||
|
const itemRareteEnMilieu = item => {
|
||||||
|
const raretes = filterMilieux(item);
|
||||||
|
const frequenceMax = Math.max(raretes.map(env => env.frequence));
|
||||||
|
return raretes.find(env => env.frequence == frequenceMax);
|
||||||
|
}
|
||||||
|
const itemFrequenceEnMilieu = item => itemRareteEnMilieu(item)?.frequence ?? 0;
|
||||||
|
const isPresentEnMilieu = item => itemFrequenceEnMilieu(item) > 0;
|
||||||
|
return await this.table.buildTable(itemFrequenceEnMilieu, isPresentEnMilieu);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
async getElements(itemFrequence, filter) {
|
async getElements(itemFrequence, filter) {
|
||||||
const compendiumsElement = await Promise.all(
|
return await this.table.getContent(itemFrequence, filter);
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
async buildTable(itemFrequence, filter = it => true) {
|
|
||||||
if (!itemFrequence) {
|
|
||||||
itemFrequence = it => it.getFrequence()
|
|
||||||
}
|
|
||||||
const elements = await this.getElements(itemFrequence, filter);;
|
|
||||||
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class EnvironmentSheetHelper {
|
||||||
|
|
||||||
|
static defaultOptions(defaultOptions) {
|
||||||
|
return mergeObject(defaultOptions, {
|
||||||
|
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }]
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static setPosition(sheet, superPosition) {
|
||||||
|
const position = superPosition;
|
||||||
|
const sheetHeader = sheet.element.find(".sheet-header");
|
||||||
|
const sheetBody = sheet.element.find(".sheet-body");
|
||||||
|
sheetBody.css("height", position.height - sheetHeader[0].clientHeight)
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async getData(sheet, formData) {
|
||||||
|
return mergeObject(formData, {
|
||||||
|
milieux: await game.system.rdd.environnement.autresMilieux(sheet.item)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
static activateListeners(sheet) {
|
||||||
|
if (!sheet.options.editable) return;
|
||||||
|
|
||||||
|
sheet.html.find("input.input-selection-milieu").keypress(event => {
|
||||||
|
if (event.keyCode == '13') {
|
||||||
|
EnvironmentSheetHelper.onAddMilieu(sheet, event);
|
||||||
|
}
|
||||||
|
event.stopPropagation();
|
||||||
|
})
|
||||||
|
sheet.html.find("a.milieu-add").click(event => EnvironmentSheetHelper.onAddMilieu(sheet, event));
|
||||||
|
sheet.html.find("div.environnement-milieu a.milieu-delete").click(event => EnvironmentSheetHelper.onDeleteMilieu(sheet, event));
|
||||||
|
sheet.html.find("div.environnement-milieu select.environnement-rarete").change(event => EnvironmentSheetHelper.onChange(sheet, event,
|
||||||
|
updated => EnvironmentSheetHelper.$changeRarete(sheet, event, updated)));
|
||||||
|
sheet.html.find("div.environnement-milieu input[name='environnement-frequence']").change(event => EnvironmentSheetHelper.onChange(sheet, event,
|
||||||
|
updated => EnvironmentSheetHelper.$changeFrequence(sheet, event, updated)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static $changeFrequence(sheet, event, updated) {
|
||||||
|
updated.frequence = Number(sheet.html.find(event.currentTarget).val());
|
||||||
|
}
|
||||||
|
|
||||||
|
static $changeRarete(sheet, event, updated) {
|
||||||
|
const name = sheet.html.find(event.currentTarget).val();
|
||||||
|
const rarete = Environnement.getRarete(name);
|
||||||
|
updated.rarete = rarete.name;
|
||||||
|
updated.frequence = rarete.frequence;
|
||||||
|
// updated.frequence = Math.min(
|
||||||
|
// Math.max(rarete.min, updated.frequence ?? rarete.frequence),
|
||||||
|
// rarete.max);
|
||||||
|
}
|
||||||
|
|
||||||
|
static async onAddMilieu(sheet, event) {
|
||||||
|
const milieu = sheet.html.find('input.input-selection-milieu').val();
|
||||||
|
if (!milieu) {
|
||||||
|
ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${sheet.item.name}`);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const list = sheet.item.system.environnement;
|
||||||
|
const exists = list.find(it => it.milieu == milieu);
|
||||||
|
if (exists) {
|
||||||
|
ui.notifications.warn(`${sheet.item.name} a déjà une rareté ${exists.rarete} en ${milieu} (fréquence: ${exists.frequence})`);
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const rarete = Environnement.getRarete();
|
||||||
|
const newList = [...list, { milieu, rarete: rarete.name, frequence: rarete.frequence }].sort(Misc.ascending(it => it.milieu))
|
||||||
|
await sheet.item.update({ 'system.environnement': newList })
|
||||||
|
}
|
||||||
|
|
||||||
|
static async onDeleteMilieu(sheet, event) {
|
||||||
|
const milieu = EnvironmentSheetHelper.$getEventMilieu(sheet, event);
|
||||||
|
if (milieu != undefined) {
|
||||||
|
const newList = sheet.item.system.environnement.filter(it => it.milieu != milieu)
|
||||||
|
.sort(Misc.ascending(it => it.milieu));
|
||||||
|
await sheet.item.update({ 'system.environnement': newList });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static async onChange(sheet, event, doMutation) {
|
||||||
|
const list = sheet.item.system.environnement;
|
||||||
|
const milieu = EnvironmentSheetHelper.$getEventMilieu(sheet, event);
|
||||||
|
const updated = list.find(it => it.milieu == milieu);
|
||||||
|
if (updated) {
|
||||||
|
doMutation(updated);
|
||||||
|
const newList = [...list.filter(it => it.milieu != milieu), updated]
|
||||||
|
.sort(Misc.ascending(it => it.milieu));
|
||||||
|
await sheet.item.update({ 'system.environnement': newList });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static $getEventMilieu(sheet, event) {
|
||||||
|
return sheet.html.find(event.currentTarget)?.parents("div.environnement-milieu").data("milieu");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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,5 @@
|
|||||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
|
||||||
import { TYPES } from "./item.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
import { RdDCombatManager } from "./rdd-combat.js";
|
||||||
|
|
||||||
const nomCategorieParade = {
|
const nomCategorieParade = {
|
||||||
@ -20,7 +20,7 @@ const nomCategorieParade = {
|
|||||||
export class RdDItemArme extends Item {
|
export class RdDItemArme extends Item {
|
||||||
|
|
||||||
static isArme(item) {
|
static isArme(item) {
|
||||||
return RdDItemCompetenceCreature.getCategorieAttaque(item) || item.type == 'arme';
|
return (item.type == 'competencecreature' && item.system.iscombat) || item.type == 'arme';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -28,7 +28,7 @@ export class RdDItemArme extends Item {
|
|||||||
switch (arme ? arme.type : '') {
|
switch (arme ? arme.type : '') {
|
||||||
case 'arme': return arme;
|
case 'arme': return arme;
|
||||||
case 'competencecreature':
|
case 'competencecreature':
|
||||||
return RdDItemCompetenceCreature.armeCreature(arme);
|
return RdDItemCompetenceCreature.armeNaturelle(arme);
|
||||||
}
|
}
|
||||||
return RdDItemArme.mainsNues();
|
return RdDItemArme.mainsNues();
|
||||||
}
|
}
|
||||||
@ -166,7 +166,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) {
|
||||||
|
@ -23,7 +23,7 @@ const limitesArchetypes = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
const categoriesCompetences = {
|
const categorieCompetences = {
|
||||||
"generale": { base: -4, label: "Générales" },
|
"generale": { base: -4, label: "Générales" },
|
||||||
"particuliere": { base: -8, label: "Particulières" },
|
"particuliere": { base: -8, label: "Particulières" },
|
||||||
"specialisee": { base: -11, label: "Spécialisées" },
|
"specialisee": { base: -11, label: "Spécialisées" },
|
||||||
@ -49,16 +49,16 @@ const competence_xp_cumul = _buildCumulXP();
|
|||||||
|
|
||||||
export class RdDItemCompetence extends Item {
|
export class RdDItemCompetence extends Item {
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getCategories() {
|
static getCategorieCompetences() {
|
||||||
return categoriesCompetences;
|
return categorieCompetences;
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static getNiveauBase(category) {
|
||||||
|
return categorieCompetences[category].base;
|
||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getLabelCategorie(category) {
|
static getLabelCategorie(category) {
|
||||||
return categoriesCompetences[category].label;
|
return categorieCompetences[category].label;
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static getNiveauBase(category, categories = categoriesCompetences) {
|
|
||||||
return categories[category]?.base ?? 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -190,9 +190,18 @@ 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, item.getCategories());
|
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -270,7 +279,7 @@ export class RdDItemCompetence extends Item {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static triVisible(competences) {
|
static triVisible(competences) {
|
||||||
return competences.filter(it => !it.system.isHidden)
|
return competences.filter(it => it.system.isVisible)
|
||||||
.sort((a, b) => RdDItemCompetence.compare(a, b))
|
.sort((a, b) => RdDItemCompetence.compare(a, b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,95 +1,49 @@
|
|||||||
|
|
||||||
import { RdDItem, TYPES } from "./item.js";
|
|
||||||
import { RdDCombatManager } from "./rdd-combat.js";
|
import { RdDCombatManager } from "./rdd-combat.js";
|
||||||
|
|
||||||
const categories = {
|
|
||||||
"generale": { base: 0, label: "Générale" },
|
|
||||||
"naturelle": { base: 0, label: "Arme naturelle" },
|
|
||||||
"melee": { base: 0, label: "Mêlée" },
|
|
||||||
"parade": { base: 0, label: "Parade" },
|
|
||||||
"tir": { base: 0, label: "Tir" },
|
|
||||||
"lancer": { base: 0, label: "Lancer" },
|
|
||||||
"possession": { base: 0, label: "Possession" },
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDItemCompetenceCreature extends Item {
|
export class RdDItemCompetenceCreature extends Item {
|
||||||
|
|
||||||
static getCategories() {
|
|
||||||
return categories;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static setRollDataCreature(rollData) {
|
static setRollDataCreature(rollData) {
|
||||||
|
rollData.competence = rollData.competence
|
||||||
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } }
|
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } }
|
||||||
rollData.competence.system.defaut_carac = "carac_creature"
|
rollData.competence.system.defaut_carac = "carac_creature"
|
||||||
|
rollData.competence.system.categorie = "creature"
|
||||||
rollData.selectedCarac = rollData.carac.carac_creature
|
rollData.selectedCarac = rollData.carac.carac_creature
|
||||||
rollData.arme = RdDItemCompetenceCreature.armeCreature(rollData.competence);
|
if (rollData.competence.system.iscombat) {
|
||||||
|
rollData.arme = RdDItemCompetenceCreature.armeNaturelle(rollData.competence);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static armeCreature(item) {
|
static armeNaturelle(competencecreature) {
|
||||||
const categorieAttaque = RdDItemCompetenceCreature.getCategorieAttaque(item)
|
if (RdDItemCompetenceCreature.isCompetenceAttaque(competencecreature)) {
|
||||||
if (categorieAttaque != undefined) {
|
// si c'est un Item compétence: cloner pour ne pas modifier lma compétence
|
||||||
// si c'est un Item compétence: cloner pour ne pas modifier la compétence
|
let arme = (competencecreature instanceof Item) ? competencecreature.clone(): competencecreature;
|
||||||
let arme = item.clone();
|
mergeObject(arme.system,
|
||||||
mergeObject(arme,
|
|
||||||
{
|
{
|
||||||
action: item.isCompetencePossession() ? 'possession' : 'attaque',
|
|
||||||
system: {
|
|
||||||
competence: arme.name,
|
competence: arme.name,
|
||||||
cac: categorieAttaque == "naturelle" ? "naturelle" : "",
|
initiative: RdDCombatManager.calculInitiative(competencecreature.system.niveau, competencecreature.system.carac_value),
|
||||||
niveau: item.system.niveau,
|
niveau: competencecreature.system.niveau,
|
||||||
initiative: RdDCombatManager.calculInitiative(item.system.niveau, item.system.carac_value),
|
|
||||||
equipe: true,
|
equipe: true,
|
||||||
resistance: 100,
|
resistance: 100,
|
||||||
dommagesReels: arme.system.dommages,
|
dommagesReels: arme.system.dommages,
|
||||||
penetration: 0,
|
penetration: 0,
|
||||||
force: 0,
|
force: 0,
|
||||||
rapide: true,
|
rapide: true,
|
||||||
}
|
cac: competencecreature.system.isnaturelle ? "naturelle" : "",
|
||||||
|
action: 'attaque'
|
||||||
});
|
});
|
||||||
return arme;
|
return arme;
|
||||||
}
|
}
|
||||||
|
console.error("RdDItemCompetenceCreature.toActionArme(", competencecreature, ") : impossible de transformer l'Item en arme");
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getCategorieAttaque(item) {
|
static isCompetenceAttaque(item) {
|
||||||
if (item.type == TYPES.competencecreature) {
|
return item.type == 'competencecreature' && item.system.iscombat;
|
||||||
switch (item.system.categorie) {
|
|
||||||
case "melee":
|
|
||||||
case "tir":
|
|
||||||
case "lancer":
|
|
||||||
case "naturelle":
|
|
||||||
case "possession":
|
|
||||||
return item.system.categorie
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
static isDommages(item) {
|
|
||||||
if (item.type == TYPES.competencecreature) {
|
|
||||||
switch (item.system.categorie) {
|
|
||||||
case "melee":
|
|
||||||
case "tir":
|
|
||||||
case "lancer":
|
|
||||||
case "naturelle":
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
static isParade(item) {
|
|
||||||
if (item.type == TYPES.competencecreature) {
|
|
||||||
switch (item.system.categorie) {
|
|
||||||
case "melee":
|
|
||||||
case "naturelle":
|
|
||||||
case "parade":
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
import { RdDBaseActorSheet } from "../actor/base-actor-sheet.js";
|
import { RdDItemSheet } from "./item-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 RdDItemInventaireSheet {
|
export class RdDConteneurItemSheet extends RdDItemSheet {
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "conteneur" };
|
static get ITEM_TYPE() { return "conteneur" };
|
||||||
|
|
||||||
@ -28,8 +27,9 @@ export class RdDConteneurItemSheet extends RdDItemInventaireSheet {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
prepareConteneurData(formData) {
|
prepareConteneurData(formData) {
|
||||||
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
|
RdDUtility.filterEquipementParType(formData, this.actor.itemTypes);
|
||||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
|
|
||||||
|
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,8 +43,7 @@ export class RdDConteneurItemSheet extends RdDItemInventaireSheet {
|
|||||||
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));
|
||||||
@ -52,8 +51,7 @@ export class RdDConteneurItemSheet extends RdDItemInventaireSheet {
|
|||||||
|
|
||||||
async _onDropItem(event, dragData) {
|
async _onDropItem(event, dragData) {
|
||||||
if (this.actor) {
|
if (this.actor) {
|
||||||
const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id') ?? this.item.id
|
const dropParams = RdDSheetUtility.prepareItemDropParameters(this.item.id, this.actor, dragData, this.objetVersConteneur);
|
||||||
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);
|
||||||
}
|
}
|
67
module/item-faune-sheet.js
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { EnvironmentSheetHelper } from "./environnement.js";
|
||||||
|
import { RdDItemSheet } from "./item-sheet.js";
|
||||||
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
|
||||||
|
export class RdDFauneItemSheet extends RdDItemSheet {
|
||||||
|
|
||||||
|
static get ITEM_TYPE() { return "faune" };
|
||||||
|
|
||||||
|
static get defaultOptions() {
|
||||||
|
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPosition(options = {}) {
|
||||||
|
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getData() {
|
||||||
|
const formData = await super.getData();
|
||||||
|
return await EnvironmentSheetHelper.getData(this, formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
if (!this.options.editable) return;
|
||||||
|
|
||||||
|
EnvironmentSheetHelper.activateListeners(this);
|
||||||
|
|
||||||
|
html.find("a.linked-actor-delete").click(event => this.onDeleteLinkedActor());
|
||||||
|
html.find("a.preparer-nourriture").click(event => this.preparerNourriture(event));
|
||||||
|
html.find("a.manger-nourriture").click(event => this.mangerNourriture(event));
|
||||||
|
}
|
||||||
|
|
||||||
|
async _onDropActor(event, dragData) {
|
||||||
|
console.log('faune:dropActor', event, dragData)
|
||||||
|
const linkedActor = fromUuidSync(dragData.uuid);
|
||||||
|
if (linkedActor?.pack) {
|
||||||
|
this.item.update({
|
||||||
|
'system.actor.pack': linkedActor.pack,
|
||||||
|
'system.actor.id': linkedActor._id,
|
||||||
|
'system.actor.name': linkedActor.name
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ui.notifications.warn(`${linkedActor.name} ne provient pas d'un compendium.
|
||||||
|
<br>Choisissez une créature du compendium pour représenter un élément de faune générique`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async onDeleteLinkedActor() {
|
||||||
|
this.item.update({
|
||||||
|
'system.actor.pack': '',
|
||||||
|
'system.actor.id': '',
|
||||||
|
'system.actor.name': ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async preparerNourriture(event) {
|
||||||
|
if (this.actor) {
|
||||||
|
await this.actor.preparerNourriture(this.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
async mangerNourriture(event) {
|
||||||
|
if (this.actor) {
|
||||||
|
await this.actor.mangerNourriture(this.item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
25
module/item-herbe-sheet.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { EnvironmentSheetHelper } from "./environnement.js";
|
||||||
|
import { RdDItemSheet } from "./item-sheet.js";
|
||||||
|
|
||||||
|
export class RdDHerbeItemSheet extends RdDItemSheet {
|
||||||
|
|
||||||
|
static get ITEM_TYPE() { return "herbe" };
|
||||||
|
|
||||||
|
static get defaultOptions() {
|
||||||
|
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPosition(options = {}) {
|
||||||
|
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getData() {
|
||||||
|
const formData = await super.getData();
|
||||||
|
return await EnvironmentSheetHelper.getData(this, formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
EnvironmentSheetHelper.activateListeners(this);
|
||||||
|
}
|
||||||
|
}
|
25
module/item-ingredient-sheet.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { EnvironmentSheetHelper } from "./environnement.js";
|
||||||
|
import { RdDItemSheet } from "./item-sheet.js";
|
||||||
|
|
||||||
|
export class RdDIngredientItemSheet extends RdDItemSheet {
|
||||||
|
|
||||||
|
static get ITEM_TYPE() { return "ingredient" };
|
||||||
|
|
||||||
|
static get defaultOptions() {
|
||||||
|
return EnvironmentSheetHelper.defaultOptions(super.defaultOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
setPosition(options = {}) {
|
||||||
|
return EnvironmentSheetHelper.setPosition(this, super.setPosition(options));
|
||||||
|
}
|
||||||
|
|
||||||
|
async getData() {
|
||||||
|
const formData = await super.getData();
|
||||||
|
return await EnvironmentSheetHelper.getData(this, formData);
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
EnvironmentSheetHelper.activateListeners(this);
|
||||||
|
}
|
||||||
|
}
|
@ -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: "Dragon (or)", type: 'monnaie',
|
name: "Dreagon (or)", type: 'monnaie',
|
||||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
|
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
|
||||||
system: { quantite: 0, cout: 10, encombrement: 0.004, description: "" }
|
system: { quantite: 0, cout: 10, encombrement: 0.004, description: "" }
|
||||||
};
|
};
|
||||||
@ -62,24 +62,21 @@ export class Monnaie {
|
|||||||
return deniers;
|
return deniers;
|
||||||
}
|
}
|
||||||
|
|
||||||
static toSolsDeniers(fortune) {
|
static getFortune(actor) {
|
||||||
return {
|
if (actor) {
|
||||||
sols: Math.floor(fortune),
|
Monnaie.validerMonnaies(actor);
|
||||||
deniers: Math.round(100 * (fortune - Math.floor(fortune)))
|
return actor.itemTypes['monnaie']
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getFortune(monnaies) {
|
|
||||||
return (monnaies??[])
|
|
||||||
.map(m => Number(m.system.cout) * Number(m.system.quantite))
|
.map(m => Number(m.system.cout) * Number(m.system.quantite))
|
||||||
.reduce(Misc.sum(), 0);
|
.reduce(Misc.sum(), 0);
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static async optimiserFortune(actor, fortune) {
|
static async optimiserFortune(actor, fortune) {
|
||||||
let resteEnDeniers = Math.round(fortune * 100);
|
let resteEnDeniers = Math.round(fortune * 100);
|
||||||
let monnaies = actor.itemTypes['monnaie'];
|
let monnaies = actor.itemTypes['monnaie'];
|
||||||
let updates = [];
|
let updates = [];
|
||||||
Monnaie.validerMonnaies(monnaies, actor);
|
Monnaie.validerMonnaies(actor);
|
||||||
|
|
||||||
let parValeur = Misc.classifyFirst(monnaies, it => VALEUR_DENIERS(it.system.cout));
|
let parValeur = Misc.classifyFirst(monnaies, it => VALEUR_DENIERS(it.system.cout));
|
||||||
for (let valeurDeniers of [1000, 100, 10, 1]) {
|
for (let valeurDeniers of [1000, 100, 10, 1]) {
|
||||||
@ -102,9 +99,9 @@ export class Monnaie {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static validerMonnaies(monnaies, actor = undefined) {
|
static validerMonnaies(actor) {
|
||||||
monnaies.filter(it => VALEUR_DENIERS(it.system.cout) == 0)
|
actor.itemTypes['monnaie'].filter(it => VALEUR_DENIERS(it.system.cout) == 0)
|
||||||
.map(it => `La monnaie ${it.name} de l'acteur ${actor?.name ?? 'sélectionné'} a une valeur de 0!`)
|
.map(it => `La monnaie ${it.name} de l'acteur ${actor.name} a une valeur de 0!`)
|
||||||
.forEach(message => {
|
.forEach(message => {
|
||||||
ui.notifications.warn(message);
|
ui.notifications.warn(message);
|
||||||
console.warn(message);
|
console.warn(message);
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { RdDRencontre } from "./rencontre.js";
|
import { RdDRencontre } from "./item-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,5 +1,4 @@
|
|||||||
import { EffetsRencontre } from "../tmr/effets-rencontres.js";
|
import { EffetsRencontre } from "./effets-rencontres.js";
|
||||||
import { RdDItem } from "../item.js";
|
|
||||||
|
|
||||||
const tableEffets = [
|
const tableEffets = [
|
||||||
{ code: "messager", resultat: "succes", description: "Envoie un message à (force) cases", method: EffetsRencontre.messager },
|
{ code: "messager", resultat: "succes", description: "Envoie un message à (force) cases", method: EffetsRencontre.messager },
|
||||||
@ -37,11 +36,7 @@ const tableEffets = [
|
|||||||
// { code: "epart-souffle", resultat: "echec", description: "Souffle de dragon sur échec particulier" },
|
// { code: "epart-souffle", resultat: "echec", description: "Souffle de dragon sur échec particulier" },
|
||||||
];
|
];
|
||||||
|
|
||||||
export class RdDRencontre extends RdDItem {
|
export class RdDRencontre {
|
||||||
|
|
||||||
static get defaultIcon() {
|
|
||||||
return "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp";
|
|
||||||
}
|
|
||||||
|
|
||||||
static getEffetsSucces() { return RdDRencontre.getEffets("succes"); }
|
static getEffetsSucces() { return RdDRencontre.getEffets("succes"); }
|
||||||
static getEffetsEchec() { return RdDRencontre.getEffets("echec"); }
|
static getEffetsEchec() { return RdDRencontre.getEffets("echec"); }
|
||||||
@ -73,8 +68,4 @@ export class RdDRencontre extends RdDItem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async calculerFinPeriodeTemporel(debut) {
|
|
||||||
return await debut.nouvelleHeure().addHeures(12);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
@ -10,9 +10,6 @@ import { SYSTEM_RDD } from "./constants.js";
|
|||||||
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
|
||||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
|
||||||
import { TYPES } from "./item.js";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extend the basic ItemSheet for RdD specific items
|
* Extend the basic ItemSheet for RdD specific items
|
||||||
@ -63,13 +60,13 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
buttons.unshift({
|
buttons.unshift({
|
||||||
class: "vendre",
|
class: "vendre",
|
||||||
icon: "fas fa-comments-dollar",
|
icon: "fas fa-comments-dollar",
|
||||||
onclick: ev => this.item.proposerVente(1)
|
onclick: ev => this.item.proposerVente()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
buttons.unshift({
|
buttons.unshift({
|
||||||
class: "montrer",
|
class: "montrer",
|
||||||
icon: "fas fa-comment",
|
icon: "fas fa-comment",
|
||||||
onclick: ev => this.item.postItemToChat()
|
onclick: ev => this.item.postItem()
|
||||||
});
|
});
|
||||||
return buttons
|
return buttons
|
||||||
}
|
}
|
||||||
@ -88,32 +85,33 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async getData() {
|
async getData() {
|
||||||
let formData = {
|
let formData = {
|
||||||
title: this.item.name,
|
|
||||||
id: this.item.id,
|
id: this.item.id,
|
||||||
|
title: this.item.name,
|
||||||
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.getUtilisationCuisine(),
|
isComestible: this.item.isComestible()
|
||||||
options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable)
|
|
||||||
}
|
|
||||||
if (this.item.type == TYPES.competencecreature) {
|
|
||||||
formData.isparade = RdDItemCompetenceCreature.isParade(this.item)
|
|
||||||
formData.isdommages = RdDItemCompetenceCreature.isDommages(this.item)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const competences = await SystemCompendiums.getCompetences('personnage');
|
const competences = await SystemCompendiums.getCompetences(this.actor?.type);
|
||||||
formData.categories = this.item.getCategories()
|
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences()
|
||||||
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
|
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
|
||||||
formData.caracList = duplicate(game.system.model.Actor.personnage.carac)
|
formData.caracList = duplicate(game.system.model.Actor.personnage.carac)
|
||||||
formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve)
|
formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve)
|
||||||
formData.competences = 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));
|
||||||
@ -137,14 +135,18 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
RdDGemme.calculDataDerivees(this.item);
|
RdDGemme.calculDataDerivees(this.item);
|
||||||
}
|
}
|
||||||
if (this.item.type == 'potion') {
|
if (this.item.type == 'potion') {
|
||||||
await RdDHerbes.addPotionFormData(formData);
|
if (this.dateUpdated) {
|
||||||
|
formData.system.prdate = this.dateUpdated;
|
||||||
|
this.dateUpdated = undefined;
|
||||||
}
|
}
|
||||||
if (formData.options.isOwned && this.item.type == 'herbe' && (formData.system.categorie == 'Soin' || formData.system.categorie == 'Repos')) {
|
await RdDHerbes.updatePotionData(formData);
|
||||||
|
}
|
||||||
|
if (formData.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.options.isOwned ? this.item.actor.items.get(sortId) : game.items.get(sortId);
|
formData.sort = formData.isOwned ? this.item.actor.items.get(sortId) : game.items.get(sortId);
|
||||||
}
|
}
|
||||||
formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true);
|
formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true);
|
||||||
|
|
||||||
@ -157,10 +159,8 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
super.activateListeners(html);
|
super.activateListeners(html);
|
||||||
this.html = html;
|
this.html = html;
|
||||||
|
|
||||||
HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs')
|
HtmlUtility._showControlWhen(this.html.find(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.item.isOwned);
|
||||||
|| game.user.isGM
|
HtmlUtility._showControlWhen(this.html.find(".item-magique"), this.item.isMagique());
|
||||||
|| !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;
|
||||||
@ -185,16 +185,14 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
this.html.find('.date-enchantement').change((event) => {
|
this.html.find('.enchanteDate').change((event) => {
|
||||||
const jour = Number(this.html.find('input.date-enchantement[name="enchantement.jour"]').val());
|
let jour = Number(this.html.find('[name="splitDate.day"]').val());
|
||||||
const mois = RdDTimestamp.definition(this.html.find('select.date-enchantement[name="enchantement.mois"]').val());
|
let mois = this.html.find('[name="splitDate.month"]').val();
|
||||||
const indexDate = game.system.rdd.calendrier.getIndexFromDate(jour, mois.heure);
|
this.dateUpdated = game.system.rdd.calendrier.getIndexFromDate(jour, mois);
|
||||||
this.item.update({ 'system.prdate': indexDate });
|
|
||||||
console.warn(`Date d'enchantement modifiée ${jour}/${mois.heure}: ${indexDate}`)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.html.find('.creer-tache-livre').click((event) => this._getEventActor(event).creerTacheDepuisLivre(this.item));
|
this.html.find('.creer-tache-livre').click((event) => this._getEventActor(event).creerTacheDepuisLivre(this.item));
|
||||||
this.html.find('.consommer-potion').click((event) => this._getEventActor(event).consommerPotion(this.item, this.getActionRenderItem()));
|
this.html.find('.consommer-potion').click((event) => this._getEventActor(event).consommerPotion(this.item));
|
||||||
this.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) => {
|
||||||
@ -209,38 +207,12 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (this.actor) {
|
this.html.find('.item-split').click(async event => RdDSheetUtility.splitItem(RdDSheetUtility.getItem(event, this.actor), this.actor, async () => this.render(true)));
|
||||||
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.confirmerSuppressionItem(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)?.postItem());
|
||||||
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor, this.getActionRenderItem()));
|
this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor, async () => this.render(true)));
|
||||||
|
|
||||||
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) })
|
|
||||||
|
|
||||||
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.debut', 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) {
|
||||||
@ -249,14 +221,12 @@ export class RdDItemSheet extends ItemSheet {
|
|||||||
return actor;
|
return actor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async _onSelectCategorie(event) {
|
async _onSelectCategorie(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
|
|
||||||
if (this.item.isCompetence()) {
|
if (this.item.isCompetence()) {
|
||||||
const categorie = event.currentTarget.value;
|
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
|
||||||
const level = RdDItemCompetence.getNiveauBase(categorie, this.item.getCategories());
|
|
||||||
this.item.system.base = level;
|
this.item.system.base = level;
|
||||||
this.html.find('[name="system.base"]').val(level);
|
this.html.find('[name="system.base"]').val(level);
|
||||||
}
|
}
|
||||||
@ -267,8 +237,9 @@ 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.buildBonuscaseFromArrays(formData.bonusValue, formData.caseValue);
|
formData['system.bonuscase'] = RdDItemSort.buildBonusCaseStringFromFormData(formData.bonusValue, formData.caseValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.item.update(formData);
|
return this.item.update(formData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { RdDItemSheet } from "../item-sheet.js";
|
import { RdDItemSheet } from "./item-sheet.js";
|
||||||
import { RdDItemSigneDraconique } from "./signedraconique.js";
|
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
|
||||||
import { TMRUtility } from "../tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Item sheet pour signes draconiques
|
* Item sheet pour signes draconiques
|
@ -1,9 +1,8 @@
|
|||||||
import { RdDItem, defaultItemImg } from "../item.js";
|
import { 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 "../time/rdd-timestamp.js";
|
import { TMRType, TMRUtility } from "./tmr-utility.js";
|
||||||
import { TMRType, TMRUtility } from "../tmr-utility.js";
|
|
||||||
|
|
||||||
const tableSignesIndicatifs = [
|
const tableSignesIndicatifs = [
|
||||||
{ rarete: "Très facile", difficulte: 0, xp: 6, nbCases: 14 },
|
{ rarete: "Très facile", difficulte: 0, xp: 6, nbCases: 14 },
|
||||||
@ -16,17 +15,7 @@ const tableSignesIndicatifs = [
|
|||||||
|
|
||||||
const DIFFICULTE_LECTURE_SIGNE_MANQUE = +11;
|
const DIFFICULTE_LECTURE_SIGNE_MANQUE = +11;
|
||||||
|
|
||||||
export class RdDItemSigneDraconique extends RdDItem {
|
export class RdDItemSigneDraconique {
|
||||||
|
|
||||||
static get defaultIcon() {
|
|
||||||
return "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
async calculerFinPeriodeTemporel(debut) {
|
|
||||||
// TODO
|
|
||||||
return RdDTimestamp.formulesDuree().find(it => it.code == "").calcul(debut, this.actor);
|
|
||||||
}
|
|
||||||
|
|
||||||
static prepareSigneDraconiqueMeditation(meditation, rolled) {
|
static prepareSigneDraconiqueMeditation(meditation, rolled) {
|
||||||
return {
|
return {
|
@ -1,3 +1,4 @@
|
|||||||
|
/* -------------------------------------------- */
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
|
||||||
@ -15,7 +16,7 @@ export class RdDItemSort extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static setCoutReveReel(sort) {
|
static setCoutReveReel(sort){
|
||||||
if (sort) {
|
if (sort) {
|
||||||
sort.system.ptreve_reel = this.isCoutVariable(sort) ? 1 : sort.system.ptreve;
|
sort.system.ptreve_reel = this.isCoutVariable(sort) ? 1 : sort.system.ptreve;
|
||||||
}
|
}
|
||||||
@ -30,22 +31,30 @@ export class RdDItemSort extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static buildBonusCaseList(bonuscase, newCase) {
|
static buildBonusCaseList( caseBonusString, newCase ) {
|
||||||
const list = RdDItemSort._bonuscaseStringToList(bonuscase)
|
if (caseBonusString == undefined) {
|
||||||
if (newCase) {
|
return [];
|
||||||
return list.concat({ case: "Nouvelle", bonus: 0 });
|
|
||||||
}
|
}
|
||||||
return list;
|
let bonusCaseList = [];
|
||||||
|
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
|
||||||
*/
|
*/
|
||||||
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 RdDItemSort.buildBonusCaseList(item.system.bonuscase, newCase);
|
return this.buildBonusCaseList(item.system.bonuscase, newCase );
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@ -54,61 +63,56 @@ 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 buildBonuscaseFromArrays(bonuses, coords) {
|
static buildBonusCaseStringFromFormData( bonuses, cases ) {
|
||||||
if (bonuses) {
|
if ( bonuses ) {
|
||||||
const list = [];
|
let list = [];
|
||||||
const caseCheck = {};
|
let caseCheck = {};
|
||||||
for (let i = 0; i < bonuses.length && i < coords.length; i++) {
|
for (let i=0; i<bonuses.length; i++) {
|
||||||
const coord = coords[i] == 'Fleuve' ? 'Fleuve' : (coords[i]?.toUpperCase() ?? 'A1');
|
let coord = cases[i]?.toUpperCase() || 'A1';
|
||||||
const bonus = bonuses[i] || 0;
|
let 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({ case: coord, bonus: bonus });
|
list.push( coord+":"+bonus );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return RdDItemSort._bonuscaseListToString(list);
|
return list.toString();
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static incrementBonusCase(actor, sort, coord) {
|
static incrementBonusCase( actor, sort, coord ) {
|
||||||
if (TMRUtility.getTMR(coord).type == "fleuve") {
|
let bonusCaseList = this.buildBonusCaseList(sort.system.bonuscase, false);
|
||||||
coord = 'Fleuve';
|
//console.log("ITEMSORT", sort, bonusCaseList);
|
||||||
}
|
|
||||||
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 };
|
|
||||||
|
|
||||||
const bonuscase = RdDItemSort._bonuscaseListToString(
|
let found = false;
|
||||||
list.filter(it => it.case != coord).concat(modified)
|
let StringList = [];
|
||||||
);
|
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
|
||||||
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]);
|
let bonuscase = StringList.toString();
|
||||||
|
//console.log("Bonus cae :", bonuscase);
|
||||||
|
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static getCaseBonus(sort, coord) {
|
static getCaseBonus( sort, coord) {
|
||||||
const isFleuve = TMRUtility.getTMR(coord).type == "fleuve";
|
let bonusCaseList = this.buildBonusCaseList(sort.system.bonuscase, false);
|
||||||
|
for( let bc of bonusCaseList) {
|
||||||
let bc = RdDItemSort.buildBonusCaseList(sort.system.bonuscase, false)
|
if (bc.case == coord) { // Case existante
|
||||||
.filter(it => it.case == coord || (isFleuve && it.case == 'Fleuve'))
|
return Number(bc.bonus);
|
||||||
.find(it => true)
|
|
||||||
return Number(bc?.bonus ?? 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static _bonuscaseListToString(list) {
|
|
||||||
return list.map(it => `${it.case}:${it.bonus}`)
|
|
||||||
.sort(Misc.ascending())
|
|
||||||
.join(',');
|
|
||||||
}
|
}
|
||||||
static _bonuscaseStringToList(bonuscase) {
|
return 0;
|
||||||
return (bonuscase ?? '').split(',').map(it => {
|
|
||||||
const b = it.split(':');
|
|
||||||
return { case: b[0], bonus: b[1] };
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
4
module/item-tache.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
export class RdDItemTache extends Item {
|
||||||
|
|
||||||
|
|
||||||
|
}
|
434
module/item.js
@ -2,88 +2,28 @@ 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 "./time/rdd-timestamp.js";
|
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { SystemCompendiums } from "./settings/system-compendiums.js";
|
|
||||||
import { RdDRaretes } from "./item/raretes.js";
|
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
|
||||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
|
||||||
|
|
||||||
export const TYPES = {
|
const typesObjetsInventaire = [
|
||||||
competence: 'competence',
|
"arme",
|
||||||
competencecreature: 'competencecreature',
|
"armure",
|
||||||
empoignade: 'empoignade',
|
"conteneur",
|
||||||
possession: 'possession',
|
"gemme",
|
||||||
blessure: 'blessure',
|
"herbe",
|
||||||
maladie: 'maladie',
|
"ingredient",
|
||||||
poison: 'poison',
|
"faune",
|
||||||
arme: 'arme',
|
"livre",
|
||||||
armure: 'armure',
|
"monnaie",
|
||||||
conteneur: 'conteneur',
|
"munition",
|
||||||
objet: 'objet',
|
"nourritureboisson",
|
||||||
monnaie: 'monnaie',
|
"objet",
|
||||||
gemme: 'gemme',
|
"potion",
|
||||||
munition: 'munition',
|
|
||||||
nourritureboisson: 'nourritureboisson',
|
|
||||||
herbe: 'herbe',
|
|
||||||
plante: 'plante',
|
|
||||||
ingredient: 'ingredient',
|
|
||||||
faune: 'faune',
|
|
||||||
livre: 'livre',
|
|
||||||
potion: 'potion',
|
|
||||||
service: 'service',
|
|
||||||
musique: 'musique',
|
|
||||||
danse: 'danse',
|
|
||||||
chant: 'chant',
|
|
||||||
jeu: 'jeu',
|
|
||||||
recettecuisine: 'recettecuisine',
|
|
||||||
oeuvre: 'oeuvre',
|
|
||||||
recettealchimique: 'recettealchimique',
|
|
||||||
tache: 'tache',
|
|
||||||
sort: 'sort',
|
|
||||||
sortreserve: 'sortreserve',
|
|
||||||
rencontre: 'rencontre',
|
|
||||||
queue: 'queue',
|
|
||||||
ombre: 'ombre',
|
|
||||||
souffle: 'souffle',
|
|
||||||
tete: 'tete',
|
|
||||||
casetmr: 'casetmr',
|
|
||||||
meditation: 'meditation',
|
|
||||||
signedraconique: 'signedraconique',
|
|
||||||
tarot: 'tarot',
|
|
||||||
nombreastral: 'nombreastral',
|
|
||||||
extraitpoetique: 'extraitpoetique',
|
|
||||||
}
|
|
||||||
|
|
||||||
const typesInventaireMateriel = [
|
|
||||||
TYPES.arme,
|
|
||||||
TYPES.armure,
|
|
||||||
TYPES.conteneur,
|
|
||||||
TYPES.faune,
|
|
||||||
TYPES.gemme,
|
|
||||||
TYPES.herbe,
|
|
||||||
TYPES.plante,
|
|
||||||
TYPES.ingredient,
|
|
||||||
TYPES.livre,
|
|
||||||
TYPES.monnaie,
|
|
||||||
TYPES.munition,
|
|
||||||
TYPES.nourritureboisson,
|
|
||||||
TYPES.objet,
|
|
||||||
TYPES.potion,
|
|
||||||
]
|
]
|
||||||
const typesInventaire = {
|
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"]
|
||||||
materiel: typesInventaireMateriel,
|
const typesObjetsDraconiques = ["queue", "ombre", "souffle", "tete", "signedraconique", "sortreserve", "rencontre"]
|
||||||
all: ['service'].concat(typesInventaireMateriel),
|
const typesObjetsConnaissance = ["meditation", "recettealchimique", "sort"]
|
||||||
}
|
const typesObjetsEffet = ["possession", "poison", "maladie"]
|
||||||
|
const typesObjetsCompetence = ["competence", "competencecreature"]
|
||||||
const typesObjetsOeuvres = [TYPES.oeuvre, TYPES.recettecuisine, TYPES.musique, TYPES.chant, TYPES.danse, TYPES.jeu]
|
|
||||||
const typesObjetsDraconiques = [TYPES.queue, TYPES.ombre, TYPES.souffle, TYPES.tete, TYPES.signedraconique, TYPES.sortreserve, TYPES.rencontre]
|
|
||||||
const typesObjetsConnaissance = [TYPES.meditation, TYPES.recettealchimique, TYPES.sort]
|
|
||||||
const typesObjetsEffet = [TYPES.possession, TYPES.poison, TYPES.maladie, TYPES.blessure]
|
|
||||||
const typesObjetsCompetence = [TYPES.competence, TYPES.competencecreature]
|
|
||||||
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/
|
||||||
@ -117,36 +57,34 @@ export const defaultItemImg = {
|
|||||||
poison: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp",
|
poison: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp",
|
||||||
oeuvre: "systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp",
|
oeuvre: "systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp",
|
||||||
nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
|
nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
|
||||||
service: "systems/foundryvtt-reve-de-dragon/icons/services/lit.webp",
|
|
||||||
signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp",
|
signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp",
|
||||||
gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp",
|
gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp",
|
||||||
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
||||||
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
|
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
|
||||||
extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp",
|
extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp",
|
||||||
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
|
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() {
|
static getDefaultImg(itemType) {
|
||||||
return undefined;
|
return defaultItemImg[itemType];
|
||||||
}
|
}
|
||||||
|
|
||||||
static getDefaultImg(itemType) {
|
static isItemInventaire(newLocal) {
|
||||||
return game.system.rdd.itemClasses[itemType]?.defaultIcon ?? defaultItemImg[itemType];
|
return typesObjetsInventaire.includes(newLocal.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isFieldInventaireModifiable(type, field) {
|
static isFieldInventaireModifiable(type, field) {
|
||||||
switch (field) {
|
switch (field) {
|
||||||
case 'quantite':
|
case 'quantite':
|
||||||
if ([TYPES.conteneur].includes(type)) {
|
if (['conteneur'].includes(type)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'cout':
|
case 'cout':
|
||||||
if ([TYPES.monnaie].includes(type)) {
|
if (['monnaie'].includes(type)) {
|
||||||
return game.user.isGM;
|
return game.user.isGM;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -154,123 +92,65 @@ export class RdDItem extends Item {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async getCorrespondingItem(itemRef) {
|
|
||||||
if (itemRef.pack) {
|
|
||||||
return await SystemCompendiums.loadDocument(itemRef)
|
|
||||||
}
|
|
||||||
return game.items.get(itemRef.id ?? itemRef._id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static getItemTypesInventaire(mode = 'materiel') {
|
|
||||||
return typesInventaire[mode ?? 'materiel']
|
|
||||||
}
|
|
||||||
static getItemTypesDraconiques() {
|
|
||||||
return typesObjetsDraconiques;
|
|
||||||
}
|
|
||||||
static getItemTypesEnvironnement() {
|
|
||||||
return typesEnvironnement;
|
|
||||||
}
|
|
||||||
|
|
||||||
static getTypesOeuvres() {
|
|
||||||
return typesObjetsOeuvres
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(docData, context = {}) {
|
|
||||||
if (!context.rdd?.ready) {
|
|
||||||
mergeObject(context, { rdd: { ready: true } });
|
|
||||||
const ItemConstructor = game.system.rdd.itemClasses[docData.type];
|
|
||||||
if (ItemConstructor) {
|
|
||||||
if (!docData.img) {
|
|
||||||
docData.img = ItemConstructor.defaultIcon;
|
|
||||||
}
|
|
||||||
return new ItemConstructor(docData, context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!docData.img) {
|
|
||||||
docData.img = RdDItem.getDefaultImg(docData.type);
|
|
||||||
}
|
|
||||||
super(docData, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
getUniteQuantite() {
|
getUniteQuantite() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case TYPES.monnaie: return "(Pièces)"
|
case "monnaie": return "(Pièces)"
|
||||||
case TYPES.herbe:
|
case "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 TYPES.ingredient: return "(Pépins ou Brins)"
|
case "ingredient": return "(Pépins ou Brins)"
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
isEquipable() {
|
constructor(itemData, context) {
|
||||||
return typesObjetsEquipable.includes(this.type)
|
if (!itemData.img) {
|
||||||
|
itemData.img = RdDItem.getDefaultImg(itemData.type);
|
||||||
|
}
|
||||||
|
super(itemData, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
isCompetencePersonnage() { return this.type == TYPES.competence }
|
static getItemTypesInventaire() {
|
||||||
isCompetenceCreature() { return this.type == TYPES.competencecreature }
|
return typesObjetsInventaire
|
||||||
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) }
|
|
||||||
isCompetencePossession() { return TYPES.competencecreature == this.type && this.system.categorie == "possession" }
|
|
||||||
isTemporel() { return typesObjetsTemporels.includes(this.type) }
|
|
||||||
isOeuvre() { return typesObjetsOeuvres.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) }
|
|
||||||
isConnaissance() { return typesObjetsConnaissance.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; }
|
|
||||||
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
|
|
||||||
}
|
|
||||||
getCategories() {
|
|
||||||
switch (this.type) {
|
|
||||||
case TYPES.competence: return RdDItemCompetence.getCategories()
|
|
||||||
case TYPES.competencecreature: return RdDItemCompetenceCreature.getCategories()
|
|
||||||
}
|
|
||||||
return {}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getEnvironnements(milieux = undefined) {
|
static getTypesOeuvres() {
|
||||||
const environnements = this.isInventaire() ? this.system.environnement : undefined;
|
return typesObjetsOeuvres
|
||||||
if (milieux == undefined || !environnements) {
|
|
||||||
return environnements ?? [];
|
|
||||||
}
|
|
||||||
return environnements.filter(env => milieux.includes(env.milieu))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getMilieux() {
|
isCompetencePersonnage() {
|
||||||
return this.getEnvironnements().map(env => env.milieu);
|
return this.type == 'competence'
|
||||||
}
|
}
|
||||||
|
isCompetenceCreature() {
|
||||||
getRaretes(milieux = undefined) {
|
return this.type == 'competencecreature'
|
||||||
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;
|
isCompetence() {
|
||||||
|
return typesObjetsCompetence.includes(this.type)
|
||||||
}
|
}
|
||||||
return [RdDRaretes.rareteEgale()];
|
isInventaire() {
|
||||||
|
return RdDItem.isItemInventaire(this)
|
||||||
}
|
}
|
||||||
|
isOeuvre() {
|
||||||
getFrequence(milieux = undefined) {
|
return typesObjetsOeuvres.includes(this.type)
|
||||||
const frequences = this.getEnvironnements(milieux).map(it => it.frequence);
|
}
|
||||||
return frequences.length == 0 ? 0 : Math.max(...frequences);
|
isDraconique() {
|
||||||
|
return typesObjetsDraconiques.includes(this.type)
|
||||||
|
}
|
||||||
|
isEffet() {
|
||||||
|
return typesObjetsEffet.includes(this.type)
|
||||||
|
}
|
||||||
|
isConnaissance() {
|
||||||
|
return typesObjetsConnaissance.includes(this.type)
|
||||||
|
}
|
||||||
|
isConteneur() {
|
||||||
|
return this.type == 'conteneur';
|
||||||
|
}
|
||||||
|
isMonnaie() {
|
||||||
|
return this.type == 'monnaie';
|
||||||
}
|
}
|
||||||
|
|
||||||
getItemGroup() {
|
getItemGroup() {
|
||||||
@ -283,113 +163,64 @@ export class RdDItem extends Item {
|
|||||||
return "autres";
|
return "autres";
|
||||||
}
|
}
|
||||||
|
|
||||||
isConteneurNonVide() { return this.isConteneur() && (this.system.contenu?.length ?? 0) > 0; }
|
isConteneurNonVide() {
|
||||||
isConteneurVide() { return this.isConteneur() && (this.system.contenu?.length ?? 0) == 0; }
|
return this.isConteneur() && (this.system.contenu?.length ?? 0) > 0;
|
||||||
isVideOuNonConteneur() { return !this.isConteneur() || (this.system.contenu?.length ?? 0) == 0; }
|
|
||||||
|
|
||||||
isFinPeriode(oldTimestamp, newTimestamp) {
|
|
||||||
if (!this.isTemporel()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const finPeriode = new RdDTimestamp(this.system.temporel.fin);
|
|
||||||
return oldTimestamp.compare(finPeriode) < 0 && finPeriode.compare(newTimestamp) <= 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onCreateItemTemporel(actor) {
|
isConteneurVide() {
|
||||||
if (this.isTemporel()) {
|
return this.isConteneur() && (this.system.contenu?.length ?? 0) == 0;
|
||||||
const timestampDebut = game.system.rdd.calendrier.timestamp;
|
|
||||||
const timestampFin = await this.calculerFinPeriodeTemporel(timestampDebut);
|
|
||||||
await actor.updateEmbeddedDocuments('Item', [{
|
|
||||||
_id: this.id,
|
|
||||||
'system.temporel.debut': duplicate(timestampDebut),
|
|
||||||
'system.temporel.fin': duplicate(timestampFin),
|
|
||||||
}])
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async calculerFinPeriodeTemporel(timestampDebut) {
|
isVideOuNonConteneur() {
|
||||||
return timestampDebut;
|
return !this.isConteneur() || (this.system.contenu?.length ?? 0) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
async onFinPeriodeTemporel(oldTimestamp, newTimestamp) {
|
isNourritureBoisson() {
|
||||||
if (this.isTemporel() && this.actor) {
|
return this.type == 'nourritureboisson';
|
||||||
await this.onFinPeriode(oldTimestamp, newTimestamp);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async onFinPeriode(oldTimestamp, newTimestamp) {
|
isComestible() {
|
||||||
console.log(`${this.actor.name}: l'objet ${this.name} a expiré et été supprimé`);
|
|
||||||
await this.actor?.deleteEmbeddedDocuments('Item', [this.id]);
|
|
||||||
}
|
|
||||||
|
|
||||||
getUtilisation() {
|
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case TYPES.potion:
|
case 'nourritureboisson': return 'pret';
|
||||||
switch (this.system.categorie) {
|
case 'herbe':
|
||||||
case 'Alchimie': case 'AlchimieEnchante': case 'AlchimieAutre': return 'alchimie'
|
return this.system.categorie == 'Cuisine' && this.system.sust > 0 ? 'brut' : '';
|
||||||
case 'Cuisine': return 'cuisine'
|
case 'faune':
|
||||||
case 'Remede': case 'Repos': case 'ReposEnchante': case 'Soin': case 'SoinEnchante': return 'soins'
|
return this.system.sust > 0 ? 'brut' : '';
|
||||||
}
|
|
||||||
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 '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
getUtilisationCuisine() {
|
isAlcool() {
|
||||||
if (this.getUtilisation() == 'cuisine') {
|
return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise;
|
||||||
switch (this.type) {
|
|
||||||
case TYPES.nourritureboisson:
|
|
||||||
return 'pret';
|
|
||||||
case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante:
|
|
||||||
return 'brut';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return '';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isHerbeAPotion() {
|
||||||
|
return this.type == 'herbe' && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos');
|
||||||
|
}
|
||||||
|
isPotion() {
|
||||||
|
return this.type == 'potion';
|
||||||
|
}
|
||||||
isCristalAlchimique() {
|
isCristalAlchimique() {
|
||||||
return this.type == TYPES.objet && Grammar.includesLowerCaseNoAccent(this.name, 'cristal alchimique') && this.system.quantite > 0;
|
return this.type == 'objet' && Grammar.toLowerCaseNoAccent(this.name) == 'cristal alchimique' && this.system.quantite > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
isMagique() {
|
isMagique() {
|
||||||
return this.system.magique
|
return this.system.magique
|
||||||
}
|
}
|
||||||
|
|
||||||
isItemCommerce() {
|
|
||||||
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 Math.round(this.isConteneur() ? 1 : (this.system.quantite ?? 0))
|
||||||
}
|
}
|
||||||
|
|
||||||
getEncTotal() {
|
getEncTotal() {
|
||||||
return (this.getQuantite() ?? 0) * this.getEnc();
|
return this.getEnc() * this.getQuantite();
|
||||||
}
|
}
|
||||||
|
|
||||||
getEnc() {
|
getEnc() {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case TYPES.service:
|
case 'herbe':
|
||||||
return 0;
|
|
||||||
case TYPES.herbe:
|
|
||||||
return this.getEncHerbe();
|
return this.getEncHerbe();
|
||||||
case TYPES.gemme:
|
case 'gemme':
|
||||||
return encPepin * this.system.taille;
|
return encPepin * this.system.taille;
|
||||||
}
|
}
|
||||||
return Math.max(this.system.encombrement ?? 0, 0);
|
return Math.max(this.system.encombrement ?? 0, 0);
|
||||||
@ -405,21 +236,13 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
valeurTotale() {
|
valeurTotale() {
|
||||||
return (this.isService() ? 1 : this.getQuantite()) * this.valeur()
|
return this.getQuantite() * this.valeur()
|
||||||
}
|
}
|
||||||
|
|
||||||
valeur() {
|
valeur() {
|
||||||
return this.system.cout ?? 0
|
return this.system.cout ?? 0
|
||||||
}
|
}
|
||||||
|
|
||||||
calculerPrixCommercant() {
|
|
||||||
if (this.isItemCommerce()) {
|
|
||||||
// appliquer le pourcentage
|
|
||||||
return this.parent.calculerPrix(this);
|
|
||||||
}
|
|
||||||
return this.system.cout;
|
|
||||||
}
|
|
||||||
|
|
||||||
prepareDerivedData() {
|
prepareDerivedData() {
|
||||||
super.prepareDerivedData();
|
super.prepareDerivedData();
|
||||||
if (this.isInventaire()) {
|
if (this.isInventaire()) {
|
||||||
@ -429,7 +252,6 @@ 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() {
|
||||||
@ -445,19 +267,19 @@ export class RdDItem extends Item {
|
|||||||
|
|
||||||
getActionPrincipale(options = { warnIfNot: true }) {
|
getActionPrincipale(options = { warnIfNot: true }) {
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case TYPES.conteneur: return 'Ouvrir';
|
case 'conteneur': return 'Ouvrir';
|
||||||
}
|
}
|
||||||
if (this.actor?.isPersonnage()) {
|
if (this.actor?.isPersonnage()) {
|
||||||
const warn = options.warnIfNot;
|
const warn = options.warnIfNot;
|
||||||
if (this.getUtilisationCuisine() == 'brut') {
|
if (this.isComestible() == 'brut') {
|
||||||
return 'Utiliser';
|
return 'Utiliser';
|
||||||
}
|
}
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
|
case 'nourritureboisson': return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
|
||||||
case TYPES.potion: return this._actionOrWarnQuantiteZero('Boire', warn);
|
case 'potion': return this._actionOrWarnQuantiteZero('Boire', warn);
|
||||||
case TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn);
|
case 'livre': return this._actionOrWarnQuantiteZero('Lire', warn);
|
||||||
case TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
|
case 'herbe': return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
|
||||||
case TYPES.queue: case TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined;
|
case 'queue': case 'ombre': return this.system.refoulement > 0 ? 'Refouler' : undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -472,11 +294,11 @@ export class RdDItem extends Item {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
switch (this.type) {
|
switch (this.type) {
|
||||||
case TYPES.potion: return await actor.consommerPotion(this, onActionItem);
|
case 'potion': return await actor.consommerPotion(this, onActionItem);
|
||||||
case TYPES.livre: return await actor.actionLire(this);
|
case 'livre': return await actor.actionLire(this);
|
||||||
case TYPES.conteneur: return await this.sheet.render(true);
|
case 'conteneur': return await this.sheet.render(true);
|
||||||
case TYPES.herbe: return await actor.actionHerbe(this, onActionItem);
|
case 'herbe': return await actor.actionHerbe(this);
|
||||||
case TYPES.queue: case TYPES.ombre: return await actor.actionRefoulement(this);
|
case 'queue': case 'ombre': return await actor.actionRefoulement(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -498,7 +320,7 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async onCreateDecoupeComestible(actor) {
|
async onCreateDecoupeComestible(actor) {
|
||||||
if (actor && this.getUtilisationCuisine() == 'brut' && this.system.sust != 1) {
|
if (actor && this.isComestible() == '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,
|
||||||
@ -519,7 +341,7 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async empiler(item) {
|
async empiler(item) {
|
||||||
if (this.getUtilisationCuisine() == 'brut') {
|
if (this.isComestible() == '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({
|
||||||
@ -533,7 +355,7 @@ export class RdDItem extends Item {
|
|||||||
await item.delete();
|
await item.delete();
|
||||||
}
|
}
|
||||||
|
|
||||||
async quantiteIncDec(nombre, options = { supprimerSiZero: false }) {
|
async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
|
||||||
const quantite = Number(this.system.quantite ?? -1);
|
const quantite = Number(this.system.quantite ?? -1);
|
||||||
if (quantite >= 0) {
|
if (quantite >= 0) {
|
||||||
const reste = Math.max(quantite + Number(nombre), 0);
|
const reste = Math.max(quantite + Number(nombre), 0);
|
||||||
@ -570,8 +392,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', 'contenu'];
|
const excludedProperties = ['quantite', 'cout', 'encTotal'];
|
||||||
if (this.getUtilisationCuisine()) {
|
if (this.isComestible()) {
|
||||||
excludedProperties.push('sust', 'encombrement');
|
excludedProperties.push('sust', 'encombrement');
|
||||||
}
|
}
|
||||||
let differences = Object.entries(this.system)
|
let differences = Object.entries(this.system)
|
||||||
@ -588,16 +410,13 @@ export class RdDItem extends Item {
|
|||||||
return [true, undefined];
|
return [true, undefined];
|
||||||
}
|
}
|
||||||
|
|
||||||
async proposerVente(quantiteMax = undefined) {
|
async proposerVente() {
|
||||||
console.log(this);
|
console.log(this);
|
||||||
if (this.isConteneurNonVide()) {
|
if (this.isConteneurNonVide()) {
|
||||||
ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`);
|
ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
await DialogItemVente.display({
|
await DialogItemVente.display(this, async (vente) => {
|
||||||
item: this,
|
|
||||||
quantiteMax,
|
|
||||||
callback: async (vente) => {
|
|
||||||
vente["properties"] = this.getProprietes();
|
vente["properties"] = this.getProprietes();
|
||||||
if (vente.isOwned) {
|
if (vente.isOwned) {
|
||||||
if (vente.quantiteNbLots * vente.tailleLot > vente.quantiteMax) {
|
if (vente.quantiteNbLots * vente.tailleLot > vente.quantiteMax) {
|
||||||
@ -607,44 +426,38 @@ export class RdDItem extends Item {
|
|||||||
}
|
}
|
||||||
vente.jsondata = JSON.stringify(vente.item);
|
vente.jsondata = JSON.stringify(vente.item);
|
||||||
|
|
||||||
|
console.log(vente);
|
||||||
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
|
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
|
||||||
ChatMessage.create(RdDUtility.chatDataSetup(html));
|
ChatMessage.create(RdDUtility.chatDataSetup(html));
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
getProprietes() {
|
getProprietes() {
|
||||||
if (this[`_${this.type}ChatData`]) {
|
|
||||||
return this[`_${this.type}ChatData`]().filter(it => it != undefined);
|
return this[`_${this.type}ChatData`]().filter(it => it != undefined);
|
||||||
}
|
}
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async postItemToChat(modeOverride) {
|
async postItem(modeOverride) {
|
||||||
console.log(this);
|
console.log(this);
|
||||||
let chatData = {
|
let chatData = duplicate(this);
|
||||||
doctype: 'Item',
|
chatData["properties"] = this.getProprietes();
|
||||||
id: this.id,
|
if (this.actor) {
|
||||||
type: this.type,
|
chatData.actor = { id: this.actor.id };
|
||||||
img: this.img,
|
|
||||||
pack: this.pack,
|
|
||||||
name: this.name,
|
|
||||||
actor: this.actor ? { id: this.actor.id } : undefined,
|
|
||||||
system: { description: this.system.description },
|
|
||||||
properties: this.getProprietes(),
|
|
||||||
}
|
}
|
||||||
renderTemplate(this.getChatItemTemplate(), chatData).then(html => {
|
// JSON object for easy creation
|
||||||
|
chatData.jsondata = JSON.stringify(
|
||||||
|
{
|
||||||
|
compendium: "postedItem",
|
||||||
|
payload: chatData,
|
||||||
|
});
|
||||||
|
|
||||||
|
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-item.html', chatData).then(html => {
|
||||||
let chatOptions = RdDUtility.chatDataSetup(html, modeOverride);
|
let chatOptions = RdDUtility.chatDataSetup(html, modeOverride);
|
||||||
ChatMessage.create(chatOptions)
|
ChatMessage.create(chatOptions)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getChatItemTemplate() {
|
|
||||||
return 'systems/foundryvtt-reve-de-dragon/templates/post-item.html';
|
|
||||||
}
|
|
||||||
|
|
||||||
static propertyIfDefined(name, val, condition = true) {
|
static propertyIfDefined(name, val, condition = true) {
|
||||||
return condition ? `<b>${name}</b>: ${val}` : undefined;
|
return condition ? `<b>${name}</b>: ${val}` : undefined;
|
||||||
}
|
}
|
||||||
@ -893,4 +706,5 @@ export class RdDItem extends Item {
|
|||||||
...this._inventaireTemplateChatData()
|
...this._inventaireTemplateChatData()
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,51 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,199 +0,0 @@
|
|||||||
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,47 +0,0 @@
|
|||||||
import { RdDItem } from "../item.js";
|
|
||||||
import { Misc } from "../misc.js";
|
|
||||||
import { RdDTimestamp } from "../time/rdd-timestamp.js";
|
|
||||||
|
|
||||||
export class RdDItemMaladie extends RdDItem {
|
|
||||||
|
|
||||||
static get defaultIcon() {
|
|
||||||
return "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/maladie.webp";
|
|
||||||
}
|
|
||||||
|
|
||||||
async calculerFinPeriodeTemporel(debut) {
|
|
||||||
return await debut.addPeriode(this.system.periode.nombre, this.system.periode.unite);
|
|
||||||
}
|
|
||||||
|
|
||||||
async onFinPeriode(oldTimestamp, newTimestamp) {
|
|
||||||
await RdDItemMaladie.notifierMaladiePoison(this, oldTimestamp, newTimestamp)
|
|
||||||
}
|
|
||||||
|
|
||||||
static async notifierMaladiePoison(mal, oldTimestamp, newTimestamp) {
|
|
||||||
if (mal.actor) {
|
|
||||||
const souffrance = mal.system.identifie
|
|
||||||
? `de ${mal.name}`
|
|
||||||
: `d'un mal inconnu`
|
|
||||||
ChatMessage.create({ content: `${mal.actor.name} souffre ${souffrance} (${Misc.typeName('Item', mal.type)}): vérifiez que les effets ne se sont pas aggravés !` });
|
|
||||||
mal.postItemToChat('gmroll');
|
|
||||||
await RdDItemMaladie.prolongerPeriode(mal,oldTimestamp, newTimestamp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static async prolongerPeriode(mal, oldTimestamp, newTimestamp) {
|
|
||||||
if (mal.actor) {
|
|
||||||
// TODO: déterminer le nombre de périodes écoulées
|
|
||||||
console.log(`${mal.actor.name}: le mal ${mal.name} a atteint la fin de sa période et été prolongé`);
|
|
||||||
const current = newTimestamp;
|
|
||||||
const finPeriode = new RdDTimestamp(mal.system.temporel.fin)
|
|
||||||
const periodeSuivante = (finPeriode.compare(current) > 0 ? finPeriode : current);
|
|
||||||
const timestampFin = await mal.calculerFinPeriodeTemporel(periodeSuivante);
|
|
||||||
|
|
||||||
await mal.actor.updateEmbeddedDocuments('Item', [{
|
|
||||||
_id: mal.id,
|
|
||||||
'system.temporel.fin': duplicate(timestampFin),
|
|
||||||
}])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
@ -1,11 +0,0 @@
|
|||||||
import { RdDItem } from "../item.js";
|
|
||||||
|
|
||||||
export class RdDItemOmbre extends RdDItem {
|
|
||||||
static get defaultIcon() {
|
|
||||||
return "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp";
|
|
||||||
}
|
|
||||||
|
|
||||||
async calculerFinPeriodeTemporel(debut) {
|
|
||||||
return await debut.appliquerDuree(this.system.duree, this.parent);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
import { RdDItem } from "../item.js";
|
|
||||||
import { RdDItemMaladie } from "./maladie.js";
|
|
||||||
|
|
||||||
export class RdDItemPoison extends RdDItem {
|
|
||||||
|
|
||||||
static get defaultIcon() {
|
|
||||||
return "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp";
|
|
||||||
}
|
|
||||||
|
|
||||||
async calculerFinPeriodeTemporel(debut) {
|
|
||||||
return await debut.addPeriode(this.system.periode.nombre, this.system.periode.unite) ;
|
|
||||||
}
|
|
||||||
|
|
||||||
async onFinPeriode(oldTimestamp, newTimestamp) {
|
|
||||||
RdDItemMaladie.notifierMaladiePoison(this, oldTimestamp, newTimestamp)
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import { RdDItem } from "../item.js";
|
|
||||||
|
|
||||||
export class RdDItemQueue extends RdDItem {
|
|
||||||
|
|
||||||
static get defaultIcon() {
|
|
||||||
return "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp";
|
|
||||||
}
|
|
||||||
|
|
||||||
async calculerFinPeriodeTemporel(debut) {
|
|
||||||
return await debut.appliquerDuree(this.system.duree, this.parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
|
|
||||||
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,17 +0,0 @@
|
|||||||
import { RdDItem } from "../item.js";
|
|
||||||
|
|
||||||
export class RdDItemService extends RdDItem {
|
|
||||||
|
|
||||||
static get defaultIcon() {
|
|
||||||
return "systems/foundryvtt-reve-de-dragon/icons/services/lit.webp";
|
|
||||||
}
|
|
||||||
|
|
||||||
isService() { return true; }
|
|
||||||
getProprietes() {
|
|
||||||
return [
|
|
||||||
RdDItem.propertyIfDefined('Qualité', this.system.qualite, this.system.qualite != 0),
|
|
||||||
RdDItem.propertyIfDefined('Moral', 'Situation heureuse', this.system.moral),
|
|
||||||
RdDItem.propertyIfDefined('Coût', `${this.calculerPrixCommercant()} sols`),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,120 +0,0 @@
|
|||||||
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");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
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,38 +0,0 @@
|
|||||||
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': ''
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,6 +0,0 @@
|
|||||||
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
|
||||||
|
|
||||||
export class RdDHerbeItemSheet extends RdDItemInventaireSheet {
|
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "herbe" };
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
|
||||||
|
|
||||||
export class RdDIngredientItemSheet extends RdDItemInventaireSheet {
|
|
||||||
static get ITEM_TYPE() { return "ingredient" };
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
|
|
||||||
|
|
||||||
export class RdDPlanteItemSheet extends RdDItemInventaireSheet {
|
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "plante" };
|
|
||||||
|
|
||||||
}
|
|
@ -1,16 +0,0 @@
|
|||||||
import { RdDItemSheet } from "../item-sheet.js";
|
|
||||||
|
|
||||||
export class RdDServiceItemSheet extends RdDItemSheet {
|
|
||||||
|
|
||||||
static get ITEM_TYPE() { return "service" };
|
|
||||||
|
|
||||||
async getData() {
|
|
||||||
const formData = await super.getData();
|
|
||||||
formData.disabled = formData.options.isGM || formData.options.isOwned ? '' : 'disabled';
|
|
||||||
return formData;
|
|
||||||
}
|
|
||||||
|
|
||||||
activateListeners(html) {
|
|
||||||
super.activateListeners(html);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
import { RdDItem } from "../item.js";
|
|
||||||
|
|
||||||
export class RdDItemSouffle extends RdDItem {
|
|
||||||
|
|
||||||
static get defaultIcon() {
|
|
||||||
return "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp";
|
|
||||||
}
|
|
||||||
|
|
||||||
async calculerFinPeriodeTemporel(debut) {
|
|
||||||
return await debut.appliquerDuree(this.system.duree, this.parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,10 +1,6 @@
|
|||||||
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 { RdDItem, TYPES } from "./item.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"; }
|
||||||
@ -13,7 +9,7 @@ class Migration {
|
|||||||
|
|
||||||
async applyItemsUpdates(computeUpdates) {
|
async applyItemsUpdates(computeUpdates) {
|
||||||
await game.actors.forEach(async (actor) => {
|
await game.actors.forEach(async (actor) => {
|
||||||
const actorItemUpdates = computeUpdates(actor.items).filter(it => it != undefined);
|
const actorItemUpdates = computeUpdates(actor.items);
|
||||||
if (actorItemUpdates.length > 0) {
|
if (actorItemUpdates.length > 0) {
|
||||||
console.log(
|
console.log(
|
||||||
this.code,
|
this.code,
|
||||||
@ -24,7 +20,7 @@ class Migration {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const itemUpdates = computeUpdates(game.items).filter(it => it != undefined);
|
const itemUpdates = computeUpdates(game.items);
|
||||||
if (itemUpdates.length > 0) {
|
if (itemUpdates.length > 0) {
|
||||||
console.log(this.code, "Applying updates on items", itemUpdates);
|
console.log(this.code, "Applying updates on items", itemUpdates);
|
||||||
await Item.updateDocuments(itemUpdates);
|
await Item.updateDocuments(itemUpdates);
|
||||||
@ -33,38 +29,6 @@ class Migration {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class _1_5_34_migrationPngWebp {
|
|
||||||
get code() { return "migrationPngWebp"; }
|
|
||||||
get version() { return "1.5.34"; }
|
|
||||||
async migrate() {
|
|
||||||
|
|
||||||
const regexOldPngJpg = /(systems\/foundryvtt-reve-de-dragon\/icons\/.*)\.(png|jpg)/;
|
|
||||||
const replaceWithWebp = '$1.webp';
|
|
||||||
function convertImgToWebp(img) {
|
|
||||||
return img.replace(regexOldPngJpg, replaceWithWebp);
|
|
||||||
}
|
|
||||||
function prepareDocumentsImgUpdate(documents) {
|
|
||||||
return documents.filter(it => it.img && it.img.match(regexOldPngJpg))
|
|
||||||
.map(it => {
|
|
||||||
return { _id: it.id, img: convertImgToWebp(it.img) }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
const itemsUpdates = prepareDocumentsImgUpdate(game.items);
|
|
||||||
const actorsUpdates = prepareDocumentsImgUpdate(game.actors);
|
|
||||||
//Migrate system png to webp
|
|
||||||
await Item.updateDocuments(itemsUpdates);
|
|
||||||
await Actor.updateDocuments(actorsUpdates);
|
|
||||||
game.actors.forEach(actor => {
|
|
||||||
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
|
|
||||||
actor.update({ "token.img": convertImgToWebp(actor.token.img) });
|
|
||||||
}
|
|
||||||
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
|
|
||||||
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _10_0_16_MigrationSortsReserve extends Migration {
|
class _10_0_16_MigrationSortsReserve extends Migration {
|
||||||
get code() { return "creation-item-sort-reserve"; }
|
get code() { return "creation-item-sort-reserve"; }
|
||||||
get version() { return "10.0.16"; }
|
get version() { return "10.0.16"; }
|
||||||
@ -287,11 +251,10 @@ 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: rarete.code, frequence: rarete.frequence }]
|
'system.environnement': [{ milieu: it.system.milieu, rarete: it.system.rarete, frequence: Environnement.getFrequenceRarete(it.system.rarete, 'frequence') }]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -329,195 +292,10 @@ class _10_3_17_Monnaies extends Migration {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _10_4_6_ServicesEnCommerces extends Migration {
|
|
||||||
|
|
||||||
get code() { return "migration-service-acteurs"; }
|
|
||||||
get version() { return "10.4.6"; }
|
|
||||||
|
|
||||||
async migrate() {
|
|
||||||
const servicesToMigrate = game.items.filter(it => it.type == 'service');
|
|
||||||
servicesToMigrate.forEach(async service => {
|
|
||||||
const commerce = await this.convertServiceToCommerce(service);
|
|
||||||
await RdDBaseActor.create(commerce, { renderSheet: false });
|
|
||||||
await service.delete();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async convertServiceToCommerce(service) {
|
|
||||||
return {
|
|
||||||
name: service.name, img: service.img, type: 'commerce',
|
|
||||||
system: {
|
|
||||||
description: service.system.description,
|
|
||||||
notesmj: service.system.descriptionmj,
|
|
||||||
illimite: service.system.illimite
|
|
||||||
},
|
|
||||||
items: await this.transformInventaireCommerce(service)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
async transformInventaireCommerce(service) {
|
|
||||||
const serviceItems = (service.system.items ?? []);
|
|
||||||
const commerceItems = await Promise.all(serviceItems.map(async (it) => { return await this.transformToItemBoutique(it); }));
|
|
||||||
return commerceItems.concat(Monnaie.monnaiesStandard());
|
|
||||||
}
|
|
||||||
|
|
||||||
async transformToItemBoutique(serviceRefItem) {
|
|
||||||
const item = await RdDItem.getCorrespondingItem(serviceRefItem);
|
|
||||||
const itemToCreate = {
|
|
||||||
name: item.name, img: item.img, type: item.type,
|
|
||||||
system: mergeObject({ cout: serviceRefItem.system.cout, quantite: serviceRefItem.system.quantite }, item.system, { overwrite: false })
|
|
||||||
};
|
|
||||||
return itemToCreate;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _10_5_0_UpdatePeriodicite extends Migration {
|
|
||||||
get code() { return "migration-periodicite-poisons-maladies"; }
|
|
||||||
get version() { return "10.5.0"; }
|
|
||||||
|
|
||||||
async migrate() {
|
|
||||||
await this.applyItemsUpdates(items => this._updatePeriodicite(items));
|
|
||||||
}
|
|
||||||
|
|
||||||
_updatePeriodicite(items) {
|
|
||||||
return items.filter(it => ['poison', 'maladie'].includes(it.type))
|
|
||||||
.filter(it => it.system.periodicite != "")
|
|
||||||
.map(it => {
|
|
||||||
let [incubation, periodicite] = this.getPeriodicite(it);
|
|
||||||
const periode = periodicite.split(' ');
|
|
||||||
let unite = periode.length == 2
|
|
||||||
? RdDTimestamp.formulesPeriode().find(it => Grammar.includesLowerCaseNoAccent(periode[1], it.code))?.code
|
|
||||||
: undefined
|
|
||||||
if (unite && Number(periode[0])) {
|
|
||||||
return {
|
|
||||||
_id: it.id,
|
|
||||||
'system.periodicite': undefined,
|
|
||||||
'system.incubation': incubation,
|
|
||||||
'system.periode.nombre': Number.parseInt(periode[0]),
|
|
||||||
'system.periode.unite': unite
|
|
||||||
};
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return {
|
|
||||||
_id: it.id,
|
|
||||||
'system.periodicite': undefined,
|
|
||||||
'system.incubation': it.system.periodicite
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}).filter(it => it != undefined);
|
|
||||||
}
|
|
||||||
|
|
||||||
getPeriodicite(it) {
|
|
||||||
let p = it.system.periodicite.split(/[\/\\]/);
|
|
||||||
switch (p.length) {
|
|
||||||
case 2: return [p[0].trim(), p[1].trim()];
|
|
||||||
case 1: return ["", it.system.periodicite.trim()];
|
|
||||||
default: return [it.system.periodicite.trim(), ""];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _10_7_19_CategorieCompetenceCreature extends Migration {
|
|
||||||
get code() { return "categorie-competence-creature"; }
|
|
||||||
get version() { return "10.7.19"; }
|
|
||||||
|
|
||||||
async migrate() {
|
|
||||||
await this.applyItemsUpdates(items => items
|
|
||||||
.filter(it => TYPES.competencecreature == it.type)
|
|
||||||
.map(it => this.migrateCompetenceCreature(it))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
migrateCompetenceCreature(it) {
|
|
||||||
const categorie = this.getCategorie(it)
|
|
||||||
if (categorie == it.system.categorie) {
|
|
||||||
return undefined
|
|
||||||
}
|
|
||||||
return { _id: it.id, 'system.categorie': categorie }
|
|
||||||
}
|
|
||||||
|
|
||||||
getCategorie(it) {
|
|
||||||
if (it.system.ispossession) {
|
|
||||||
return 'possession'
|
|
||||||
}
|
|
||||||
switch (it.system.categorie) {
|
|
||||||
case "melee":
|
|
||||||
if (it.system.isnaturelle) {
|
|
||||||
return 'naturelle'
|
|
||||||
}
|
|
||||||
return 'melee'
|
|
||||||
case "particuliere": case "specialisee": case "connaissance":
|
|
||||||
return "generale"
|
|
||||||
default:
|
|
||||||
return it.system.categorie
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _10_7_19_PossessionsEntiteVictime extends Migration {
|
|
||||||
get code() { return "possessions-entite-victime"; }
|
|
||||||
get version() { return "10.7.19"; }
|
|
||||||
|
|
||||||
async migrate() {
|
|
||||||
await this.applyItemsUpdates(items => items
|
|
||||||
.filter(it => TYPES.possession == it.type)
|
|
||||||
.map(it => this.migratePossession(it))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
migratePossession(it) {
|
|
||||||
return { _id: it.id,
|
|
||||||
'system.entite.actorid': it.system.possesseurid,
|
|
||||||
'system.victime.actorid': it.system.possedeid
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class Migrations {
|
export class Migrations {
|
||||||
static getMigrations() {
|
static getMigrations() {
|
||||||
return [
|
return [
|
||||||
new _1_5_34_migrationPngWebp(),
|
|
||||||
new _10_0_16_MigrationSortsReserve(),
|
new _10_0_16_MigrationSortsReserve(),
|
||||||
new _10_0_17_MigrationCompetenceCreature(),
|
new _10_0_17_MigrationCompetenceCreature(),
|
||||||
new _10_0_21_VehiculeStructureResistanceMax(),
|
new _10_0_21_VehiculeStructureResistanceMax(),
|
||||||
@ -526,12 +304,7 @@ export class Migrations {
|
|||||||
new _10_2_10_DesirLancinant_IdeeFixe(),
|
new _10_2_10_DesirLancinant_IdeeFixe(),
|
||||||
new _10_3_0_Inventaire(),
|
new _10_3_0_Inventaire(),
|
||||||
new _10_3_0_FrequenceEnvironnement(),
|
new _10_3_0_FrequenceEnvironnement(),
|
||||||
new _10_3_17_Monnaies(),
|
new _10_3_17_Monnaies()
|
||||||
new _10_4_6_ServicesEnCommerces(),
|
|
||||||
new _10_5_0_UpdatePeriodicite(),
|
|
||||||
new _10_7_0_MigrationBlessures(),
|
|
||||||
new _10_7_19_CategorieCompetenceCreature(),
|
|
||||||
new _10_7_19_PossessionsEntiteVictime(),
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -548,10 +321,16 @@ export class Migrations {
|
|||||||
migrate() {
|
migrate() {
|
||||||
const currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion");
|
const currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion");
|
||||||
if (isNewerVersion(game.system.version, currentVersion)) {
|
if (isNewerVersion(game.system.version, currentVersion)) {
|
||||||
// if (true) { /* comment previous and uncomment here to test before upgrade */
|
//if (true) { /* comment previous and uncomment here to test before upgrade */
|
||||||
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
|
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion));
|
||||||
if (migrations.length > 0) {
|
if (migrations.length > 0) {
|
||||||
migrations.sort((a, b) => this.compareVersions(a, b));
|
migrations.sort((a, b) =>
|
||||||
|
isNewerVersion(a.version, b.version)
|
||||||
|
? 1
|
||||||
|
: isNewerVersion(b.version, a.version)
|
||||||
|
? -1
|
||||||
|
: 0
|
||||||
|
);
|
||||||
migrations.forEach(async (m) => {
|
migrations.forEach(async (m) => {
|
||||||
ui.notifications.info(
|
ui.notifications.info(
|
||||||
`Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}`
|
`Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}`
|
||||||
@ -577,8 +356,4 @@ export class Migrations {
|
|||||||
console.log(LOG_HEAD + `No system version changed`);
|
console.log(LOG_HEAD + `No system version changed`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
compareVersions(a, b) {
|
|
||||||
return isNewerVersion(a.version, b.version) ? 1 : isNewerVersion(b.version, a.version) ? -1 : 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -46,9 +46,6 @@ export class Misc {
|
|||||||
: '';
|
: '';
|
||||||
}
|
}
|
||||||
|
|
||||||
static arrayOrEmpty(items) {
|
|
||||||
return items?.length ? items : [];
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* Converts the value to an integer, or to 0 if undefined/null/not representing integer
|
* Converts the value to an integer, or to 0 if undefined/null/not representing integer
|
||||||
* @param {*} value value to convert to an integer using parseInt
|
* @param {*} value value to convert to an integer using parseInt
|
||||||
@ -85,7 +82,6 @@ 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), []);
|
||||||
}
|
}
|
||||||
@ -119,17 +115,6 @@ 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)];
|
||||||
}
|
}
|
||||||
@ -165,11 +150,11 @@ export class Misc {
|
|||||||
return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
|
return game.users.filter(u => u.isGM && u.active).sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active);
|
||||||
}
|
}
|
||||||
|
|
||||||
static isOwnerPlayer(actor, user = undefined) {
|
static isOwnerPlayer(actor, user=undefined) {
|
||||||
return actor.testUserPermission(user ?? game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER)
|
return actor.testUserPermission(user ?? game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER)
|
||||||
}
|
}
|
||||||
|
|
||||||
static isOwnerPlayerOrUniqueConnectedGM(actor, user = undefined) {
|
static isOwnerPlayerOrUniqueConnectedGM(actor, user =undefined){
|
||||||
return Misc.isOwnerPlayer(actor, user) ?? Misc.isUniqueConnectedGM();
|
return Misc.isOwnerPlayer(actor, user) ?? Misc.isUniqueConnectedGM();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,15 +224,4 @@ 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,11 +8,13 @@ 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);
|
||||||
@ -25,19 +27,20 @@ export class RdDAlchimie {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _alchimieCouleur(recette, couleurs, actorId) {
|
static _alchimieCouleur(recette, couleurs, actorId) {
|
||||||
return RdDAlchimie._alchimieLink(recette, couleurs, actorId, 'couleur', 'Température');
|
if (actorId) {
|
||||||
|
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) {
|
||||||
return RdDAlchimie._alchimieLink(recette, consistances, actorId, 'consistance', 'Consistance');
|
if (actorId) {
|
||||||
|
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>`;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
48
module/rdd-astrologie-editeur.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
/**
|
||||||
|
* 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: 300, '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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
104
module/rdd-astrologie-joueur.js
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
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, dialogConfig) {
|
||||||
|
|
||||||
|
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);
|
||||||
|
let options = { classes: ["rdd-roll-dialog"], width: 600, height: 500, 'z-index': 99999 };
|
||||||
|
if (dialogConfig.options) {
|
||||||
|
mergeObject(options, dialogConfig.options, { overwrite: true });
|
||||||
|
}
|
||||||
|
return new RdDAstrologieJoueur(html, actor, dialogData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
constructor(html, actor, dialogData) {
|
||||||
|
const dialogConf = {
|
||||||
|
title: "Nombres Astraux",
|
||||||
|
content: html,
|
||||||
|
default: "saveButton",
|
||||||
|
buttons: {
|
||||||
|
saveButton: { label: "Fermer", callback: html => this.quitDialog() }
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const dialogOptions = { classes: ["rdd-roll-dialog"], width: 600, height: 300, 'z-index': 99999 };
|
||||||
|
super(dialogConf, dialogOptions);
|
||||||
|
|
||||||
|
this.actor = actor;
|
||||||
|
this.dataNombreAstral = duplicate(dialogData);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
this.html = html;
|
||||||
|
|
||||||
|
this.html.find(function () {
|
||||||
|
this.html.find("[name='diffConditions']").val(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.html.find('[name="jet-astrologie"]').click((event) => {
|
||||||
|
this.requestJetAstrologie();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static organizeNombres(actor) {
|
||||||
|
let itemNombres = actor.listItemsData('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() {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,4 @@
|
|||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
import { RdDPossession } from "./rdd-possession.js";
|
|
||||||
|
|
||||||
const conditionsTactiques = [
|
const conditionsTactiques = [
|
||||||
{ type: '', descr: '', dmg: 0, attaque: 0, parade: 0, esquive: true },
|
{ type: '', descr: '', dmg: 0, attaque: 0, parade: 0, esquive: true },
|
||||||
@ -25,17 +24,11 @@ export class RdDBonus {
|
|||||||
}
|
}
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static isDefenseAttaqueFinesse(rollData) {
|
static isDefenseAttaqueFinesse(rollData) {
|
||||||
if (rollData.isEmpoignade && rollData.rolled?.isPart) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if (RdDPossession.isDefensePossession(rollData)) {
|
|
||||||
return RdDPossession.isPossessionFinesse(rollData)
|
|
||||||
}
|
|
||||||
return rollData.attackerRoll?.particuliere == 'finesse';
|
return rollData.attackerRoll?.particuliere == 'finesse';
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static dmg(rollData, dmgActor, isEntiteIncarnee = false) {
|
static dmg(rollData, dmgActor, isCauchemar = 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
|
||||||
@ -48,7 +41,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, isEntiteIncarnee)
|
dmg.mortalite = RdDBonus._calculMortalite(rollData, isCauchemar)
|
||||||
}
|
}
|
||||||
return dmg;
|
return dmg;
|
||||||
}
|
}
|
||||||
@ -69,8 +62,11 @@ export class RdDBonus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _calculMortalite(rollData, isEntiteIncarnee) {
|
static _calculMortalite(rollData, isCauchemar) {
|
||||||
return isEntiteIncarnee ? "entiteincarnee"
|
if (isCauchemar) {
|
||||||
|
return "cauchemar";
|
||||||
|
}
|
||||||
|
return isCauchemar ? "cauchemar"
|
||||||
: rollData.dmg?.mortalite
|
: rollData.dmg?.mortalite
|
||||||
?? rollData.arme?.system.mortalite
|
?? rollData.arme?.system.mortalite
|
||||||
?? "mortel";
|
?? "mortel";
|
||||||
@ -78,7 +74,7 @@ export class RdDBonus {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static _dmgArme(rollData) {
|
static _dmgArme(rollData) {
|
||||||
if (rollData.arme) {
|
if ( rollData.arme) {
|
||||||
let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0);
|
let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0);
|
||||||
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
|
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
|
||||||
return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0);
|
return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0);
|
||||||
|
52
module/rdd-calendrier-editeur.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { Misc } from "./misc.js";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extend the base Dialog entity by defining a custom window to perform roll.
|
||||||
|
* @extends {Dialog}
|
||||||
|
*/
|
||||||
|
export class RdDCalendrierEditeur extends Dialog {
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
constructor(html, calendrier, calendrierData) {
|
||||||
|
let dialogConf = {
|
||||||
|
content: html,
|
||||||
|
title: "Editeur de date/heure",
|
||||||
|
buttons: {
|
||||||
|
save: { label: "Enregistrer", callback: html => this.fillData() }
|
||||||
|
},
|
||||||
|
default: "save"
|
||||||
|
};
|
||||||
|
let dialogOptions = { classes: ["rdd-dialog-calendar-editor"], width: 400, height: 'fit-content', 'z-index': 99999 }
|
||||||
|
super(dialogConf, dialogOptions)
|
||||||
|
|
||||||
|
this.calendrier = calendrier;
|
||||||
|
this.calendrierData = calendrierData;
|
||||||
|
}
|
||||||
|
|
||||||
|
activateListeners(html) {
|
||||||
|
super.activateListeners(html);
|
||||||
|
this.html = html;
|
||||||
|
this.html.find("input[name='nomMois']").val(this.calendrierData.moisKey);
|
||||||
|
this.html.find("select[name='nomHeure']").val(this.calendrierData.heureKey);
|
||||||
|
this.html.find("select[name='jourMois']").val(this.calendrierData.jourMois);
|
||||||
|
this.html.find("select[name='minutesRelative']").val(calendrierData.minutesRelative);
|
||||||
|
this.html.find("select[name='annee']").val(this.calendrierData.annee);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
fillData() {
|
||||||
|
this.calendrierData.annee = this.html.find("input[name='annee']").val();
|
||||||
|
this.calendrierData.moisKey = this.html.find("select[name='nomMois']").val();
|
||||||
|
this.calendrierData.heureKey = this.html.find("select[name='nomHeure']").val();
|
||||||
|
this.calendrierData.jourMois = this.html.find("select[name='jourMois']").val();
|
||||||
|
this.calendrierData.minutesRelative = this.html.find("select[name='minutesRelative']").val();
|
||||||
|
|
||||||
|
this.calendrier.saveEditeur(this.calendrierData)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
updateData(calendrierData) {
|
||||||
|
this.calendrierData = duplicate(calendrierData);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
649
module/rdd-calendrier.js
Normal file
@ -0,0 +1,649 @@
|
|||||||
|
/* -------------------------------------------- */
|
||||||
|
import { RdDCalendrierEditeur } from "./rdd-calendrier-editeur.js";
|
||||||
|
import { RdDAstrologieEditeur } from "./rdd-astrologie-editeur.js";
|
||||||
|
import { HtmlUtility } from "./html-utility.js";
|
||||||
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
import { Grammar } from "./grammar.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";
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
const dossierIconesHeures = 'systems/foundryvtt-reve-de-dragon/icons/heures/'
|
||||||
|
const heuresList = ["vaisseau", "sirene", "faucon", "couronne", "dragon", "epees", "lyre", "serpent", "poissonacrobate", "araignee", "roseau", "chateaudormant"];
|
||||||
|
const heuresDef = {
|
||||||
|
"vaisseau": {key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "printemps", heure: 0, icon: 'hd01.svg' },
|
||||||
|
"sirene": { key: "sirene", label: "Sirène", lettreFont: 'i', saison: "printemps", heure: 1, icon: 'hd02.svg' },
|
||||||
|
"faucon": { key: "faucon", label: "Faucon", lettreFont: 'f', saison: "printemps", heure: 2, icon: 'hd03.svg' },
|
||||||
|
"couronne": { key: "couronne", label: "Couronne", lettreFont: '', saison: "ete", heure: 3, icon: 'hd04.svg' },
|
||||||
|
"dragon": { key: "dragon", label: "Dragon", lettreFont: 'd', saison: "ete", heure: 4, icon: 'hd05.svg' },
|
||||||
|
"epees": { key: "epees", label: "Epées", lettreFont: 'e', saison: "ete", heure: 5, icon: 'hd06.svg' },
|
||||||
|
"lyre": { key: "lyre", label: "Lyre", lettreFont: 'l', saison: "automne", heure: 6, icon: 'hd07.svg' },
|
||||||
|
"serpent": { key: "serpent", label: "Serpent", lettreFont: 's', saison: "automne", heure: 7, icon: 'hd08.svg' },
|
||||||
|
"poissonacrobate": { key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "automne", heure: 8, icon: 'hd09.svg' },
|
||||||
|
"araignee": { key: "araignee", label: "Araignée", lettreFont: 'a', saison: "hiver", heure: 9, icon: 'hd10.svg' },
|
||||||
|
"roseau": { key: "roseau", label: "Roseau", lettreFont: 'r', saison: "hiver", heure: 10, icon: 'hd11.svg' },
|
||||||
|
"chateaudormant": { key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "hiver", heure: 11, icon: 'hd12.svg' }
|
||||||
|
};
|
||||||
|
const saisonsDef = {
|
||||||
|
"printemps": { label: "Printemps" },
|
||||||
|
"ete": { label: "Eté" },
|
||||||
|
"automne": { label: "Automne" },
|
||||||
|
"hiver": { label: "Hiver" }
|
||||||
|
};
|
||||||
|
|
||||||
|
const RDD_MOIS_PAR_AN = 12;
|
||||||
|
export const RDD_JOUR_PAR_MOIS = 28;
|
||||||
|
const RDD_HEURES_PAR_JOUR = 12;
|
||||||
|
const RDD_MINUTES_PAR_HEURES = 120;
|
||||||
|
const MAX_NOMBRE_ASTRAL = 12;
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
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 };
|
||||||
|
}
|
||||||
|
|
||||||
|
static getDefSigne(chiffre) {
|
||||||
|
chiffre = chiffre % RDD_MOIS_PAR_AN;
|
||||||
|
return Object.values(heuresDef).find(h => h.heure == chiffre);
|
||||||
|
}
|
||||||
|
|
||||||
|
static getSigneAs(key, value) {
|
||||||
|
const heure = (typeof value == 'string' || typeof value == 'number') && Number.isInteger(Number(value))
|
||||||
|
? Number(value)
|
||||||
|
: (typeof value == 'string') ? RdDCalendrier.getChiffreFromSigne(value)
|
||||||
|
: undefined
|
||||||
|
|
||||||
|
if (heure != undefined && ['key', 'label', 'lettreFont', 'saison', 'heure', 'icon'].includes(key)) {
|
||||||
|
return RdDCalendrier.getDefSigne(heure)[key]
|
||||||
|
}
|
||||||
|
if (heure != undefined && ['webp'].includes(key)) {
|
||||||
|
return RdDCalendrier.getDefSigne(heure)['icon'].replace('svg', 'webp');
|
||||||
|
}
|
||||||
|
console.error(`Appel à getSigneAs('${key}', ${value}) avec une clé/heure incorrects`);
|
||||||
|
return value;
|
||||||
|
|
||||||
|
}
|
||||||
|
static getChiffreFromSigne(signe) {
|
||||||
|
return heuresList.indexOf(signe);
|
||||||
|
}
|
||||||
|
|
||||||
|
static createCalendrierInitial() {
|
||||||
|
return {
|
||||||
|
heureRdD: 0,
|
||||||
|
minutesRelative: 0,
|
||||||
|
indexJour: 0,
|
||||||
|
annee: 0,
|
||||||
|
moisRdD: 0,
|
||||||
|
moisLabel: heuresDef["vaisseau"].label,
|
||||||
|
jour: 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
getCalendrier(index) {
|
||||||
|
index = index ?? this.getCurrentDayIndex();
|
||||||
|
const mois = Math.floor(index / RDD_JOUR_PAR_MOIS) % RDD_MOIS_PAR_AN;
|
||||||
|
return {
|
||||||
|
heureRdD: 0, // Index dans heuresList / heuresDef[x].heure
|
||||||
|
minutesRelative: 0,
|
||||||
|
indexJour: index,
|
||||||
|
annee: Math.floor(index / (RDD_JOUR_PAR_MOIS * RDD_MOIS_PAR_AN)),
|
||||||
|
moisRdD: RdDCalendrier.getDefSigne(mois).heure,
|
||||||
|
moisLabel: RdDCalendrier.getDefSigne(mois).label,
|
||||||
|
jour: (index % RDD_JOUR_PAR_MOIS) // Le calendrier stocke le jour en 0-27, mais en 1-28 à l'affichage
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.calendrier = duplicate(game.settings.get(SYSTEM_RDD, "calendrier") ?? RdDCalendrier.createCalendrierInitial());
|
||||||
|
this.calendrier.annee = this.calendrier.annee ?? Math.floor((this.calendrier.moisRdD ?? 0) / RDD_MOIS_PAR_AN);
|
||||||
|
this.calendrier.moisRdD = (this.calendrier.moisRdD ?? 0) % RDD_MOIS_PAR_AN;
|
||||||
|
|
||||||
|
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
|
||||||
|
game.settings.set(SYSTEM_RDD, "calendrier", this.calendrier);
|
||||||
|
|
||||||
|
this.listeNombreAstral = this.getListeNombreAstral();
|
||||||
|
this.rebuildListeNombreAstral(HIDE_DICE); // Ensure always up-to-date
|
||||||
|
}
|
||||||
|
console.log('RdDCalendrier.constructor()', this.calendrier, this.calendrierPos, this.listeNombreAstral);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/** @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") ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getDateFromIndex(index) {
|
||||||
|
const dateRdD = this.getCalendrier(index);
|
||||||
|
return (dateRdD.jour + 1) + ' ' + dateRdD.moisLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getDayMonthFromIndex(index = undefined) {
|
||||||
|
const dateRdD = this.getCalendrier(index);
|
||||||
|
return {
|
||||||
|
day: dateRdD.jour + 1,
|
||||||
|
month: heuresList[dateRdD.moisRdD]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getCurrentHeure() {
|
||||||
|
return heuresList[this.calendrier.heureRdD];
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getCurrentDayIndex() {
|
||||||
|
return (((this.calendrier.annee ?? 0) * RDD_MOIS_PAR_AN + (this.calendrier.moisRdD ?? 0)) * RDD_JOUR_PAR_MOIS) + (this.calendrier.jour ?? 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getIndexFromDate(jour, mois) {
|
||||||
|
return (heuresDef[mois].heure * RDD_JOUR_PAR_MOIS) + jour - 1;
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getJoursSuivants(num) {
|
||||||
|
let jours = [];
|
||||||
|
let index = this.getCurrentDayIndex();
|
||||||
|
for (let i = 0; i < num; i++) {
|
||||||
|
jours[i] = { label: this.getDateFromIndex(index + i), index: index + i };
|
||||||
|
}
|
||||||
|
return jours;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async ajouterNombreAstral(index, showDice = SHOW_DICE) {
|
||||||
|
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: showDice, rollMode: "selfroll" });
|
||||||
|
const dateFuture = this.getDateFromIndex(index);
|
||||||
|
if (showDice != HIDE_DICE) {
|
||||||
|
ChatMessage.create({
|
||||||
|
whisper: ChatMessage.getWhisperRecipients("GM"),
|
||||||
|
content: `Le chiffre astrologique du ${dateFuture} sera le ${nombreAstral}`
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
nombreAstral: nombreAstral,
|
||||||
|
valeursFausses: [],
|
||||||
|
index: index
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getCurrentNombreAstral() {
|
||||||
|
let indexDate = this.getCurrentDayIndex();
|
||||||
|
return this.getNombreAstral(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 jourCourant = this.getCurrentDayIndex();
|
||||||
|
let newList = [];
|
||||||
|
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
|
||||||
|
let dayIndex = jourCourant + i;
|
||||||
|
let na = this.listeNombreAstral.find(n => n.index == dayIndex);
|
||||||
|
if (na) {
|
||||||
|
newList[i] = na;
|
||||||
|
} else {
|
||||||
|
newList[i] = await this.ajouterNombreAstral(dayIndex, showDice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", newList);
|
||||||
|
this.listeNombreAstral = newList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
checkMaladie( periode) {
|
||||||
|
for (let actor of game.actors) {
|
||||||
|
if (actor.type == 'personnage') {
|
||||||
|
let maladies = actor.items.filter( item => (item.type == 'maladie' || (item.type == 'poison' && item.system.active) ) && item.system.periodicite.toLowerCase().includes(periode) );
|
||||||
|
for (let maladie of maladies) {
|
||||||
|
if ( maladie.system.identifie) {
|
||||||
|
ChatMessage.create({ content: `${actor.name} souffre de ${maladie.name} (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` });
|
||||||
|
} else {
|
||||||
|
ChatMessage.create({ content: `${actor.name} souffre d'un mal inconnu (${maladie.type}): vérifiez que les effets ne se sont pas aggravés !` });
|
||||||
|
}
|
||||||
|
let itemMaladie = actor.getObjet(maladie.id)
|
||||||
|
itemMaladie.postItem( 'gmroll');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async incrementTime(minutes = 0) {
|
||||||
|
this.calendrier.minutesRelative += minutes;
|
||||||
|
this.checkMaladie("round");
|
||||||
|
this.checkMaladie("minute");
|
||||||
|
if (this.calendrier.minutesRelative >= RDD_MINUTES_PAR_HEURES) {
|
||||||
|
this.calendrier.minutesRelative -= RDD_MINUTES_PAR_HEURES;
|
||||||
|
this.calendrier.heureRdD += 1;
|
||||||
|
this.checkMaladie("heure");
|
||||||
|
}
|
||||||
|
if (this.calendrier.heureRdD >= RDD_HEURES_PAR_JOUR) {
|
||||||
|
this.calendrier.heureRdD -= RDD_HEURES_PAR_JOUR;
|
||||||
|
await this.incrementerJour();
|
||||||
|
this.checkMaladie("heure");
|
||||||
|
this.checkMaladie("jour");
|
||||||
|
}
|
||||||
|
game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier));
|
||||||
|
// Notification aux joueurs // TODO: replace with Hook on game settings update
|
||||||
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
|
msg: "msg_sync_time",
|
||||||
|
data: duplicate(this.calendrier)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async incrementerJour() {
|
||||||
|
const index = this.getCurrentDayIndex() + 1;
|
||||||
|
this.calendrier = this.getCalendrier(index);
|
||||||
|
await this.rebuildListeNombreAstral();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
syncPlayerTime(calendrier) {
|
||||||
|
this.calendrier = duplicate(calendrier); // Local copy update
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async positionnerHeure(indexHeure) {
|
||||||
|
if (indexHeure <= this.calendrier.heureRdD) {
|
||||||
|
await this.incrementerJour();
|
||||||
|
}
|
||||||
|
this.calendrier.heureRdD = indexHeure;
|
||||||
|
this.calendrier.minutesRelative = 0;
|
||||||
|
game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
fillCalendrierData(formData = {}) {
|
||||||
|
const mois = RdDCalendrier.getDefSigne(this.calendrier.moisRdD);
|
||||||
|
const heure = RdDCalendrier.getDefSigne(this.calendrier.heureRdD);
|
||||||
|
console.log('fillCalendrierData', this.calendrier, mois, heure);
|
||||||
|
|
||||||
|
formData.heureKey = heure.key;
|
||||||
|
formData.moisKey = mois.key;
|
||||||
|
formData.jourMois = this.calendrier.jour + 1;
|
||||||
|
formData.nomMois = mois.label; // heures et mois nommés identiques
|
||||||
|
formData.annee = this.calendrier.annee;
|
||||||
|
formData.iconMois = dossierIconesHeures + mois.icon;
|
||||||
|
formData.nomHeure = heure.label;
|
||||||
|
formData.iconHeure = dossierIconesHeures + heure.icon;
|
||||||
|
formData.nomSaison = saisonsDef[mois.saison].label;
|
||||||
|
formData.heureRdD = this.calendrier.heureRdD;
|
||||||
|
formData.minutesRelative = this.calendrier.minutesRelative;
|
||||||
|
formData.isGM = game.user.isGM;
|
||||||
|
return formData;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getLectureAstrologieDifficulte(dateIndex) {
|
||||||
|
let indexNow = this.getCurrentDayIndex();
|
||||||
|
let diffDay = dateIndex - indexNow;
|
||||||
|
return - Math.floor(diffDay / 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async requestNombreAstral(request) {
|
||||||
|
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);
|
||||||
|
let nbAstral = this.getNombreAstral(request.date);
|
||||||
|
request.rolled = rollData.rolled;
|
||||||
|
request.isValid = true;
|
||||||
|
if (!request.rolled.isSuccess) {
|
||||||
|
request.isValid = false;
|
||||||
|
nbAstral = await RdDDice.rollTotal("1dhr" + nbAstral, { rollMode: "selfroll" });
|
||||||
|
// Mise à jour des nombres astraux du joueur
|
||||||
|
let astralData = this.listeNombreAstral.find((nombreAstral, i) => nombreAstral.index == request.date);
|
||||||
|
astralData.valeursFausses.push({ actorId: request.id, nombreAstral: nbAstral });
|
||||||
|
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.listeNombreAstral);
|
||||||
|
}
|
||||||
|
request.nbAstral = nbAstral;
|
||||||
|
if (Misc.getActiveUser(request.userId)?.isGM) {
|
||||||
|
RdDUtility.responseNombreAstral(request);
|
||||||
|
} else {
|
||||||
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
|
msg: "msg_response_nombre_astral",
|
||||||
|
data: request
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
findHeure(heure) {
|
||||||
|
heure = Grammar.toLowerCaseNoAccentNoSpace(heure);
|
||||||
|
let parHeureOuLabel = Object.values(heuresDef).filter(it => (it.heure + 1) == parseInt(heure) || Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure);
|
||||||
|
if (parHeureOuLabel.length == 1) {
|
||||||
|
return parHeureOuLabel[0];
|
||||||
|
}
|
||||||
|
let parLabelPartiel = Object.values(heuresDef).filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label).includes(heure));
|
||||||
|
if (parLabelPartiel.length > 0) {
|
||||||
|
parLabelPartiel.sort(Misc.ascending(h => h.label.length));
|
||||||
|
return parLabelPartiel[0];
|
||||||
|
}
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getHeureNumber( hNum) {
|
||||||
|
let heure = Object.values(heuresDef).find(it => (it.heure) == hNum);
|
||||||
|
return heure
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getHeuresChanceMalchance(heureNaissance) {
|
||||||
|
let heuresChancesMalchances = [];
|
||||||
|
let defHeure = this.findHeure(heureNaissance);
|
||||||
|
if (defHeure) {
|
||||||
|
let hn = defHeure.heure;
|
||||||
|
let chiffreAstral = this.getCurrentNombreAstral() ?? 0;
|
||||||
|
heuresChancesMalchances[0] = { value : "+4", heures: [this.getHeureNumber((hn + chiffreAstral) % RDD_HEURES_PAR_JOUR).label]};
|
||||||
|
heuresChancesMalchances[1] = { value : "+2", heures: [this.getHeureNumber((hn + chiffreAstral+4) % RDD_HEURES_PAR_JOUR).label,
|
||||||
|
this.getHeureNumber((hn + chiffreAstral + 8) % RDD_HEURES_PAR_JOUR).label ] };
|
||||||
|
heuresChancesMalchances[2] = { value : "-4", heures: [this.getHeureNumber((hn + chiffreAstral+6) % RDD_HEURES_PAR_JOUR).label]};
|
||||||
|
heuresChancesMalchances[3] = { value : "-2", heures: [this.getHeureNumber((hn + chiffreAstral+3) % RDD_HEURES_PAR_JOUR).label,
|
||||||
|
this.getHeureNumber((hn + chiffreAstral + 9) % RDD_HEURES_PAR_JOUR).label ]};
|
||||||
|
}
|
||||||
|
return heuresChancesMalchances;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
getAjustementAstrologique(heureNaissance, name = undefined) {
|
||||||
|
let defHeure = this.findHeure(heureNaissance);
|
||||||
|
if (defHeure) {
|
||||||
|
let hn = defHeure.heure;
|
||||||
|
let chiffreAstral = this.getCurrentNombreAstral() ?? 0;
|
||||||
|
let heureCourante = this.calendrier.heureRdD;
|
||||||
|
let ecartChance = (hn + chiffreAstral - heureCourante) % 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.jourMois} ${calendrier.nomMois} ${calendrier.annee} (${calendrier.nomSaison})`
|
||||||
|
if (game.user.isGM) {
|
||||||
|
dateHTML = dateHTML + " - NA: " + (this.getCurrentNombreAstral() ?? "indéterminé");
|
||||||
|
}
|
||||||
|
for (let handle of document.getElementsByClassName("calendar-date-rdd")) {
|
||||||
|
handle.innerHTML = dateHTML;
|
||||||
|
}
|
||||||
|
for (let heure of document.getElementsByClassName("calendar-heure-texte")) {
|
||||||
|
heure.innerHTML = calendrier.nomHeure;
|
||||||
|
}
|
||||||
|
for (const minute of document.getElementsByClassName("calendar-time-disp")) {
|
||||||
|
minute.innerHTML = `${calendrier.minutesRelative} minutes`;
|
||||||
|
}
|
||||||
|
for (const heureImg of document.getElementsByClassName("calendar-heure-img")) {
|
||||||
|
heureImg.src = calendrier.iconHeure;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async saveEditeur(calendrierData) {
|
||||||
|
this.calendrier.minutesRelative = Number(calendrierData.minutesRelative);
|
||||||
|
this.calendrier.jour = Number(calendrierData.jourMois) - 1;
|
||||||
|
this.calendrier.moisRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.moisKey);
|
||||||
|
this.calendrier.annee = Number(calendrierData.annee);
|
||||||
|
this.calendrier.heureRdD = RdDCalendrier.getChiffreFromSigne(calendrierData.heureKey);
|
||||||
|
game.settings.set(SYSTEM_RDD, "calendrier", duplicate(this.calendrier));
|
||||||
|
|
||||||
|
await this.rebuildListeNombreAstral();
|
||||||
|
|
||||||
|
game.socket.emit(SYSTEM_SOCKET_ID, {
|
||||||
|
msg: "msg_sync_time",
|
||||||
|
data: duplicate(this.calendrier)
|
||||||
|
});
|
||||||
|
|
||||||
|
this.updateDisplay();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async showCalendarEditor() {
|
||||||
|
let calendrierData = duplicate(this.fillCalendrierData());
|
||||||
|
if (this.editeur == undefined) {
|
||||||
|
calendrierData.jourMoisOptions = RdDCalendrier.buildJoursMois();
|
||||||
|
calendrierData.heuresOptions = [0, 1];
|
||||||
|
calendrierData.minutesOptions = Array(RDD_MINUTES_PAR_HEURES).fill().map((item, index) => 0 + index);
|
||||||
|
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 Array(RDD_JOUR_PAR_MOIS).fill().map((item, index) => 1 + index);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
async showAstrologieEditor() {
|
||||||
|
let calendrierData = duplicate(this.fillCalendrierData());
|
||||||
|
let astrologieArray = [];
|
||||||
|
this.listeNombreAstral = this.listeNombreAstral || [];
|
||||||
|
for (let astralData of this.listeNombreAstral) {
|
||||||
|
astralData.humanDate = this.getDateFromIndex(astralData.index);
|
||||||
|
for (let vf of astralData.valeursFausses) {
|
||||||
|
let actor = game.actors.get(vf.actorId);
|
||||||
|
vf.actorName = (actor) ? actor.name : "Inconnu";
|
||||||
|
}
|
||||||
|
astrologieArray.push(duplicate(astralData));
|
||||||
|
}
|
||||||
|
let heuresParActeur = {};
|
||||||
|
for (let actor of game.actors) {
|
||||||
|
let heureNaissance = actor.getHeureNaissance();
|
||||||
|
if ( heureNaissance) {
|
||||||
|
heuresParActeur[actor.name] = this.getHeuresChanceMalchance(heureNaissance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//console.log("ASTRO", astrologieArray);
|
||||||
|
calendrierData.astrologieData = astrologieArray;
|
||||||
|
calendrierData.heuresParActeur = heuresParActeur;
|
||||||
|
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,10 +39,9 @@ const tableCaracDerivee = {
|
|||||||
|
|
||||||
export class RdDCarac {
|
export class RdDCarac {
|
||||||
|
|
||||||
static isAgiliteOuDerobee(selectedCarac) {
|
static isAgiliteOuDerivee(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é';
|
||||||
}
|
}
|
||||||
@ -58,6 +57,15 @@ export class RdDCarac {
|
|||||||
selectedCarac?.label.match(/(Apparence|Force|Agilité|Dextérité|Vue|Ouïe|Odorat-Goût|Empathie|Dérobée|Mêlée|Tir|Lancer)/);
|
selectedCarac?.label.match(/(Apparence|Force|Agilité|Dextérité|Vue|Ouïe|Odorat-Goût|Empathie|Dérobée|Mêlée|Tir|Lancer)/);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static isIgnoreEtatGeneral(rollData) {
|
||||||
|
const selectedCarac = rollData.selectedCarac;
|
||||||
|
return !selectedCarac ||
|
||||||
|
rollData.ethylisme ||
|
||||||
|
RdDCarac.isChance(selectedCarac) ||
|
||||||
|
(RdDCarac.isReve(selectedCarac) && !rollData.competence);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static computeTotal(carac, beaute = undefined) {
|
static computeTotal(carac, beaute = undefined) {
|
||||||
const total = Object.values(carac ?? {}).filter(c => !c.derivee)
|
const total = Object.values(carac ?? {}).filter(c => !c.derivee)
|
||||||
.map(it => parseInt(it.value))
|
.map(it => parseInt(it.value))
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { ChatUtility } from "./chat-utility.js";
|
import { ChatUtility } from "./chat-utility.js";
|
||||||
import { ENTITE_BLURETTE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE, HIDE_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
|
import { DialogSelectTarget } from "./dialog-select-target.js";
|
||||||
import { Grammar } from "./grammar.js";
|
import { Grammar } from "./grammar.js";
|
||||||
import { RdDItemArme } from "./item-arme.js";
|
import { RdDItemArme } from "./item-arme.js";
|
||||||
import { RdDItemCompetence } from "./item-competence.js";
|
import { RdDItemCompetence } from "./item-competence.js";
|
||||||
@ -12,7 +13,6 @@ 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,32 +40,35 @@ export class RdDCombatManager extends Combat {
|
|||||||
|
|
||||||
static init() {
|
static init() {
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
Hooks.on("getCombatTrackerEntryContext", (html, options) => { RdDCombatManager.pushInitiativeOptions(html, options); });
|
Hooks.on("getCombatTrackerEntryContext", (html, options) => {
|
||||||
Hooks.on("updateCombat", (combat, change, options, userId) => { RdDCombat.onUpdateCombat(combat, change, options, userId) });
|
RdDCombatManager.pushInitiativeOptions(html, options);
|
||||||
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);
|
||||||
@ -87,32 +90,19 @@ export class RdDCombatManager extends Combat {
|
|||||||
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0);
|
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0);
|
||||||
if (!formula) {
|
if (!formula) {
|
||||||
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
|
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
|
||||||
const competence = combatant.actor.items.find(it => RdDItemCompetenceCreature.getCategorieAttaque(it))
|
const competence = combatant.actor.items.find(it => it.system.iscombat)
|
||||||
if (competence) {
|
if (competence) {
|
||||||
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, 0);
|
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, 0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
|
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
|
||||||
let compName = "Corps à corps"
|
const compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.system.competence;
|
||||||
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 && competence.system.defaut_carac) {
|
if (competence) {
|
||||||
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`);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -121,10 +111,10 @@ export class RdDCombatManager extends Combat {
|
|||||||
if (!roll.total) {
|
if (!roll.total) {
|
||||||
roll.evaluate({ async: false });
|
roll.evaluate({ async: false });
|
||||||
}
|
}
|
||||||
const total = Math.max(roll.total, 0.00);
|
if (roll.total <= 0) 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: total }]);
|
await this.updateEmbeddedDocuments("Combatant", [{ _id: id, initiative: roll.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");
|
||||||
@ -155,8 +145,9 @@ export class RdDCombatManager extends Combat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static calculInitiative(niveau, caracValue, bonus = 0) {
|
static calculInitiative(niveau, caracValue, bonusEcaille = 0) {
|
||||||
let base = niveau + Math.floor(caracValue / 2) + bonus;
|
let base = niveau + Math.floor(caracValue / 2);
|
||||||
|
base += bonusEcaille;
|
||||||
return "1d6" + (base >= 0 ? "+" : "") + base;
|
return "1d6" + (base >= 0 ? "+" : "") + base;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +162,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
if (arme.system.unemain && arme.system.deuxmains && !dommages.includes("/")) {
|
if (arme.system.unemain && arme.system.deuxmains && !dommages.includes("/")) {
|
||||||
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
|
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
|
||||||
}
|
}
|
||||||
|
console.log(">>>>", arme)
|
||||||
if ((arme.system.unemain && arme.system.competence) ||
|
if ((arme.system.unemain && arme.system.competence) ||
|
||||||
(arme.system.competence.toLowerCase().includes("corps à corps"))) {
|
(arme.system.competence.toLowerCase().includes("corps à corps"))) {
|
||||||
actions.push(RdDCombatManager.$prepareAttaqueArme({
|
actions.push(RdDCombatManager.$prepareAttaqueArme({
|
||||||
@ -230,15 +222,15 @@ export class RdDCombatManager extends Combat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static listActionsCreature(competences) {
|
static listActionsCreature(competences) {
|
||||||
return competences.map(it => RdDItemCompetenceCreature.armeCreature(it))
|
return competences.filter(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
|
||||||
.filter(it => it != undefined);
|
.map(it => RdDItemCompetenceCreature.armeNaturelle(it));
|
||||||
}
|
}
|
||||||
|
|
||||||
static listActionsPossessions(actor) {
|
static listActionsPossessions(actor) {
|
||||||
return RdDCombatManager._indexActions(actor.getPossessions().map(p => {
|
return RdDCombatManager._indexActions(actor.getPossessions().map(p => {
|
||||||
return {
|
return {
|
||||||
name: p.name,
|
name: p.name,
|
||||||
action: 'possession',
|
action: 'conjurer',
|
||||||
system: {
|
system: {
|
||||||
competence: p.name,
|
competence: p.name,
|
||||||
possessionid: p.system.possessionid,
|
possessionid: p.system.possessionid,
|
||||||
@ -255,15 +247,15 @@ export class RdDCombatManager extends Combat {
|
|||||||
return actions;
|
return actions;
|
||||||
}
|
}
|
||||||
if (actor.isCreatureEntite()) {
|
if (actor.isCreatureEntite()) {
|
||||||
actions = RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']);
|
actions = actions.concat(RdDCombatManager.listActionsCreature(actor.itemTypes['competencecreature']));
|
||||||
} else if (actor.isPersonnage()) {
|
} else {
|
||||||
// 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'];
|
||||||
actions = RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac);
|
actions = actions.concat(RdDCombatManager.listActionsArmes(armes, competences, actor.system.carac));
|
||||||
|
|
||||||
if (actor.system.attributs.hautrevant.value) {
|
if (actor.system.attributs.hautrevant.value) {
|
||||||
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
|
actions.push({ name: "Draconic", action: 'haut-reve', system: { initOnly: true, competence: "Draconic" } });
|
||||||
@ -351,7 +343,7 @@ export class RdDCombatManager extends Combat {
|
|||||||
} else if (combatant.actor.getSurprise() == "demi") {
|
} else if (combatant.actor.getSurprise() == "demi") {
|
||||||
initOffset = 0;
|
initOffset = 0;
|
||||||
initInfo = "Demi Surprise"
|
initInfo = "Demi Surprise"
|
||||||
} else if (action.action == 'possession') {
|
} else if (action.action == 'conjurer') {
|
||||||
initOffset = 10;
|
initOffset = 10;
|
||||||
caracForInit = combatant.actor.getReveActuel();
|
caracForInit = combatant.actor.getReveActuel();
|
||||||
initInfo = "Possession"
|
initInfo = "Possession"
|
||||||
@ -430,11 +422,18 @@ 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": return RdDCombat.onMsgEncaisser(sockmsg.data);
|
case "msg_encaisser":
|
||||||
case "msg_defense": return RdDCombat.onMsgDefense(sockmsg.data);
|
return RdDCombat.onMsgEncaisser(sockmsg.data);
|
||||||
|
case "msg_defense":
|
||||||
|
return RdDCombat.onMsgDefense(sockmsg.data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -445,6 +444,16 @@ 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()) {
|
||||||
@ -749,14 +758,29 @@ 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') {
|
if (arme.system.cac == 'empoignade' && this.attacker.isCombatTouche()) {
|
||||||
RdDEmpoignade.onAttaqueEmpoignade(this.attacker, this.defender)
|
ChatMessage.create({
|
||||||
|
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);
|
||||||
@ -790,7 +814,7 @@ export class RdDCombat {
|
|||||||
passeArme: randomID(16),
|
passeArme: randomID(16),
|
||||||
mortalite: arme?.system.mortalite,
|
mortalite: arme?.system.mortalite,
|
||||||
coupsNonMortels: false,
|
coupsNonMortels: false,
|
||||||
competence: competence.clone(),
|
competence: competence,
|
||||||
surprise: this.attacker.getSurprise(true),
|
surprise: this.attacker.getSurprise(true),
|
||||||
surpriseDefenseur: this.defender.getSurprise(true),
|
surpriseDefenseur: this.defender.getSurprise(true),
|
||||||
targetToken: Targets.extractTokenData(this.target),
|
targetToken: Targets.extractTokenData(this.target),
|
||||||
@ -948,8 +972,9 @@ 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))
|
||||||
items.forEach(item => item.system.nbUsage = defender.getItemUse(item.id)); // Ajout du # d'utilisation ce round
|
for (let item of items) {
|
||||||
|
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':
|
||||||
@ -1045,7 +1070,7 @@ export class RdDCombat {
|
|||||||
passeArme: attackerRoll.passeArme,
|
passeArme: attackerRoll.passeArme,
|
||||||
diffLibre: attackerRoll.diffLibre,
|
diffLibre: attackerRoll.diffLibre,
|
||||||
attackerRoll: attackerRoll,
|
attackerRoll: attackerRoll,
|
||||||
competence: this.defender.getCompetence(competenceParade).clone(),
|
competence: this.defender.getCompetence(competenceParade),
|
||||||
arme: armeParade,
|
arme: armeParade,
|
||||||
surprise: this.defender.getSurprise(true),
|
surprise: this.defender.getSurprise(true),
|
||||||
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
|
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(attackerRoll.arme, armeParade),
|
||||||
@ -1126,7 +1151,7 @@ export class RdDCombat {
|
|||||||
passeArme: attackerRoll.passeArme,
|
passeArme: attackerRoll.passeArme,
|
||||||
diffLibre: attackerRoll.diffLibre,
|
diffLibre: attackerRoll.diffLibre,
|
||||||
attackerRoll: attackerRoll,
|
attackerRoll: attackerRoll,
|
||||||
competence: competence.clone(),
|
competence: competence,
|
||||||
surprise: this.defender.getSurprise(true),
|
surprise: this.defender.getSurprise(true),
|
||||||
surpriseDefenseur: this.defender.getSurprise(true),
|
surpriseDefenseur: this.defender.getSurprise(true),
|
||||||
carac: this.defender.system.carac,
|
carac: this.defender.system.carac,
|
||||||
@ -1304,8 +1329,13 @@ export class RdDCombat {
|
|||||||
blessuresStatus: actor.computeResumeBlessure(),
|
blessuresStatus: actor.computeResumeBlessure(),
|
||||||
SConst: actor.getSConst(),
|
SConst: actor.getSConst(),
|
||||||
actorId: actor.id,
|
actorId: actor.id,
|
||||||
isGrave: actor.countBlessures(it => it.isGrave()) > 0,
|
isGrave: false,
|
||||||
isCritique: actor.countBlessures(it => it.isCritique()) > 0
|
isCritique: false
|
||||||
|
}
|
||||||
|
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,8 +2,7 @@
|
|||||||
|
|
||||||
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 { DialogChateauDormant } from "./sommeil/dialog-chateau-dormant.js";
|
import { DialogStress } from "./dialog-stress.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";
|
||||||
@ -14,7 +13,7 @@ import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
|||||||
import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
|
import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
|
||||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { FenetreRechercheTirage } from "./tirage/fenetre-recherche-tirage.js";
|
import { CompendiumTableHelpers } from "./settings/system-compendiums.js";
|
||||||
import { TMRUtility } from "./tmr-utility.js";
|
import { TMRUtility } from "./tmr-utility.js";
|
||||||
|
|
||||||
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
|
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
|
||||||
@ -24,7 +23,6 @@ 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] == '/') {
|
||||||
@ -37,6 +35,7 @@ export class RdDCommands {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
game.system.rdd.commands = rddCommands;
|
||||||
}
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
@ -64,6 +63,7 @@ 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,9 +75,8 @@ 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: ["/tirage"], func: (content, msg, params) => this.tirage(), descr: "Ouvre la fenêtre de recherche et tirage" });
|
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: ["/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" });
|
||||||
|
|
||||||
@ -208,7 +207,7 @@ export class RdDCommands {
|
|||||||
if (["gmroll", "blindroll"].includes(rollMode)) {
|
if (["gmroll", "blindroll"].includes(rollMode)) {
|
||||||
msg["whisper"] = ChatMessage.getWhisperRecipients("GM");
|
msg["whisper"] = ChatMessage.getWhisperRecipients("GM");
|
||||||
}
|
}
|
||||||
if (rollMode === "blindroll") {
|
if (rollMode === "blindroll"){
|
||||||
msg["blind"] = true;
|
msg["blind"] = true;
|
||||||
}
|
}
|
||||||
msg["type"] = 0;
|
msg["type"] = 0;
|
||||||
@ -226,7 +225,7 @@ export class RdDCommands {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
_isCommandHandled(command) {
|
_isCommandHandled(command){
|
||||||
return this.commandsTable[command] != undefined;
|
return this.commandsTable[command] != undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -255,7 +254,10 @@ export class RdDCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async help(msg, table = undefined) {
|
async help(msg) {
|
||||||
|
this.help(msg, undefined);
|
||||||
|
}
|
||||||
|
async help(msg, table) {
|
||||||
let commands = []
|
let commands = []
|
||||||
this._buildSubTableHelp(commands, table ?? this.commandsTable);
|
this._buildSubTableHelp(commands, table ?? this.commandsTable);
|
||||||
|
|
||||||
@ -329,10 +331,10 @@ export class RdDCommands {
|
|||||||
diff = 0;
|
diff = 0;
|
||||||
}
|
}
|
||||||
const caracName = params[0];
|
const caracName = params[0];
|
||||||
let competence = length > 1 ? actors[0].getCompetence(Misc.join(params.slice(1, length), ' ')) : { 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.doRollCaracCompetence(caracName, competence.name, diff);
|
await actor.rollCaracCompetence(caracName, competence.name, diff);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -396,6 +398,32 @@ 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)) {
|
||||||
@ -420,27 +448,17 @@ export class RdDCommands {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async creerSignesDraconiques() {
|
async creerSignesDraconiques() {
|
||||||
if (game.user.isGM) {
|
|
||||||
DialogCreateSigneDraconique.createSigneForActors();
|
DialogCreateSigneDraconique.createSigneForActors();
|
||||||
}
|
|
||||||
else {
|
|
||||||
ui.notifications.warn("Seul le MJ est autorisé à utiliser la commande /signe");
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
async supprimerSignesDraconiquesEphemeres() {
|
async supprimerSignesDraconiquesEphemeres() {
|
||||||
if (game.user.isGM) {
|
|
||||||
game.actors.forEach(actor => {
|
game.actors.forEach(actor => {
|
||||||
const ephemeres = actor.items.filter(item => item.type = 'signedraconique' && item.system.ephemere);
|
const ephemeres = actor.items.filter(item => item.type = 'signedraconique' && item.system.ephemere);
|
||||||
if (ephemeres.length > 0) {
|
if (ephemeres.length > 0) {
|
||||||
actor.deleteEmbeddedDocuments("Item", ephemeres.map(item => item.id));
|
actor.deleteEmbeddedDocuments("Item", ephemeres.map(item => item.id));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
else {
|
|
||||||
ui.notifications.warn("Seul le MJ est autorisé à utiliser la commande /signe");
|
|
||||||
}
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -463,14 +481,13 @@ 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) {
|
||||||
// TODO: ne plus stresser les entités de cauchemar!
|
actor.distribuerStress('stress', stress, motif);
|
||||||
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) {
|
||||||
await actor.distribuerStress('stress', stress, motif);
|
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}!`);
|
||||||
@ -484,11 +501,5 @@ 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) {
|
||||||
|
@ -1,436 +0,0 @@
|
|||||||
/* -------------------------------------------- */
|
|
||||||
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";
|
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
|
||||||
import { TYPES } from "./item.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
export class RdDEmpoignade {
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static init() {
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static registerChatCallbacks(html) {
|
|
||||||
html.on("click", '.defense-empoignade-cac', event => {
|
|
||||||
const chatMessage = ChatUtility.getChatMessage(event);
|
|
||||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
|
||||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
|
||||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee")
|
|
||||||
});
|
|
||||||
html.on("click", '.defense-empoignade-esquive', event => {
|
|
||||||
const chatMessage = ChatUtility.getChatMessage(event);
|
|
||||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
|
||||||
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
|
|
||||||
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee")
|
|
||||||
});
|
|
||||||
html.on("click", '.empoignade-poursuivre', event => {
|
|
||||||
let attackerId = event.currentTarget.attributes['data-attackerId'].value
|
|
||||||
let defenderId = event.currentTarget.attributes['data-defenderId'].value
|
|
||||||
RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId))
|
|
||||||
});
|
|
||||||
html.on("click", '.empoignade-entrainer-sol', event => {
|
|
||||||
const chatMessage = ChatUtility.getChatMessage(event);
|
|
||||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
|
||||||
RdDEmpoignade.entrainerAuSol(rollData)
|
|
||||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
|
||||||
});
|
|
||||||
html.on("click", '.empoignade-projeter-sol', event => {
|
|
||||||
const chatMessage = ChatUtility.getChatMessage(event);
|
|
||||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
|
||||||
RdDEmpoignade.projeterAuSol(rollData)
|
|
||||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
|
||||||
});
|
|
||||||
html.on("change", '.empoignade-perte-endurance', event => {
|
|
||||||
const chatMessage = ChatUtility.getChatMessage(event);
|
|
||||||
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
|
|
||||||
if (event.currentTarget.value && event.currentTarget.value != "none") {
|
|
||||||
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
|
|
||||||
ChatUtility.removeChatMessageId(chatMessage.id)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static checkEmpoignadeEnCours(actor) {
|
|
||||||
// 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 $storeRollEmpoignade(msg, rollData) {
|
|
||||||
RdDEmpoignade.$reduceActorToIds(rollData);
|
|
||||||
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData);
|
|
||||||
}
|
|
||||||
|
|
||||||
static $reduceActorToIds(rollData) {
|
|
||||||
rollData.attacker = { id: rollData.attacker.id };
|
|
||||||
rollData.defender = { id: rollData.defender.id };
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static $readRollEmpoignade(msg) {
|
|
||||||
const rollData = ChatUtility.getMessageData(msg, 'empoignade-roll-data');
|
|
||||||
RdDEmpoignade.$replaceIdsWithActors(rollData);
|
|
||||||
return rollData
|
|
||||||
}
|
|
||||||
|
|
||||||
static $replaceIdsWithActors(rollData) {
|
|
||||||
rollData.attacker = game.actors.get(rollData.attacker.id);
|
|
||||||
rollData.defender = game.actors.get(rollData.defender.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static isEmpoignadeEnCours(actor) {
|
|
||||||
return actor.itemTypes[TYPES.empoignade].find(it => it.system.pointsemp > 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static getEmpoignadeById(actor, id) {
|
|
||||||
let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id)
|
|
||||||
return emp && duplicate(emp) || undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static getEmpoignade(attacker, defender) {
|
|
||||||
let emp = attacker.itemTypes[TYPES.empoignade].find(it =>
|
|
||||||
(it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) ||
|
|
||||||
(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
|
|
||||||
}
|
|
||||||
// p135: Malus de -1 par point de taille de différence de taille au delà de 1 (donc -2 pour une différence de 3, ...)
|
|
||||||
const diffTaille = attacker.system.carac.taille.value - defender.system.carac.taille.value;
|
|
||||||
const diffTailleAbs = Math.abs(diffTaille)
|
|
||||||
const signDiff = diffTaille > 0 ? 1 : -1
|
|
||||||
|
|
||||||
if (diffTailleAbs > 2) {
|
|
||||||
return signDiff * (diffTailleAbs - 1)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
static isActionAutorisee(mode, attacker, defender) {
|
|
||||||
const acting = RdDEmpoignade.isActionDefenseur(mode) ? defender : attacker;
|
|
||||||
if (acting.getUserLevel(game.user) < CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) {
|
|
||||||
ui.notifications.warn(`Vous n'êtes pas autorisé à choisir l'action de ${acting.name}`)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
static isActionDefenseur(mode) {
|
|
||||||
switch (mode) {
|
|
||||||
case "liberer":
|
|
||||||
case "contrer-empoigner":
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async onAttaqueEmpoignade(attacker, defender) {
|
|
||||||
if (!RdDEmpoignade.isActionAutorisee("empoigner", attacker, defender)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
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 onAttaqueEmpoignadeValidee(attacker, defender) {
|
|
||||||
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
|
|
||||||
const isNouvelle = empoignade == undefined;
|
|
||||||
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
|
|
||||||
|
|
||||||
let mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer"
|
|
||||||
|
|
||||||
if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let rollData = {
|
|
||||||
mode, empoignade, attacker, defender,
|
|
||||||
isEmpoignade: true,
|
|
||||||
competence: attacker.getCompetence("Corps à corps").clone(),
|
|
||||||
selectedCarac: attacker.system.carac.melee,
|
|
||||||
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
|
|
||||||
}
|
|
||||||
if (attacker.isCreatureEntite()) {
|
|
||||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
|
||||||
}
|
|
||||||
if (empoignade.system.pointsemp >= 2) {
|
|
||||||
if (!empoignade.system.ausol) {
|
|
||||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.html');
|
|
||||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async onAttaqueEmpoignadeFromItem(empoignade) {
|
|
||||||
let attacker = game.actors.get(empoignade.system.empoigneurid)
|
|
||||||
let defender = game.actors.get(empoignade.system.empoigneid)
|
|
||||||
await this.onAttaqueEmpoignadeValidee(attacker, defender)
|
|
||||||
}
|
|
||||||
|
|
||||||
static async onImmobilisation(attacker, defender, empoignade) {
|
|
||||||
const rollData = {
|
|
||||||
mode: "immobilise",
|
|
||||||
empoignade, attacker, defender,
|
|
||||||
isEmpoignade: true,
|
|
||||||
competence: attacker.getCompetence("Corps à corps").clone()
|
|
||||||
}
|
|
||||||
const msg = await ChatMessage.create({
|
|
||||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(attacker.name),
|
|
||||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-immobilise.html`, rollData)
|
|
||||||
})
|
|
||||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) {
|
|
||||||
const dialog = await RdDRoll.create(attacker, rollData,
|
|
||||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' },
|
|
||||||
{
|
|
||||||
name: 'jet-empoignade',
|
|
||||||
label: 'Empoigner',
|
|
||||||
callbacks: [{ action: async (r) => await RdDEmpoignade.$onRollEmpoignade(r, isNouvelle) },]
|
|
||||||
});
|
|
||||||
dialog.render(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async $onRollEmpoignade(rollData, isNouvelle = false) {
|
|
||||||
let attacker = game.actors.get(rollData.attacker.id)
|
|
||||||
let defender = game.actors.get(rollData.defender.id)
|
|
||||||
|
|
||||||
|
|
||||||
if (rollData.rolled.isSuccess && isNouvelle) {
|
|
||||||
const objectEmpoignade = rollData.empoignade.toObject();
|
|
||||||
// Creer l'empoignade sur attaquant/defenseur
|
|
||||||
attacker.creerObjetParMJ(objectEmpoignade);
|
|
||||||
defender.creerObjetParMJ(objectEmpoignade);
|
|
||||||
}
|
|
||||||
|
|
||||||
rollData.empoignade.isSuccess = rollData.rolled.isSuccess;
|
|
||||||
if (rollData.rolled.isPart) {
|
|
||||||
rollData.particuliere = "finesse";
|
|
||||||
}
|
|
||||||
let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-resultat.html');
|
|
||||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async onDefenseEmpoignade(attackerRoll, mode, competenceName = "Corps à corps", carac = "melee") {
|
|
||||||
let attacker = game.actors.get(attackerRoll.attacker.id)
|
|
||||||
let defender = game.actors.get(attackerRoll.defender.id)
|
|
||||||
if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
let empoignade = this.getEmpoignade(attacker, defender)
|
|
||||||
|
|
||||||
if (!empoignade) {
|
|
||||||
ui.notifications.warn("Une erreur s'est produite : Aucune empoignade trouvée !!")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
empoignade = duplicate(empoignade)
|
|
||||||
let defenderRoll = {
|
|
||||||
mode, attacker, defender, empoignade, attackerRoll,
|
|
||||||
diffLibre: attackerRoll.diffLibre,
|
|
||||||
attaqueParticuliere: attackerRoll.particuliere,
|
|
||||||
competence: defender.getCompetence(competenceName).clone(),
|
|
||||||
surprise: defender.getSurprise(true),
|
|
||||||
carac: defender.system.carac,
|
|
||||||
selectedCarac: defender.system.carac[carac],
|
|
||||||
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, defender, attacker),
|
|
||||||
show: {}
|
|
||||||
};
|
|
||||||
await RdDEmpoignade.$rollDefenseEmpoignade(defender, defenderRoll);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async $rollDefenseEmpoignade(defender, defenderRoll) {
|
|
||||||
const dialog = await RdDRoll.create(defender, defenderRoll,
|
|
||||||
{ 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)
|
|
||||||
}
|
|
||||||
|
|
||||||
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-empoignade-resultat.html')
|
|
||||||
if (empoignade.system.pointsemp >= 2) {
|
|
||||||
let msg = await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-empoignade-entrainer.html');
|
|
||||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
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])
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async entrainerAuSol(rollData) {
|
|
||||||
let attacker = game.actors.get(rollData.attacker.id)
|
|
||||||
let defender = game.actors.get(rollData.defender.id)
|
|
||||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
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');
|
|
||||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async projeterAuSol(rollData) {
|
|
||||||
let attacker = game.actors.get(rollData.attacker.id)
|
|
||||||
let defender = game.actors.get(rollData.defender.id)
|
|
||||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
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');
|
|
||||||
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static async perteEndurance(rollData, perteMode) {
|
|
||||||
let attacker = game.actors.get(rollData.attacker.id)
|
|
||||||
let defender = game.actors.get(rollData.defender.id)
|
|
||||||
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
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');
|
|
||||||
RdDEmpoignade.$storeRollEmpoignade(msg, 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,7 @@
|
|||||||
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
|
import { RdDCalendrier } from "./rdd-calendrier.js";
|
||||||
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 "./time/rdd-timestamp.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
export class RdDHerbes extends Item {
|
export class RdDHerbes extends Item {
|
||||||
@ -28,7 +29,7 @@ export class RdDHerbes extends Item {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async addPotionFormData(formData) {
|
static async updatePotionData(formData) {
|
||||||
formData.isSoins = formData.system.categorie.includes('Soin');
|
formData.isSoins = formData.system.categorie.includes('Soin');
|
||||||
formData.isRepos = formData.system.categorie.includes('Repos');
|
formData.isRepos = formData.system.categorie.includes('Repos');
|
||||||
if (formData.isSoins) {
|
if (formData.isSoins) {
|
||||||
@ -39,8 +40,9 @@ export class RdDHerbes extends Item {
|
|||||||
}
|
}
|
||||||
formData.herbesSoins = RdDHerbes.buildHerbesList(this.herbesSoins, 12);
|
formData.herbesSoins = RdDHerbes.buildHerbesList(this.herbesSoins, 12);
|
||||||
formData.herbesRepos = RdDHerbes.buildHerbesList(this.herbesRepos, 7);
|
formData.herbesRepos = RdDHerbes.buildHerbesList(this.herbesRepos, 7);
|
||||||
formData.dateActuelle = game.system.rdd.calendrier.dateCourante();
|
formData.jourMoisOptions = RdDCalendrier.buildJoursMois();
|
||||||
formData.enchantement = RdDTimestamp.splitIndexDate(formData.system.prdate);
|
formData.dateActuelle = game.system.rdd.calendrier.getDateFromIndex();
|
||||||
|
formData.splitDate = game.system.rdd.calendrier.getDayMonthFromIndex(formData.system.prdate);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import { Misc } from "./misc.js";
|
||||||
|
|
||||||
export class RdDHotbar {
|
export class RdDHotbar {
|
||||||
|
|
||||||
|
@ -1,217 +1,78 @@
|
|||||||
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
/**
|
||||||
import { Migrations } from './migrations.js';
|
* RdD system
|
||||||
|
* Author: LeRatierBretonnien
|
||||||
|
* Software License: GNU GPLv3
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
// Import Modules
|
||||||
|
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||||
|
import { RdDActor } from "./actor.js";
|
||||||
|
import { RdDItemSheet } from "./item-sheet.js";
|
||||||
|
import { RdDActorSheet } from "./actor-sheet.js";
|
||||||
|
import { RdDActorCreatureSheet } from "./actor-creature-sheet.js";
|
||||||
|
import { RdDActorVehiculeSheet } from "./actor-vehicule-sheet.js";
|
||||||
|
import { RdDActorEntiteSheet } from "./actor-entite-sheet.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 { TMRRencontres } from "./tmr-rencontres.js";
|
import { RdDCalendrier } from "./rdd-calendrier.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";
|
||||||
import { RdDHerbes } from "./rdd-herbes.js";
|
import { RdDHerbes } from "./rdd-herbes.js";
|
||||||
|
import { RdDItem } from "./item.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 { RdDSigneDraconiqueItemSheet } from "./item-signedraconique-sheet.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 { RdDRencontreItemSheet } from "./item-rencontre-sheet.js";
|
||||||
|
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||||
|
import { RdDHerbeItemSheet } from "./item-herbe-sheet.js";
|
||||||
import { Environnement } from "./environnement.js";
|
import { Environnement } from "./environnement.js";
|
||||||
|
import { RdDIngredientItemSheet } from "./item-ingredient-sheet.js";
|
||||||
|
import { RdDFauneItemSheet } from "./item-faune-sheet.js";
|
||||||
|
import { RdDConteneurItemSheet } from "./item-conteneur-sheet.js";
|
||||||
|
|
||||||
import { RdDActor } from "./actor.js";
|
/* -------------------------------------------- */
|
||||||
import { RdDBaseActor } from "./actor/base-actor.js";
|
/* Foundry VTT Initialization */
|
||||||
import { RdDCommerce } from "./actor/commerce.js";
|
/* -------------------------------------------- */
|
||||||
import { RdDActorSheet } from "./actor-sheet.js";
|
|
||||||
import { RdDCommerceSheet } from "./actor/commerce-sheet.js";
|
|
||||||
import { RdDActorCreatureSheet } from "./actor-creature-sheet.js";
|
|
||||||
import { RdDActorVehiculeSheet } from "./actor-vehicule-sheet.js";
|
|
||||||
import { RdDActorEntiteSheet } from "./actor-entite-sheet.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
|
|
||||||
* Author: LeRatierBretonnien
|
|
||||||
* Software License: GNU GPLv3
|
|
||||||
*/
|
|
||||||
export class SystemReveDeDragon {
|
|
||||||
|
|
||||||
static start() {
|
|
||||||
const system = new SystemReveDeDragon();
|
|
||||||
Hooks.once('init', async () => await system.onInit());
|
|
||||||
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d));
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor() {
|
|
||||||
this.RdDUtility = RdDUtility;
|
|
||||||
this.RdDHotbar = RdDHotbar;
|
|
||||||
this.itemClasses = {
|
|
||||||
armure: RdDItemArmure,
|
|
||||||
blessure: RdDItemBlessure,
|
|
||||||
maladie: RdDItemMaladie,
|
|
||||||
ombre: RdDItemOmbre,
|
|
||||||
poison: RdDItemPoison,
|
|
||||||
queue: RdDItemQueue,
|
|
||||||
rencontre: RdDRencontre,
|
|
||||||
service: RdDItemService,
|
|
||||||
signedraconique: RdDItemSigneDraconique,
|
|
||||||
souffle: RdDItemSouffle,
|
|
||||||
}
|
|
||||||
this.actorClasses = {
|
|
||||||
commerce: RdDCommerce,
|
|
||||||
creature: RdDActor,
|
|
||||||
entite: RdDActor,
|
|
||||||
personnage: RdDActor,
|
|
||||||
vehicule: RdDActor,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
/* Foundry VTT Initialization */
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
async onInit() {
|
|
||||||
game.system.rdd = this;
|
|
||||||
this.AppAstrologie = AppAstrologie;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/************************************************************************************/
|
||||||
|
Hooks.once("init", async function () {
|
||||||
console.log(`Initializing Reve de Dragon System`);
|
console.log(`Initializing Reve de Dragon System`);
|
||||||
|
|
||||||
// preload handlebars templates
|
// preload handlebars templates
|
||||||
RdDUtility.preloadHandlebarsTemplates();
|
RdDUtility.preloadHandlebarsTemplates();
|
||||||
|
// Create useful storage space
|
||||||
/* -------------------------------------------- */
|
game.system.rdd = {
|
||||||
this.initSystemSettings();
|
TMRUtility,
|
||||||
|
RdDUtility,
|
||||||
/* -------------------------------------------- */
|
RdDHotbar,
|
||||||
// Set an initiative formula for the system
|
RdDPossession,
|
||||||
CONFIG.Combat.initiative = {
|
|
||||||
formula: "1+(1d6/10)",
|
|
||||||
decimals: 2
|
|
||||||
};
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => {
|
|
||||||
console.log(">>>>> MSG RECV", sockmsg);
|
|
||||||
try {
|
|
||||||
RdDUtility.onSocketMessage(sockmsg);
|
|
||||||
RdDCombat.onSocketMessage(sockmsg);
|
|
||||||
ChatUtility.onSocketMessage(sockmsg);
|
|
||||||
RdDBaseActor.onSocketMessage(sockmsg);
|
|
||||||
} catch (e) {
|
|
||||||
console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg, ' => ', e)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
// Define custom Entity classes
|
|
||||||
CONFIG.Actor.documentClass = RdDBaseActor;
|
|
||||||
CONFIG.Item.documentClass = RdDItem;
|
|
||||||
CONFIG.RDD = {
|
|
||||||
resolutionTable: RdDResolutionTable.resolutionTable,
|
|
||||||
carac_array: RdDUtility.getCaracArray(),
|
|
||||||
ajustementsConditions: RdDUtility.getAjustementsConditions(),
|
|
||||||
difficultesLibres: RdDUtility.getDifficultesLibres()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// Register sheet application classes
|
|
||||||
Actors.unregisterSheet("core", ActorSheet);
|
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDCommerceSheet, { types: ["commerce"], makeDefault: true });
|
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true });
|
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDActorCreatureSheet, { types: ["creature"], makeDefault: true });
|
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true });
|
|
||||||
Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true });
|
|
||||||
Items.unregisterSheet("core", ItemSheet);
|
|
||||||
|
|
||||||
RdDItemSheet.register(RdDSigneDraconiqueItemSheet);
|
|
||||||
RdDItemSheet.register(RdDRencontreItemSheet);
|
|
||||||
RdDItemSheet.register(RdDConteneurItemSheet);
|
|
||||||
RdDItemSheet.register(RdDHerbeItemSheet);
|
|
||||||
RdDItemSheet.register(RdDFauneItemSheet);
|
|
||||||
RdDItemSheet.register(RdDPlanteItemSheet);
|
|
||||||
RdDItemSheet.register(RdDIngredientItemSheet);
|
|
||||||
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, {
|
|
||||||
types: [
|
|
||||||
"competence", "competencecreature",
|
|
||||||
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
|
|
||||||
"meditation", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
|
|
||||||
"nombreastral", "tache", "maladie", "poison", "possession",
|
|
||||||
"tarot", "extraitpoetique", "empoignade"
|
|
||||||
], makeDefault: true
|
|
||||||
});
|
|
||||||
CONFIG.Combat.documentClass = RdDCombatManager;
|
|
||||||
|
|
||||||
// préparation des différents modules
|
|
||||||
RdDTimestamp.init();
|
|
||||||
RdDCalendrier.init();
|
|
||||||
SystemCompendiums.init();
|
|
||||||
DialogChronologie.init();
|
|
||||||
ReglesOptionelles.init();
|
|
||||||
RdDUtility.init();
|
|
||||||
RdDDice.init();
|
|
||||||
RdDCommands.init();
|
|
||||||
RdDCombatManager.init();
|
|
||||||
RdDTokenHud.init();
|
|
||||||
RdDBaseActor.init();
|
|
||||||
RdDCompendiumOrganiser.init();
|
|
||||||
EffetsDraconiques.init()
|
|
||||||
TMRUtility.init();
|
|
||||||
RdDHotbar.initDropbar();
|
|
||||||
RdDPossession.init();
|
|
||||||
TMRRencontres.init();
|
|
||||||
Environnement.init();
|
|
||||||
|
|
||||||
Hooks.once('ready', () => this.onReady());
|
|
||||||
}
|
|
||||||
|
|
||||||
initSystemSettings() {
|
|
||||||
game.settings.register(SYSTEM_RDD, "accorder-entite-cauchemar", {
|
game.settings.register(SYSTEM_RDD, "accorder-entite-cauchemar", {
|
||||||
name: "Accorder le rêve aux entités",
|
name: "Accorder le rêve aux entités",
|
||||||
hint: "A quel moment les personnages doivent accorder leur rêve aux entités de cauchemar",
|
hint: "A quel moment les personnages doivent accorder leur rêve aux entités de cauchemar",
|
||||||
scope: "world",
|
scope: "world",
|
||||||
config: true,
|
config: true,
|
||||||
type: String,
|
type: String,
|
||||||
choices: {
|
choices: { // If choices are defined, the resulting setting will be a select menu
|
||||||
"avant-attaque": "Avant l'attaque",
|
"avant-attaque": "Avant l'attaque",
|
||||||
"avant-defense": "Avant la défense",
|
"avant-defense": "Avant la défense",
|
||||||
"avant-encaissement": "Avant l'encaissement",
|
"avant-encaissement": "Avant l'encaissement",
|
||||||
@ -219,6 +80,43 @@ export class SystemReveDeDragon {
|
|||||||
default: "avant-encaissement"
|
default: "avant-encaissement"
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
game.settings.register(SYSTEM_RDD, "calendrier", {
|
||||||
|
name: "calendrier",
|
||||||
|
scope: "world",
|
||||||
|
config: false,
|
||||||
|
default: RdDCalendrier.createCalendrierInitial(),
|
||||||
|
type: Object
|
||||||
|
});
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
game.settings.register(SYSTEM_RDD, "migration-png-webp-1.5.34", {
|
||||||
|
name: "calendrier",
|
||||||
|
scope: "world",
|
||||||
|
config: false,
|
||||||
|
default: false,
|
||||||
|
type: Boolean
|
||||||
|
});
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
game.settings.register(SYSTEM_RDD, "liste-nombre-astral", {
|
||||||
|
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",
|
||||||
@ -228,7 +126,6 @@ export class SystemReveDeDragon {
|
|||||||
default: true,
|
default: true,
|
||||||
type: Boolean
|
type: Boolean
|
||||||
});
|
});
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
game.settings.register(SYSTEM_RDD, "activer-sons-audio", {
|
game.settings.register(SYSTEM_RDD, "activer-sons-audio", {
|
||||||
name: "Activer les bruitages intégrés",
|
name: "Activer les bruitages intégrés",
|
||||||
@ -252,43 +149,89 @@ export class SystemReveDeDragon {
|
|||||||
},
|
},
|
||||||
default: "aucun"
|
default: "aucun"
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
async onReady() {
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Foundry VTT Initialization */
|
// Set an initiative formula for the system
|
||||||
/* -------------------------------------------- */
|
CONFIG.Combat.initiative = {
|
||||||
// CSS patch for v9
|
formula: "1+(1d6/10)",
|
||||||
if (game.version) {
|
decimals: 2
|
||||||
let sidebar = document.getElementById("sidebar");
|
};
|
||||||
sidebar.style.width = "min-content";
|
|
||||||
}
|
|
||||||
game.system.rdd.calendrier = new RdDCalendrier();
|
|
||||||
if (Misc.isUniqueConnectedGM()) {
|
|
||||||
new Migrations().migrate();
|
|
||||||
this.messageDeBienvenue();
|
|
||||||
this.registerUsageCount(SYSTEM_RDD);
|
|
||||||
}
|
|
||||||
|
|
||||||
StatusEffects.onReady();
|
|
||||||
RdDHerbes.initializeHerbes();
|
|
||||||
RdDDice.onReady();
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Affiche/Init le calendrier */
|
game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => {
|
||||||
game.system.rdd.calendrier.display();
|
console.log(">>>>> MSG RECV", sockmsg);
|
||||||
// Avertissement si joueur sans personnage
|
try {
|
||||||
if (!game.user.isGM && game.user.character == undefined) {
|
RdDUtility.onSocketMessage(sockmsg);
|
||||||
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !");
|
RdDCombat.onSocketMessage(sockmsg);
|
||||||
ChatMessage.create({
|
ChatUtility.onSocketMessage(sockmsg);
|
||||||
content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !",
|
RdDActor.onSocketMessage(sockmsg);
|
||||||
user: game.user.id
|
} catch (e) {
|
||||||
|
console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg, ' => ', e)
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
// Define custom Entity classes
|
||||||
|
CONFIG.Actor.documentClass = RdDActor;
|
||||||
|
CONFIG.Item.documentClass = RdDItem;
|
||||||
|
CONFIG.RDD = {
|
||||||
|
resolutionTable: RdDResolutionTable.resolutionTable,
|
||||||
|
carac_array: RdDUtility.getCaracArray(),
|
||||||
|
ajustementsConditions: RdDUtility.getAjustementsConditions(),
|
||||||
|
difficultesLibres: RdDUtility.getDifficultesLibres()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
messageDeBienvenue() {
|
// Register sheet application classes
|
||||||
|
Actors.unregisterSheet("core", ActorSheet);
|
||||||
|
Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true });
|
||||||
|
Actors.registerSheet(SYSTEM_RDD, RdDActorCreatureSheet, { types: ["creature"], makeDefault: true });
|
||||||
|
Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true });
|
||||||
|
Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true });
|
||||||
|
Items.unregisterSheet("core", ItemSheet);
|
||||||
|
|
||||||
|
RdDItemSheet.register(RdDSigneDraconiqueItemSheet);
|
||||||
|
RdDItemSheet.register(RdDRencontreItemSheet);
|
||||||
|
RdDItemSheet.register(RdDConteneurItemSheet);
|
||||||
|
RdDItemSheet.register(RdDHerbeItemSheet);
|
||||||
|
RdDItemSheet.register(RdDFauneItemSheet);
|
||||||
|
RdDItemSheet.register(RdDIngredientItemSheet);
|
||||||
|
|
||||||
|
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
|
||||||
|
types: [
|
||||||
|
"competence", "competencecreature",
|
||||||
|
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre",
|
||||||
|
"objet", "arme", "armure", "livre", "potion", "munition",
|
||||||
|
"monnaie", "nourritureboisson", "gemme",
|
||||||
|
"meditation", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
|
||||||
|
"nombreastral", "tache", "maladie", "poison", "possession",
|
||||||
|
"tarot", "extraitpoetique"
|
||||||
|
], makeDefault: true
|
||||||
|
});
|
||||||
|
CONFIG.Combat.documentClass = RdDCombatManager;
|
||||||
|
|
||||||
|
// préparation des différents modules
|
||||||
|
SystemCompendiums.init();
|
||||||
|
DialogChronologie.init();
|
||||||
|
ReglesOptionelles.init();
|
||||||
|
RdDUtility.init();
|
||||||
|
RdDDice.init();
|
||||||
|
RdDCommands.init();
|
||||||
|
RdDCombat.init();
|
||||||
|
RdDCombatManager.init();
|
||||||
|
RdDTokenHud.init();
|
||||||
|
RdDActor.init();
|
||||||
|
RddCompendiumOrganiser.init();
|
||||||
|
EffetsDraconiques.init()
|
||||||
|
TMRUtility.init();
|
||||||
|
RdDHotbar.initDropbar();
|
||||||
|
RdDPossession.init();
|
||||||
|
TMRRencontres.init();
|
||||||
|
Environnement.init();
|
||||||
|
});
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
function messageDeBienvenue() {
|
||||||
if (game.user.isGM) {
|
if (game.user.isGM) {
|
||||||
ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">');
|
ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">');
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
@ -298,11 +241,11 @@ export class SystemReveDeDragon {
|
|||||||
<br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div>
|
<br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div>
|
||||||
` });
|
` });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
// Register world usage statistics
|
// Register world usage statistics
|
||||||
async registerUsageCount(registerKey) {
|
function registerUsageCount(registerKey) {
|
||||||
if (game.user.isGM) {
|
if (game.user.isGM) {
|
||||||
game.settings.register("world", "world-key", {
|
game.settings.register("world", "world-key", {
|
||||||
name: "Unique world key",
|
name: "Unique world key",
|
||||||
@ -321,9 +264,82 @@ export class SystemReveDeDragon {
|
|||||||
$.ajax(regURL)
|
$.ajax(regURL)
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Foundry VTT Initialization */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
Hooks.once("ready", async function () {
|
||||||
|
await migrationPngWebp_1_5_34()
|
||||||
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
|
new Migrations().migrate();
|
||||||
|
}
|
||||||
|
|
||||||
|
StatusEffects.onReady();
|
||||||
|
RdDHerbes.initializeHerbes();
|
||||||
|
RdDDice.onReady();
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
/* Affiche/Init le calendrier */
|
||||||
|
let calendrier = new RdDCalendrier();
|
||||||
|
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
|
||||||
|
if (!game.user.isGM && game.user.character == undefined) {
|
||||||
|
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !");
|
||||||
|
ChatMessage.create({
|
||||||
|
content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !",
|
||||||
|
user: game.user.id
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (Misc.isUniqueConnectedGM()) {
|
||||||
|
messageDeBienvenue();
|
||||||
|
registerUsageCount(SYSTEM_RDD);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function migrationPngWebp_1_5_34() {
|
||||||
|
if (!game.settings.get(SYSTEM_RDD, "migration-png-webp-1.5.34")) {
|
||||||
|
const regexOldPngJpg = /(systems\/foundryvtt-reve-de-dragon\/icons\/.*)\.(png|jpg)/;
|
||||||
|
const replaceWithWebp = '$1.webp';
|
||||||
|
function convertImgToWebp(img) {
|
||||||
|
return img.replace(regexOldPngJpg, replaceWithWebp);
|
||||||
|
}
|
||||||
|
function prepareDocumentsImgUpdate(documents) {
|
||||||
|
return documents.filter(it => it.img && it.img.match(regexOldPngJpg))
|
||||||
|
.map(it => {
|
||||||
|
return { _id: it.id, img: convertImgToWebp(it.img) }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const itemsUpdates = prepareDocumentsImgUpdate(game.items);
|
||||||
|
const actorsUpdates = prepareDocumentsImgUpdate(game.actors);
|
||||||
|
//Migrate system png to webp
|
||||||
|
await Item.updateDocuments(itemsUpdates);
|
||||||
|
await Actor.updateDocuments(actorsUpdates);
|
||||||
|
game.actors.forEach(actor => {
|
||||||
|
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
|
||||||
|
actor.update({ "token.img": convertImgToWebp(actor.token.img) });
|
||||||
|
}
|
||||||
|
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
|
||||||
|
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
|
||||||
|
});
|
||||||
|
game.settings.set(SYSTEM_RDD, "migration-png-webp-1.5.34", true)
|
||||||
|
}
|
||||||
|
|
||||||
|
// CSS patch for v9
|
||||||
|
if (game.version) {
|
||||||
|
let sidebar = document.getElementById("sidebar");
|
||||||
|
sidebar.style.width = "min-content";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemReveDeDragon.start();
|
/* -------------------------------------------- */
|
||||||
|
/* Dice-so-nice ready */
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d));
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { RdDBaseActor } from "./actor/base-actor.js";
|
import { RdDActor } from "./actor.js";
|
||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDDice } from "./rdd-dice.js";
|
import { RdDDice } from "./rdd-dice.js";
|
||||||
|
|
||||||
@ -20,7 +20,7 @@ export class RdDNameGen {
|
|||||||
|
|
||||||
static async onCreerActeur(event) {
|
static async onCreerActeur(event) {
|
||||||
const button = event.currentTarget;
|
const button = event.currentTarget;
|
||||||
await RdDBaseActor.create({
|
await RdDActor.create({
|
||||||
name: button.attributes['data-nom'].value,
|
name: button.attributes['data-nom'].value,
|
||||||
type: button.attributes['data-type'].value
|
type: button.attributes['data-type'].value
|
||||||
},
|
},
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
import { RdDCombat } from "./rdd-combat.js";
|
||||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||||
import { RdDRoll } from "./rdd-roll.js";
|
import { RdDRoll } from "./rdd-roll.js";
|
||||||
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
|
||||||
import { Targets } from "./targets.js";
|
import { Targets } from "./targets.js";
|
||||||
import { TYPES } from "./item.js";
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* On part du principe qu'une entité démarre tjs
|
/* On part du principe qu'une entité démarre tjs
|
||||||
@ -20,9 +20,9 @@ export class RdDPossession {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static searchPossessionFromEntite(attacker, defender) {
|
static searchPossessionFromEntite(attacker, defender) {
|
||||||
let poss = attacker.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id);
|
let poss = attacker.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id);
|
||||||
if (!poss) {
|
if (!poss) {
|
||||||
poss = defender.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id);
|
poss = defender.items.find(poss => poss.type == 'possession' && poss.system.possedeid == defender.id);
|
||||||
}
|
}
|
||||||
return poss && duplicate(poss) || undefined;
|
return poss && duplicate(poss) || undefined;
|
||||||
}
|
}
|
||||||
@ -31,40 +31,39 @@ export class RdDPossession {
|
|||||||
static async onAttaquePossession(target, attacker, competence, suitePossession = undefined) {
|
static async onAttaquePossession(target, attacker, competence, suitePossession = undefined) {
|
||||||
const defender = target.actor;
|
const defender = target.actor;
|
||||||
const fromEntite = RdDPossession.searchPossessionFromEntite(attacker, defender);
|
const fromEntite = RdDPossession.searchPossessionFromEntite(attacker, defender);
|
||||||
const isNouvelle = !suitePossession && !fromEntite;
|
const isNouvelle = !suitePossession && ! fromEntite;
|
||||||
const possession = (suitePossession ?? fromEntite ?? (await RdDPossession.createPossession(attacker, defender)));
|
const possession = (suitePossession ?? fromEntite ?? (await RdDPossession.createPossession(attacker, defender)));
|
||||||
|
|
||||||
RdDPossession.$updateEtatPossession(possession)
|
RdDPossession.$updateEtatPossession(possession)
|
||||||
|
|
||||||
let rollData = {
|
let rollData = {
|
||||||
mode: "attaque",
|
mode: "possession",
|
||||||
isECNIDefender: false,
|
isECNIDefender: false,
|
||||||
competence: competence.clone(),
|
competence: competence,
|
||||||
possession: possession,
|
possession: possession,
|
||||||
attacker: attacker,
|
attacker: attacker,
|
||||||
defender: defender,
|
defender: defender,
|
||||||
targetToken: Targets.extractTokenData(target)
|
targetToken: Targets.extractTokenData(target)
|
||||||
};
|
};
|
||||||
RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker)
|
if (attacker.isCreatureEntite()) {
|
||||||
|
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
||||||
|
}
|
||||||
|
|
||||||
await RdDPossession.$rollAttaquePossession(attacker, rollData, isNouvelle);
|
await RdDPossession.$rollAttaquePossession(attacker, rollData, isNouvelle);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async onConjurerPossession(attacker, possession) {
|
static async onConjurerPossession(attacker, competence, possession) {
|
||||||
possession = duplicate(possession);
|
possession = duplicate(possession);
|
||||||
RdDPossession.$updateEtatPossession(possession)
|
RdDPossession.$updateEtatPossession(possession)
|
||||||
|
|
||||||
const defender = game.actors.get(possession.system.entite.actorid);
|
|
||||||
let rollData = {
|
let rollData = {
|
||||||
mode: "attaque",
|
mode: "possession",
|
||||||
isECNIDefender: true,
|
isECNIDefender: true,
|
||||||
|
competence: competence,
|
||||||
possession: possession,
|
possession: possession,
|
||||||
attacker: attacker,
|
attacker: attacker,
|
||||||
defender: defender,
|
defender: game.actors.get(possession.system.possesseurid)
|
||||||
};
|
};
|
||||||
RdDPossession.selectCompetenceDraconicOuPossession(rollData, attacker)
|
|
||||||
|
|
||||||
await RdDPossession.$rollAttaquePossession(attacker, rollData);
|
await RdDPossession.$rollAttaquePossession(attacker, rollData);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +71,7 @@ export class RdDPossession {
|
|||||||
static async onDefensePossession(attackerId, defenderId, possessionId) {
|
static async onDefensePossession(attackerId, defenderId, possessionId) {
|
||||||
let attacker = game.actors.get(attackerId)
|
let attacker = game.actors.get(attackerId)
|
||||||
let possession = attacker?.getPossession(possessionId)
|
let possession = attacker?.getPossession(possessionId)
|
||||||
defenderId = defenderId ?? possession?.system.entite.actorid ?? undefined
|
defenderId = defenderId ?? possession?.system.possesseurid ?? undefined
|
||||||
let defender = game.actors.get(defenderId)
|
let defender = game.actors.get(defenderId)
|
||||||
possession = possession ?? defender?.getPossession(possessionId) ?? undefined;
|
possession = possession ?? defender?.getPossession(possessionId) ?? undefined;
|
||||||
|
|
||||||
@ -83,30 +82,20 @@ export class RdDPossession {
|
|||||||
possession = duplicate(possession)
|
possession = duplicate(possession)
|
||||||
// Update for draconic roll
|
// Update for draconic roll
|
||||||
let rollData = {
|
let rollData = {
|
||||||
mode: "defense",
|
mode: "conjuration",
|
||||||
isECNIDefender: defender.type == "entite",
|
isECNIDefender: defender.type == "entite",
|
||||||
possession: possession,
|
possession: possession,
|
||||||
attacker: attacker,
|
attacker: attacker,
|
||||||
defender: defender,
|
defender: defender,
|
||||||
|
competence: defender.getDraconicOuPossession(),
|
||||||
|
selectedCarac: defender.system.carac.reve,
|
||||||
|
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: defender.getReveActuel() } }
|
||||||
}
|
}
|
||||||
RdDPossession.selectCompetenceDraconicOuPossession(rollData, defender)
|
rollData.competence.system.defaut_carac = 'reve-actuel'
|
||||||
rollData.diffLibre = RdDPossession.getInfoAttaque(rollData).diffLibre
|
|
||||||
|
|
||||||
await RdDPossession.$rollDefensePossession(defender, rollData);
|
await RdDPossession.$rollDefensePossession(defender, rollData);
|
||||||
}
|
}
|
||||||
|
|
||||||
static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
|
|
||||||
rollData.competence = rollingActor.getDraconicOuPossession();
|
|
||||||
if (rollingActor.isCreatureEntite()) {
|
|
||||||
RdDItemCompetenceCreature.setRollDataCreature(rollData)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rollData.selectedCarac = rollingActor.system.carac.reve
|
|
||||||
rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } }
|
|
||||||
rollData.competence.system.defaut_carac = 'reve-actuel'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) {
|
static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) {
|
||||||
const dialog = await RdDRoll.create(attacker, rollData,
|
const dialog = await RdDRoll.create(attacker, rollData,
|
||||||
@ -115,22 +104,21 @@ export class RdDPossession {
|
|||||||
name: 'jet-possession',
|
name: 'jet-possession',
|
||||||
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',
|
label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession',
|
||||||
callbacks: [
|
callbacks: [
|
||||||
{ action: async (r) => await RdDPossession.$onRollPossession(r, isNouvelle) },
|
{ condition: r => (r.rolled.isSuccess), action: async (r) => await RdDPossession.$onRollPossession(r, true, isNouvelle) },
|
||||||
|
{ condition: r => (r.rolled.isEchec), action: async (r) => await RdDPossession.$onRollPossession(r, false, isNouvelle) },
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
dialog.render(true);
|
dialog.render(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async $onRollPossession(rollData, isNouvelle = false) {
|
static async $onRollPossession(rollData, isSuccess, isNouvelle = false) {
|
||||||
rollData.possession.isSuccess = rollData.rolled.isSuccess;
|
rollData.possession.isSuccess = isSuccess;
|
||||||
RdDPossession.$updateEtatPossession(rollData.possession, rollData);
|
RdDPossession.$updateEtatPossession(rollData.possession);
|
||||||
if (isNouvelle) {
|
if (isNouvelle) {
|
||||||
// Creer la possession sur le defenseur
|
// Creer la possession sur le defenseur
|
||||||
await rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()])
|
rollData.defender.createEmbeddedDocuments('Item', [rollData.possession.toObject()])
|
||||||
}
|
}
|
||||||
const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid)
|
|
||||||
RdDPossession.storePossessionAttaque(possession, rollData)
|
|
||||||
await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html');
|
await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +127,7 @@ export class RdDPossession {
|
|||||||
const dialog = await RdDRoll.create(defender, rollData,
|
const dialog = await RdDRoll.create(defender, rollData,
|
||||||
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html' },
|
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html' },
|
||||||
{
|
{
|
||||||
name: 'possession',
|
name: 'conjurer',
|
||||||
label: 'Conjurer une Possession',
|
label: 'Conjurer une Possession',
|
||||||
callbacks: [
|
callbacks: [
|
||||||
{ action: async (r) => await RdDPossession.$onRollConjuration(r) }
|
{ action: async (r) => await RdDPossession.$onRollConjuration(r) }
|
||||||
@ -151,30 +139,23 @@ export class RdDPossession {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async $onRollConjuration(rollData) {
|
static async $onRollConjuration(rollData) {
|
||||||
let victime = game.actors.get(rollData.possession.system.victime.actorid)
|
let actor = game.actors.get(rollData.possession.system.possedeid)
|
||||||
let compteur = rollData.possession.system.compteur
|
|
||||||
if (!rollData.rolled.isSuccess) {
|
if (!rollData.rolled.isSuccess) {
|
||||||
if (rollData.isECNIDefender) {
|
if (rollData.isECNIDefender) {
|
||||||
compteur--
|
rollData.possession.system.compteur--
|
||||||
} else {
|
} else {
|
||||||
compteur++
|
rollData.possession.system.compteur++
|
||||||
}
|
}
|
||||||
|
let update = { _id: rollData.possession._id, "system.compteur": rollData.possession.system.compteur }
|
||||||
|
await actor.updateEmbeddedDocuments('Item', [update])
|
||||||
}
|
}
|
||||||
const possession = victime.getPossession(rollData.possession.system.possessionid)
|
|
||||||
await possession.update({
|
|
||||||
system: {
|
|
||||||
compteur: compteur,
|
|
||||||
entite: { diffLibre: 0, finesse: false },
|
|
||||||
victime: { diffLibre: 0, finesse: false }
|
|
||||||
}
|
|
||||||
})
|
|
||||||
rollData.possession = possession
|
|
||||||
RdDPossession.$updateEtatPossession(rollData.possession)
|
RdDPossession.$updateEtatPossession(rollData.possession)
|
||||||
|
|
||||||
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html')
|
await RdDResolutionTable.displayRollData(rollData,rollData.defender, 'chat-resultat-possession.html')
|
||||||
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
|
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
|
||||||
// conjuration
|
// conjuration
|
||||||
victime.deleteEmbeddedDocuments("Item", [rollData.possession._id])
|
actor.deleteEmbeddedDocuments("Item", [rollData.possession._id])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,42 +180,12 @@ export class RdDPossession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static isPossessionFinesse(rollData) {
|
|
||||||
return RdDPossession.getInfoAttaque(rollData).finesse
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static getInfoAttaque(rollData) {
|
|
||||||
return rollData.possession.system[rollData.isECNIDefender ? 'victime' : 'entite'];
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static isDefensePossession(rollData) {
|
|
||||||
return rollData.possession && rollData.mode == "defense"
|
|
||||||
}
|
|
||||||
/* -------------------------------------------- */
|
|
||||||
static storePossessionAttaque(possession, rollData = undefined) {
|
|
||||||
const attaquant = rollData?.isECNIDefender ? 'victime' : 'entite'
|
|
||||||
possession.update({
|
|
||||||
[`system.${attaquant}`]: {
|
|
||||||
diffLibre: rollData?.diffLibre ?? 0,
|
|
||||||
finesse: rollData?.rolled.isPart ?? false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async createPossession(attacker, defender) {
|
static async createPossession(attacker, defender) {
|
||||||
return await Item.create({
|
return await Item.create({
|
||||||
name: "Possession en cours de " + attacker.name, type: 'possession',
|
name: "Possession en cours de " + attacker.name, type: 'possession',
|
||||||
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
|
||||||
system: {
|
system: { description: "", typepossession: attacker.name, possede: false, possessionid: randomID(16), possesseurid: attacker.id, possedeid: defender.id, date: 0, compteur: 0 }
|
||||||
description: "", typepossession: attacker.name,
|
|
||||||
possede: false,
|
|
||||||
possessionid: randomID(16),
|
|
||||||
entite: { actorid: attacker.id },
|
|
||||||
victime: { actorid: defender.id },
|
|
||||||
compteur: 0
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
temporary: true
|
temporary: true
|
||||||
|
@ -91,17 +91,13 @@ export class RdDResolutionTable {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.html') {
|
static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.html') {
|
||||||
return await ChatUtility.createChatWithRollMode(RdDResolutionTable.actorChatName(actor), {
|
return await ChatUtility.createChatWithRollMode(actor?.userName ?? game.user.name, {
|
||||||
content: await RdDResolutionTable.buildRollDataHtml(rollData, template)
|
content: await RdDResolutionTable.buildRollDataHtml(rollData, actor, template)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static actorChatName(actor) {
|
|
||||||
return actor?.userName ?? game.user.name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async buildRollDataHtml(rollData, template = 'chat-resultat-general.html') {
|
static async buildRollDataHtml(rollData, actor, template = 'chat-resultat-general.html') {
|
||||||
rollData.show = rollData.show || {};
|
rollData.show = rollData.show || {};
|
||||||
return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/${template}`, rollData);
|
return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/${template}`, rollData);
|
||||||
}
|
}
|
||||||
@ -199,6 +195,17 @@ 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) {
|
||||||
@ -287,9 +294,12 @@ export class RdDResolutionTable {
|
|||||||
carac: carac,
|
carac: carac,
|
||||||
difficulte: level,
|
difficulte: level,
|
||||||
min: minLevel,
|
min: minLevel,
|
||||||
rows: Misc.intArray(minCarac, maxCarac+1),
|
rows: RdDResolutionTable.incrementalArray(minCarac, maxCarac),
|
||||||
cols: Misc.intArray(minLevel, maxLevel+1)
|
cols: RdDResolutionTable.incrementalArray(minLevel, maxLevel)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
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 = "entiteincarnee"
|
dialogConf.default = "cauchemar"
|
||||||
dialogConf.buttons = {
|
dialogConf.buttons = {
|
||||||
"entiteincarnee": { label: "Entité incarnée", callback: html => this.performEncaisser("entiteincarnee") }
|
"cauchemar": { label: "Cauchemar", callback: html => this.performEncaisser("cauchemar") }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,6 +70,7 @@ 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.isAgiliteOuDerobee(rollData.selectedCarac));
|
HtmlUtility._showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerivee(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(".divAppelAuMoral"), 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);
|
||||||
|
|
||||||
// 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,25 +1,7 @@
|
|||||||
import { DialogSplitItem } from "./dialog-split-item.js";
|
import { DialogSplitItem } from "./dialog-split-item.js";
|
||||||
import { RdDItem } from "./item.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))
|
||||||
}
|
}
|
||||||
@ -37,11 +19,8 @@ export class RdDSheetUtility {
|
|||||||
return $(event.currentTarget)?.parents(".item");
|
return $(event.currentTarget)?.parents(".item");
|
||||||
}
|
}
|
||||||
|
|
||||||
static async prepareItemDropParameters(destItemId, actor, dragData, objetVersConteneur) {
|
static prepareItemDropParameters(destItemId, actor, dragData, objetVersConteneur) {
|
||||||
let item = fromUuidSync(dragData.uuid);
|
const item = fromUuidSync(dragData.uuid)
|
||||||
if (item.pack && !item.system) {
|
|
||||||
item = await RdDItem.getCorrespondingItem(item);
|
|
||||||
}
|
|
||||||
if (actor.canReceive(item)) {
|
if (actor.canReceive(item)) {
|
||||||
return {
|
return {
|
||||||
destId: destItemId,
|
destId: destItemId,
|
||||||
|
@ -15,8 +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/rencontre.js";
|
import { RdDRencontre } from "./item-rencontre.js";
|
||||||
import { RdDTimestamp } from "./time/rdd-timestamp.js";
|
import { RdDCalendrier } from "./rdd-calendrier.js";
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|
||||||
@ -207,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) => {
|
||||||
@ -245,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;
|
||||||
@ -284,12 +284,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async onActionRencontre(action, tmr, rencontre) {
|
async onActionRencontre(action, tmr) {
|
||||||
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();
|
||||||
@ -593,7 +588,6 @@ 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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -804,21 +798,19 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
async declencheSortEnReserve(coord) {
|
async declencheSortEnReserve(coord) {
|
||||||
const sorts = this.getSortsReserve(coord);
|
let 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;
|
||||||
}
|
}
|
||||||
const reserveSecurite = EffetsDraconiques.isReserveEnSecurite(this.actor);
|
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) &&
|
||||||
const reserveExtensible = this.isReserveExtensible(coord);
|
(EffetsDraconiques.isReserveEnSecurite(this.actor) || this.isReserveExtensible(coord))) {
|
||||||
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) && (reserveSecurite || reserveExtensible)) {
|
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>";
|
||||||
const msg = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-demande-declencher-sort.hbs`, {
|
for (let sort of sorts) {
|
||||||
actor: this.actor,
|
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>`;
|
||||||
sorts: sorts,
|
}
|
||||||
coord: coord,
|
msg += "</ol>";
|
||||||
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)
|
||||||
@ -848,7 +840,7 @@ export class RdDTMRDialog extends Dialog {
|
|||||||
async processSortReserve(sortReserve) {
|
async processSortReserve(sortReserve) {
|
||||||
await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]);
|
await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]);
|
||||||
console.log("declencheSortEnReserve", sortReserve);
|
console.log("declencheSortEnReserve", sortReserve);
|
||||||
const heureCible = RdDTimestamp.definition(sortReserve.system.heurecible).label;
|
const heureCible = RdDCalendrier.getSigneAs('label', sortReserve.system.heurecible);
|
||||||
this._tellToUserAndGM(`Vous avez déclenché
|
this._tellToUserAndGM(`Vous avez déclenché
|
||||||
${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"}
|
${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"}
|
||||||
en réserve <strong>${sortReserve.name}</strong>
|
en réserve <strong>${sortReserve.name}</strong>
|
||||||
|
@ -29,13 +29,12 @@ 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.rencontre)
|
this.tmrApp.onActionRencontre(action, this.tmr)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
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 {
|
||||||
@ -19,39 +18,29 @@ export class RdDTokenHud {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async addExtensionHud(app, html, tokenId, isCombat) {
|
static async addExtensionHud(app, html, tokenId) {
|
||||||
|
|
||||||
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;
|
||||||
}
|
}
|
||||||
let actions = RdDCombatManager.listActionsCombat(combatant);
|
app.hasExtension = true;
|
||||||
// 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, actions,
|
combatant: combatant,
|
||||||
|
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,
|
||||||
@ -62,47 +51,26 @@ 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 = hudData.actions[index];
|
let action = actionsCombat[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 = hudData.actions[actionIndex];
|
const action = actionsCombat[actionIndex];
|
||||||
const possession = action.action == 'possession' ? combatant.actor.getPossession(action.system.possessionid) : undefined;
|
if (action.action == 'conjurer') {
|
||||||
if (possession) {
|
actor.conjurerPossession(actor.getPossession(action.system.possessionid));
|
||||||
combatant.actor.conjurerPossession(possession);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
combatant.actor.rollArme(action);
|
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);
|
||||||
@ -115,17 +83,16 @@ 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(() => RdDTokenHud.addExtensionHud(app, html, tokenId), 200);
|
setTimeout(function () { RdDTokenHud.addExtensionHud(app, html, tokenId) }, 200);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
const isCombat = controlIconCombat[0].className.includes('active');
|
if (controlIconCombat.length>0 && controlIconCombat[0].className.includes('active')) {
|
||||||
RdDTokenHud.addExtensionHud(app, html, tokenId, isCombat);
|
RdDTokenHud.addExtensionHud(app, html, tokenId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,6 +111,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,22 +8,21 @@ 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 { RdDCalendrier } from "./rdd-calendrier.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 "./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 = Misc.intArray(0, -11);
|
const difficultesLibres = [0, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10];
|
||||||
const ajustementsConditions = Misc.intArray(-10, 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 ajustementsEncaissement = Misc.intArray(-10, 26);
|
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];
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
function _buildAllSegmentsFatigue(max) {
|
function _buildAllSegmentsFatigue(max) {
|
||||||
@ -68,31 +67,38 @@ 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", gravite: -1},
|
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 },
|
||||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0},
|
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
||||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2},
|
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 },
|
||||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4},
|
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", eraflures: 0, legeres: 0, graves: 1, critiques: 0 },
|
||||||
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6},
|
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", eraflures: 0, legeres: 0, graves: 0, critiques: 1 },
|
||||||
],
|
],
|
||||||
"non-mortel": [
|
"non-mortel": [
|
||||||
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1},
|
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 },
|
||||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
|
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
||||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
|
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
||||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 },
|
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 },
|
||||||
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 },
|
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", eraflures: 0, legeres: 1, graves: 0, critiques: 0 },
|
||||||
],
|
],
|
||||||
"entiteincarnee": [
|
"cauchemar": [
|
||||||
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1},
|
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", eraflures: 0, legeres: 0, graves: 0, critiques: 0 },
|
||||||
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0},
|
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
||||||
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
|
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
||||||
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 0 },
|
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
||||||
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 0 },
|
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", eraflures: 1, legeres: 0, graves: 0, critiques: 0 },
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -134,10 +140,9 @@ 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.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/blessure.html',
|
||||||
'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',
|
||||||
@ -145,7 +150,6 @@ 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',
|
||||||
@ -166,28 +170,50 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-animaux.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-animaux.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-suivants.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-suivants.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.html',
|
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.html',
|
|
||||||
//Items
|
//Items
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/boutons-comestible.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item/boutons-comestible.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/temporel.hbs',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.html',
|
'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
|
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-arme-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-armure-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-objet-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-conteneur-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-sort-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-herbe-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-ingredient-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-faune-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-livre-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-tache-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-potion-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-rencontre-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-souffle-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-tarot-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-tete-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-ombre-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-monnaie-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-meditation-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-nourritureboisson-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-signedraconique-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-possession-sheet.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/item-extraitpoetique-sheet.html',
|
||||||
// partial enums
|
// partial enums
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categories.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-competence.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
|
||||||
|
'systems/foundryvtt-reve-de-dragon/templates/enum-herbesoin-ingredient.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html',
|
||||||
@ -195,14 +221,8 @@ export class RdDUtility {
|
|||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
|
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/enum-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/periodicite.hbs',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
|
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html',
|
'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html',
|
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html',
|
||||||
@ -231,10 +251,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/sommeil/sommeil-actor-moral.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-gardien.hbs',
|
// Calendrier
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-joueur.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/calendar-template.html',
|
||||||
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-theme.hbs',
|
'systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html',
|
||||||
// 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',
|
||||||
@ -243,6 +263,20 @@ 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',
|
||||||
@ -256,27 +290,18 @@ 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() ?? '');
|
Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? 'NULL');
|
||||||
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('buildLigneInventaire', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildLigneInventaire(item, options)); });
|
Handlebars.registerHelper('buildConteneur', (objet) => { return new Handlebars.SafeString(RdDUtility.buildConteneur(objet)); });
|
||||||
Handlebars.registerHelper('buildInventaireConteneur', (actorId, itemId, options) => { return new Handlebars.SafeString(RdDUtility.buildInventaireConteneur(actorId, itemId, options)); });
|
Handlebars.registerHelper('buildContenu', (objet) => { return new Handlebars.SafeString(RdDUtility.buildContenu(objet, 1, true)); });
|
||||||
Handlebars.registerHelper('buildContenuConteneur', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildContenuConteneur(item, options)); });
|
|
||||||
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));
|
||||||
Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type));
|
Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type));
|
||||||
Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
|
Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
|
||||||
|
Handlebars.registerHelper('signeHeure', (key, heure) => RdDCalendrier.getSigneAs(key, heure));
|
||||||
Handlebars.registerHelper('timestamp-imgSigneHeure', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigneHeure(heure)) });
|
|
||||||
Handlebars.registerHelper('timestamp-imgSigne', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigne(heure)) });
|
|
||||||
Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier());
|
|
||||||
Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree());
|
|
||||||
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());
|
|
||||||
|
|
||||||
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
|
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
|
||||||
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
|
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionelles.isUsing(option));
|
||||||
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
|
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
|
||||||
@ -284,21 +309,68 @@ 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('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
|
Handlebars.registerHelper('getFrequenceRarete', (rarete, field) => Environnement.getFrequenceRarete(rarete, field));
|
||||||
|
|
||||||
Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic));
|
|
||||||
|
|
||||||
return loadTemplates(templatePaths);
|
return loadTemplates(templatePaths);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getItem(itemId, actorId = undefined) {
|
static getItem(itemId, actorId = undefined) {
|
||||||
return actorId ? game.actors.get(actorId)?.getItem(itemId) : game.items.get(itemId);
|
return actorId ? game.actors.get(actorId)?.getObjet(itemId) : game.items.get(itemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
static linkCompendium(pack, id, name) {
|
static linkCompendium(pack, id, name) {
|
||||||
return `@Compendium[${pack}.${id}]{${name}}`;
|
return `@Compendium[${pack}.${id}]{${name}}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async creerObjet(actorSheet) {
|
||||||
|
let itemType = $(".item-type").val();
|
||||||
|
await actorSheet.createItem('Nouveau ' + itemType, itemType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async selectObjetType(actorSheet) {
|
||||||
|
let typeObjets = RdDItem.getItemTypesInventaire();
|
||||||
|
let options = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
|
||||||
|
for (let typeName of typeObjets) {
|
||||||
|
options += `<option value="${typeName}">${typeName}</option>`
|
||||||
|
}
|
||||||
|
options += '</select>';
|
||||||
|
let d = new Dialog({
|
||||||
|
title: "Créer un équipement",
|
||||||
|
content: options,
|
||||||
|
buttons: {
|
||||||
|
one: {
|
||||||
|
icon: '<i class="fas fa-check"></i>',
|
||||||
|
label: "Créer l'objet",
|
||||||
|
callback: () => this.creerObjet(actorSheet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
d.render(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static async selectTypeOeuvre(actorSheet) {
|
||||||
|
let typeObjets = RdDItem.getTypesOeuvres();
|
||||||
|
let options = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`;
|
||||||
|
for (let typeName of typeObjets) {
|
||||||
|
options += `<option value="${typeName}">${typeName}</option>`
|
||||||
|
}
|
||||||
|
options += '</select>';
|
||||||
|
let d = new Dialog({
|
||||||
|
title: "Créer un équipement",
|
||||||
|
content: options,
|
||||||
|
buttons: {
|
||||||
|
one: {
|
||||||
|
icon: '<i class="fas fa-check"></i>',
|
||||||
|
label: "Créer l'objet",
|
||||||
|
callback: () => this.creerObjet(actorSheet)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
d.render(true);
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static buildListOptions(min, max) {
|
static buildListOptions(min, max) {
|
||||||
let options = ""
|
let options = ""
|
||||||
@ -339,13 +411,75 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static buildArbreDeConteneurs(conteneurs, inventaires) {
|
static filterItemsPerTypeForSheet(formData, itemTypes) {
|
||||||
|
|
||||||
|
RdDUtility.filterEquipementParType(formData, itemTypes);
|
||||||
|
|
||||||
|
formData.sorts = this.arrayOrEmpty(itemTypes['sort']);
|
||||||
|
formData.rencontres = this.arrayOrEmpty(itemTypes['rencontre']);
|
||||||
|
formData.casestmr = this.arrayOrEmpty(itemTypes['casetmr']);
|
||||||
|
formData.signesdraconiques = this.arrayOrEmpty(itemTypes['signedraconique']);
|
||||||
|
formData.queues = this.arrayOrEmpty(itemTypes['queue']);
|
||||||
|
formData.souffles = this.arrayOrEmpty(itemTypes['souffle']);
|
||||||
|
formData.ombres = this.arrayOrEmpty(itemTypes['ombre']);
|
||||||
|
formData.tetes = this.arrayOrEmpty(itemTypes['tete']);
|
||||||
|
formData.taches = this.arrayOrEmpty(itemTypes['tache']);
|
||||||
|
formData.meditations = this.arrayOrEmpty(itemTypes['meditation']);
|
||||||
|
formData.chants = this.arrayOrEmpty(itemTypes['chant']);
|
||||||
|
formData.danses = this.arrayOrEmpty(itemTypes['danse']);
|
||||||
|
formData.musiques = this.arrayOrEmpty(itemTypes['musique']);
|
||||||
|
formData.oeuvres = this.arrayOrEmpty(itemTypes['oeuvre']);
|
||||||
|
formData.jeux = this.arrayOrEmpty(itemTypes['jeu']);
|
||||||
|
|
||||||
|
formData.recettescuisine = this.arrayOrEmpty(itemTypes['recettecuisine']);
|
||||||
|
formData.recettesAlchimiques = this.arrayOrEmpty(itemTypes['recettealchimique']);
|
||||||
|
formData.maladies = this.arrayOrEmpty(itemTypes['maladie']);
|
||||||
|
formData.poisons = this.arrayOrEmpty(itemTypes['poison']);
|
||||||
|
formData.possessions = this.arrayOrEmpty(itemTypes['possession']);
|
||||||
|
formData.maladiesPoisons = formData.maladies.concat(formData.poisons);
|
||||||
|
formData.competences = (itemTypes['competence'] ?? []).concat(itemTypes['competencecreature'] ?? []);
|
||||||
|
formData.sortsReserve = this.arrayOrEmpty(itemTypes['sortreserve']);
|
||||||
|
}
|
||||||
|
|
||||||
|
static filterEquipementParType(formData, itemTypes) {
|
||||||
|
formData.conteneurs = this.arrayOrEmpty(itemTypes['conteneur']);
|
||||||
|
|
||||||
|
formData.materiel = this.arrayOrEmpty(itemTypes['objet']);
|
||||||
|
formData.armes = this.arrayOrEmpty(itemTypes['arme']);
|
||||||
|
formData.armures = this.arrayOrEmpty(itemTypes['armure']);
|
||||||
|
formData.munitions = this.arrayOrEmpty(itemTypes['munition']);
|
||||||
|
formData.livres = this.arrayOrEmpty(itemTypes['livre']);
|
||||||
|
formData.potions = this.arrayOrEmpty(itemTypes['potion']);
|
||||||
|
formData.ingredients = this.arrayOrEmpty(itemTypes['ingredient']);
|
||||||
|
formData.faunes = this.arrayOrEmpty(itemTypes['faune']);
|
||||||
|
formData.herbes = this.arrayOrEmpty(itemTypes['herbe']);
|
||||||
|
formData.monnaie = this.arrayOrEmpty(itemTypes['monnaie']).sort(Monnaie.triValeurEntiere());
|
||||||
|
formData.nourritureboissons = this.arrayOrEmpty(itemTypes['nourritureboisson']);
|
||||||
|
formData.gemmes = this.arrayOrEmpty(itemTypes['gemme']);
|
||||||
|
|
||||||
|
formData.objets = formData.conteneurs
|
||||||
|
.concat(formData.materiel)
|
||||||
|
.concat(formData.armes)
|
||||||
|
.concat(formData.armures)
|
||||||
|
.concat(formData.munitions)
|
||||||
|
.concat(formData.livres)
|
||||||
|
.concat(formData.potions)
|
||||||
|
.concat(formData.ingredients)
|
||||||
|
.concat(formData.herbes)
|
||||||
|
.concat(formData.faunes)
|
||||||
|
.concat(formData.monnaie)
|
||||||
|
.concat(formData.nourritureboissons)
|
||||||
|
.concat(formData.gemmes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -------------------------------------------- */
|
||||||
|
static buildArbreDeConteneurs(conteneurs, objets) {
|
||||||
let objetVersConteneur = {};
|
let objetVersConteneur = {};
|
||||||
// Attribution des objets aux conteneurs
|
// Attribution des objets aux conteneurs
|
||||||
for (let conteneur of conteneurs) {
|
for (let conteneur of conteneurs) {
|
||||||
conteneur.subItems = [];
|
conteneur.subItems = [];
|
||||||
for (let id of conteneur.system.contenu ?? []) {
|
for (let id of conteneur.system.contenu ?? []) {
|
||||||
let objet = inventaires.find(objet => (id == objet._id));
|
let objet = objets.find(objet => (id == objet._id));
|
||||||
if (objet) {
|
if (objet) {
|
||||||
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template
|
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template
|
||||||
objetVersConteneur[id] = conteneur._id;
|
objetVersConteneur[id] = conteneur._id;
|
||||||
@ -354,20 +488,20 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (let conteneur of conteneurs) {
|
for (let conteneur of conteneurs) {
|
||||||
conteneur.system.encTotal = RdDUtility.calculEncContenu(conteneur, inventaires);
|
conteneur.system.encTotal = RdDUtility.calculEncContenu(conteneur, objets);
|
||||||
}
|
}
|
||||||
return objetVersConteneur;
|
return objetVersConteneur;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static calculEncContenu(conteneur, inventaires) {
|
static calculEncContenu(conteneur, objets) {
|
||||||
const contenus = (conteneur.system.contenu ?? []).filter(id => id != undefined)
|
const contenus = (conteneur.system.contenu ?? []).filter(id => id != undefined)
|
||||||
.map(id => inventaires.find(it => (id == it.id)))
|
.map(id => objets.find(it => (id == it.id)))
|
||||||
.filter(it => it);
|
.filter(it => it);
|
||||||
let enc = Number(conteneur.system.encombrement ?? 0) * Number(conteneur.system.quantite ?? 1);
|
let enc = Number(conteneur.system.encombrement ?? 0) * Number(conteneur.system.quantite ?? 1);
|
||||||
for (let contenu of contenus) {
|
for (let contenu of contenus) {
|
||||||
if (contenu.type == 'conteneur') {
|
if (contenu.type == 'conteneur') {
|
||||||
enc += RdDUtility.calculEncContenu(contenu, inventaires);
|
enc += RdDUtility.calculEncContenu(contenu, objets);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
enc += Number(contenu.system.encombrement ?? 0) * Number(contenu.system.quantite ?? 1)
|
enc += Number(contenu.system.encombrement ?? 0) * Number(contenu.system.quantite ?? 1)
|
||||||
@ -382,64 +516,35 @@ 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 buildLigneInventaire(item, options = {}, optionsArbre = { ouvert: false, profondeur: 1 }) {
|
static buildConteneur(objet, profondeur) {
|
||||||
RdDUtility.prepareOptionsArbreInventaire(item, optionsArbre);
|
if (!profondeur) profondeur = 1;
|
||||||
|
objet.niveau = profondeur;
|
||||||
const isConteneur = item.type == 'conteneur';
|
const isConteneur = objet.type == 'conteneur';
|
||||||
const inventaire = {
|
const isOuvert = isConteneur && this.getAfficheContenu(objet._id);
|
||||||
item: item,
|
const isVide = isConteneur && objet.system.contenu.length == 0;
|
||||||
vide: isConteneur && item.system.contenu.length == 0,
|
const conteneur = Handlebars.partials['systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html']({
|
||||||
ouvert: isConteneur && RdDUtility.getAfficheContenu(item._id),
|
item: objet,
|
||||||
options: options
|
vide: isVide,
|
||||||
};
|
ouvert: isOuvert
|
||||||
optionsArbre.ouvert = inventaire.ouvert
|
});
|
||||||
const ligneObjet = Handlebars.partials[optionsArbre.templateItem](inventaire);
|
const contenu = isConteneur ? RdDUtility.buildContenu(objet, profondeur, isOuvert) : '';
|
||||||
if (isConteneur) {
|
return conteneur + contenu;
|
||||||
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 buildContenuConteneur(conteneur, options = {}, optionsArbre = {}) {
|
static buildContenu(objet, profondeur, afficherContenu) {
|
||||||
RdDUtility.prepareOptionsArbreInventaire(conteneur, optionsArbre);
|
if (!profondeur) profondeur = 1;
|
||||||
const display = optionsArbre.ouvert ? 'item-display-show' : 'item-display-hide';
|
objet.niveau = profondeur;
|
||||||
const profondeur = optionsArbre.profondeur;
|
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)}'>`;
|
||||||
optionsArbre.profondeur++;
|
for (let subItem of objet.subItems) {
|
||||||
const lignesContenu = conteneur.subItems.sort(Misc.ascending(it => it.name))
|
strContenu += this.buildConteneur(subItem, profondeur + 1);
|
||||||
.map(contenu => this.buildLigneInventaire(contenu, options, optionsArbre));
|
}
|
||||||
|
return strContenu + "</ul>";
|
||||||
return `<ul class='item-list alterne-list ${display} list-item-margin${Math.min(profondeur, 6)}'>`
|
|
||||||
+ lignesContenu.reduce(Misc.joining(''), '')
|
|
||||||
+ "</ul>";
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
@ -456,6 +561,10 @@ 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);
|
||||||
@ -596,10 +705,17 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -652,6 +768,8 @@ export class RdDUtility {
|
|||||||
switch (sockmsg.msg) {
|
switch (sockmsg.msg) {
|
||||||
case "msg_gm_chat_message":
|
case "msg_gm_chat_message":
|
||||||
return ChatUtility.handleGMChatMessage(sockmsg.data);
|
return ChatUtility.handleGMChatMessage(sockmsg.data);
|
||||||
|
case "msg_sync_time":
|
||||||
|
return game.system.rdd.calendrier.syncPlayerTime(sockmsg.data);
|
||||||
case "msg_request_nombre_astral":
|
case "msg_request_nombre_astral":
|
||||||
return game.system.rdd.calendrier.requestNombreAstral(sockmsg.data);
|
return game.system.rdd.calendrier.requestNombreAstral(sockmsg.data);
|
||||||
case "msg_response_nombre_astral":
|
case "msg_response_nombre_astral":
|
||||||
@ -668,7 +786,6 @@ export class RdDUtility {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async chatListeners(html) {
|
static async chatListeners(html) {
|
||||||
RdDCombat.registerChatCallbacks(html);
|
RdDCombat.registerChatCallbacks(html);
|
||||||
RdDEmpoignade.registerChatCallbacks(html);
|
|
||||||
|
|
||||||
// Gestion spécifique message passeurs
|
// Gestion spécifique message passeurs
|
||||||
html.on("click", '.tmr-passeur-coord a', event => {
|
html.on("click", '.tmr-passeur-coord a', event => {
|
||||||
@ -697,7 +814,7 @@ export class RdDUtility {
|
|||||||
|
|
||||||
// gestion bouton tchat Acheter
|
// gestion bouton tchat Acheter
|
||||||
html.on("click", '.button-acheter', event => {
|
html.on("click", '.button-acheter', event => {
|
||||||
const venteData = DialogItemAchat.preparerAchat(event.currentTarget);
|
const venteData = DialogItemAchat.venteData(event.currentTarget);
|
||||||
if (venteData) {
|
if (venteData) {
|
||||||
DialogItemAchat.onAcheter(venteData);
|
DialogItemAchat.onAcheter(venteData);
|
||||||
}
|
}
|
||||||
@ -713,18 +830,6 @@ export class RdDUtility {
|
|||||||
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget));
|
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
html.on("click", '.rdd-world-content-link', async event => {
|
|
||||||
const htmlElement = html.find(event.currentTarget);
|
|
||||||
const id = htmlElement?.data("id");
|
|
||||||
const doctype = htmlElement?.data("doctype");
|
|
||||||
switch (doctype ?? 'Item') {
|
|
||||||
case 'Actor':
|
|
||||||
return game.actors.get(id)?.sheet.render(true);
|
|
||||||
case 'Item':
|
|
||||||
default:
|
|
||||||
return game.items.get(id)?.sheet.render(true);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static findChatMessageId(current) {
|
static findChatMessageId(current) {
|
||||||
@ -800,7 +905,7 @@ export class RdDUtility {
|
|||||||
if (p2[2] == 'd') deniers += Number(p2[1]);
|
if (p2[2] == 'd') deniers += Number(p2[1]);
|
||||||
if (p2[2] == 's') sols += Number(p2[1]);
|
if (p2[2] == 's') sols += Number(p2[1]);
|
||||||
|
|
||||||
let sommeAPayer = sols + deniers / 100;
|
let sommeAPayer = sols + deniers/100;
|
||||||
let msgPayer = `La somme de ${sols} Sols et ${deniers} Deniers est à payer<br>
|
let msgPayer = `La somme de ${sols} Sols et ${deniers} Deniers est à payer<br>
|
||||||
<a class='payer-button chat-card-button' data-somme-a-payer='${sommeAPayer}'>Payer</a>`
|
<a class='payer-button chat-card-button' data-somme-a-payer='${sommeAPayer}'>Payer</a>`
|
||||||
ChatMessage.create({ content: msgPayer });
|
ChatMessage.create({ content: msgPayer });
|
||||||
@ -827,18 +932,22 @@ export class RdDUtility {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete, onSuppression = ()=>{}) {
|
static confirmerSuppressionSubacteur(sheet, subActor, htmlToDelete) {
|
||||||
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: onSuppression
|
onAction: () => {
|
||||||
|
console.log('Delete : ', subActor.id);
|
||||||
|
sheet.actor.removeSubacteur(subActor.id);
|
||||||
|
RdDUtility.slideOnDelete(sheet, htmlToDelete);
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static async confirmActorItemDelete(sheet, item, htmlToDelete) {
|
static async confirmerSuppressionItem(sheet, item, htmlToDelete) {
|
||||||
const itemId = item.id;
|
const itemId = item.id;
|
||||||
const confirmationSuppression = {
|
const confirmationSuppression = {
|
||||||
settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(),
|
settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(),
|
||||||
@ -879,10 +988,10 @@ export class RdDUtility {
|
|||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
static afficherHeuresChanceMalchance(heureNaissance) {
|
static afficherHeuresChanceMalchance(heureNaissance) {
|
||||||
if (game.user.isGM) {
|
if (game.user.isGM) {
|
||||||
const heure = RdDTimestamp.findHeure(heureNaissance - 1);
|
let heure = game.system.rdd.calendrier.findHeure(heureNaissance);
|
||||||
if (heureNaissance && heure) {
|
if (heureNaissance && heure) {
|
||||||
let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance);
|
let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance);
|
||||||
const current = game.system.rdd.calendrier.heureCourante();
|
const current = game.system.rdd.calendrier.findHeure(game.system.rdd.calendrier.getCurrentHeure());
|
||||||
ChatMessage.create({
|
ChatMessage.create({
|
||||||
content: `A l'heure de <strong>${current.label}</strong>, le modificateur de Chance/Malchance est de <strong>${Misc.toSignedString(ajustement)}</strong> pour l'heure de naissance <strong>${heure.label}</strong>.`,
|
content: `A l'heure de <strong>${current.label}</strong>, le modificateur de Chance/Malchance est de <strong>${Misc.toSignedString(ajustement)}</strong> pour l'heure de naissance <strong>${heure.label}</strong>.`,
|
||||||
whisper: ChatMessage.getWhisperRecipients("GM")
|
whisper: ChatMessage.getWhisperRecipients("GM")
|
||||||
|
@ -5,7 +5,6 @@ import { RdDItemSort } from "./item-sort.js";
|
|||||||
import { Misc } from "./misc.js";
|
import { Misc } from "./misc.js";
|
||||||
import { RdDBonus } from "./rdd-bonus.js";
|
import { RdDBonus } from "./rdd-bonus.js";
|
||||||
import { RdDCarac } from "./rdd-carac.js";
|
import { RdDCarac } from "./rdd-carac.js";
|
||||||
import { RdDPossession } from "./rdd-possession.js";
|
|
||||||
import { RdDUtility } from "./rdd-utility.js";
|
import { RdDUtility } from "./rdd-utility.js";
|
||||||
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
import { ReglesOptionelles } from "./settings/regles-optionelles.js";
|
||||||
|
|
||||||
@ -31,7 +30,7 @@ export const referenceAjustements = {
|
|||||||
},
|
},
|
||||||
diffLibre: {
|
diffLibre: {
|
||||||
isUsed: (rollData, actor) => rollData.diffLibre != undefined,
|
isUsed: (rollData, actor) => rollData.diffLibre != undefined,
|
||||||
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ?? RdDPossession.isDefensePossession(rollData) ? 'Imposée' : 'Libre',
|
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ? 'Imposée' : 'Libre',
|
||||||
getValue: (rollData, actor) => rollData.selectedSort
|
getValue: (rollData, actor) => rollData.selectedSort
|
||||||
? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre)
|
? RdDItemSort.getDifficulte(rollData.selectedSort, rollData.diffLibre)
|
||||||
: rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0
|
: rollData.diffLibre ?? rollData.competence?.system.default_diffLibre ?? 0
|
||||||
@ -52,19 +51,19 @@ export const referenceAjustements = {
|
|||||||
getValue: (rollData, actor) => RdDBonus.find(rollData.surpriseDefenseur).attaque,
|
getValue: (rollData, actor) => RdDBonus.find(rollData.surpriseDefenseur).attaque,
|
||||||
},
|
},
|
||||||
etat: {
|
etat: {
|
||||||
isUsed: (rollData, actor) => !RollDataAjustements.isIgnoreEtatGeneral(rollData),
|
isUsed: (rollData, actor) => !RdDCarac.isIgnoreEtatGeneral(rollData),
|
||||||
getLabel: (rollData, actor) => 'Etat général',
|
getLabel: (rollData, actor) => 'Etat général',
|
||||||
getValue: (rollData, actor) => actor.getEtatGeneral({ ethylisme: rollData.forceAlcool != undefined })
|
getValue: (rollData, actor) => actor.getEtatGeneral({ ethylisme: rollData.forceAlcool != undefined })
|
||||||
},
|
},
|
||||||
malusArmure: {
|
malusArmure: {
|
||||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac),
|
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac),
|
||||||
isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac),
|
isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(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.isAgiliteOuDerobee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
||||||
isUsed: (rollData, actor) => !rollData.oeuvre && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) && rollData.use.encTotal,
|
isUsed: (rollData, actor) => !rollData.oeuvre && RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) && rollData.use.encTotal,
|
||||||
getLabel: (rollData, actor) => 'Encombrement total',
|
getLabel: (rollData, actor) => 'Encombrement total',
|
||||||
getValue: (rollData, actor) => -actor.getEncTotal()
|
getValue: (rollData, actor) => -actor.getEncTotal()
|
||||||
},
|
},
|
||||||
@ -140,12 +139,6 @@ 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,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,11 +171,4 @@ export class RollDataAjustements {
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isIgnoreEtatGeneral(rollData) {
|
|
||||||
const selectedCarac = rollData.selectedCarac;
|
|
||||||
return !selectedCarac ||
|
|
||||||
rollData.ethylisme ||
|
|
||||||
RdDCarac.isChance(selectedCarac) ||
|
|
||||||
(RdDCarac.isReve(selectedCarac) && !rollData.competence);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,6 @@ 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,16 +52,12 @@ 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 [];
|
||||||
@ -91,11 +87,6 @@ export class SystemCompendiums extends FormApplication {
|
|||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
static async loadDocument(document) {
|
|
||||||
const pack = game.packs.get(document.pack);
|
|
||||||
return await pack.getDocument(document.id ?? document._id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static async getItems(compendium, itemType = undefined) {
|
static async getItems(compendium, itemType = undefined) {
|
||||||
const items = await SystemCompendiums.getPackContent(compendium, 'Item');
|
const items = await SystemCompendiums.getPackContent(compendium, 'Item');
|
||||||
return (itemType ? items.filter(it => it.type == itemType) : items);
|
return (itemType ? items.filter(it => it.type == itemType) : items);
|
||||||
@ -181,7 +172,7 @@ export class SystemCompendiums extends FormApplication {
|
|||||||
*/
|
*/
|
||||||
export class CompendiumTable {
|
export class CompendiumTable {
|
||||||
|
|
||||||
constructor(compendium, type, subTypes = undefined, sorting = undefined) {
|
constructor(compendium, type, subTypes, sorting = undefined) {
|
||||||
this.compendium = compendium;
|
this.compendium = compendium;
|
||||||
this.type = type;
|
this.type = type;
|
||||||
this.subTypes = subTypes;
|
this.subTypes = subTypes;
|
||||||
@ -191,13 +182,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 || this.subTypes.includes(it.type)) && itemFrequence(it) > 0 && filter(it),
|
it => this.subTypes.includes(it.type) && 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(itemFrequence, filter);
|
const elements = await this.getContent(filter, itemFrequence);
|
||||||
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
|
return CompendiumTableHelpers.buildTable(elements, itemFrequence);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -229,23 +220,9 @@ export class CompendiumTableHelpers {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
static concatTables(...tables) {
|
static async getRandom(table, type, subTypes, forcedRoll = undefined, localisation = undefined) {
|
||||||
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) {
|
||||||
const typeName = Misc.typeName(type, subTypes[0]);
|
ui.notifications.warn(`Aucun ${Misc.typeName(type, subTypes[0])} trouvé dans ${localisation ?? ' les compendiums'}`);
|
||||||
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);
|
||||||
@ -278,7 +255,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 ?? 'objet'),
|
typeName: Misc.typeName(type, row.document.type),
|
||||||
isGM: game.user.isGM,
|
isGM: game.user.isGM,
|
||||||
});
|
});
|
||||||
const messageData = {
|
const messageData = {
|
||||||
|