Compare commits

...

65 Commits

Author SHA1 Message Date
uberwald 80719d8c15 Merge pull request '## 11.2.20 - Le soulagement d'Akarlikarlikar' (#698) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #698
2024-05-13 17:24:51 +02:00
Vincent Vandemeulebrouck 5c59f76c17 Version 11.2.20 2024-05-13 01:58:06 +02:00
Vincent Vandemeulebrouck 65525cfd79 Correction récupération seuil
La récupération de seuil sur Rêve de Dragon était empéchée
par la gestion d'expérience quand aucune expérience n'était
gagnée.

Le même problème pouvait arriver pour d'autres raisons.
2024-05-13 01:58:06 +02:00
Vincent Vandemeulebrouck 042f5d0f69 Cleanup Promise.all pour multi async 2024-05-13 01:50:22 +02:00
Vincent Vandemeulebrouck 19dd3b540c Astrologie: garder toutes les lectures d'un acteur 2024-05-13 01:50:21 +02:00
Vincent Vandemeulebrouck 611b57c149 Adaptation des encaissement alternatifs
Les encaissement alternatifs fonctionnent avec la validation
d'encaissement par le MJ.

- l'ajout de la difficulté d'attaque au dégâts est indiqué dans
les bonus de dégâts
- pour les minimums sur les dés d'encaissement, si le MJ remplace
le jet, les minimums sont alors ignorés.
2024-05-13 01:50:21 +02:00
Vincent Vandemeulebrouck fedf8f3b29 Fix: accorder entités x2 si validation GR
Les entités pouvaient être accordées 2 fois en cas de validation
par le GR
2024-05-13 01:50:12 +02:00
Vincent Vandemeulebrouck d1ec67e485 Correction Tooltips foundry
Suite à changement des Tooltips RdD, adaptation des tooltips
standard foundry
2024-05-12 19:37:58 +02:00
LeRatierBretonnien 7f7148e658 Preparation du passage en v12 2024-05-02 14:08:02 +02:00
LeRatierBretonnien bc35c8d80e Preparation du passage en v12 2024-05-01 09:13:21 +02:00
uberwald ad9e75c66d Merge pull request '11.2.19 - Les hémorroïdes d'Akarlikarlikar' (#697) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #697
2024-05-01 08:59:34 +02:00
Vincent Vandemeulebrouck e946299810 Version 11.2.19 2024-05-01 01:12:28 +02:00
Vincent Vandemeulebrouck fad894704d Fix: encaisser dommages par MJ
Lorsque l'option d'encaisser les dommages était contrôlée
par le MJ, les données envoyées par les joueurs ne correspondaient
pas aux paramètres de la méthode à exécuter par le MJ.

De plus, l'envoi de l'attacker (Actor) était reçu comme un Object,
donc inutilisable en tant qu'Actor.
2024-05-01 01:08:50 +02:00
uberwald 3365852210 Merge pull request '11.2.18' (#696) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #696
2024-03-21 15:51:07 +01:00
Vincent Vandemeulebrouck d71bf27311 Version 11.2.18 - Le bourrichon d'Akarlikarlikar 2024-03-20 21:57:02 +01:00
Vincent Vandemeulebrouck e6da18bebd Ajout du bouton Montrer
Ajout du bouton Montrer dans les différentes listes
2024-03-20 21:55:18 +01:00
uberwald 972ae74e2c Merge pull request '11.2.17 - Le cache-oeil d'Akarlikarlikar' (#695) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #695
2024-03-10 08:57:28 +01:00
Vincent Vandemeulebrouck 7969e74c8d Version 11.2.17 2024-03-10 00:53:45 +01:00
Vincent Vandemeulebrouck 84ea3a6ea9 Fix: TMR qui ne s'affichent pas
Après un certain temps (changements de scènes?), les TMR ne
s'affichaient plus correctement.

Tentative de forcer le chargement des textures manquantes lors
de l'ouverture de la fenêtre de TMR.
2024-03-10 00:47:50 +01:00
Vincent Vandemeulebrouck 7ada5577aa Ajout de l'information Ombre de Thanatos
Si Thanatos a été utilisé, la prochaine queue est une ombre
Un indicateur apparait dans l'onglet Haut-Rêve.
2024-03-10 00:24:02 +01:00
Vincent Vandemeulebrouck b0e28ef937 Fix: labels for / id
- Ajout de "for" sur labels
- suppression d'id inutiles
- corrections de for="xp" incorrects
- simplification css alchimie-title/blessure-title
2024-03-10 00:13:36 +01:00
Vincent Vandemeulebrouck 6414f76d67 Fix: ignorer personnages joueurs non liés
Pour les fenêtres de stress/repos/voyage/astrologie, ignorer
les personnages non liés (par exemple, un guerrier sorde)
2024-03-09 23:12:13 +01:00
Vincent Vandemeulebrouck dde3011f1d Fix: Checkbox cacher les points de tâche 2024-03-09 19:50:00 +01:00
Vincent Vandemeulebrouck 6dbf322efe Fix: traduction tooltip Ediot/Delete 2024-03-09 19:49:31 +01:00
Vincent Vandemeulebrouck d34fde2ba4 Fix: titre des feuilles d'objets
Suite à la correction de l'ordre et du nom dans la fenêtre de création,
les titres étaient incorrects (TYPES.Item.Tache par exemple)
2024-03-09 19:48:53 +01:00
Vincent Vandemeulebrouck bc169d931b Fix: log erreur TMR en mode visu
En mode visualisation, les informations du personnage ne sont
pas affichées
2024-03-09 19:38:53 +01:00
Vincent Vandemeulebrouck 3b269b2baa Simplifications 2024-03-09 19:13:13 +01:00
LeRatierBretonnien dffaa29fd1 Fix termes dans les fenetres de creation 2024-02-29 21:22:42 +01:00
LeRatierBretonnien c49e2a850b Fix termes dans les fenetres de creation 2024-02-29 20:59:06 +01:00
LeRatierBretonnien a5a9cc334e Fix termes dans les fenetres de creation 2024-02-29 20:45:25 +01:00
LeRatierBretonnien 43e49a0eb8 New common CounterClass 2024-02-08 12:46:49 +01:00
LeRatierBretonnien 5ab551da9e Rework usage log 2024-02-05 18:08:35 +01:00
LeRatierBretonnien 2a9e98f8c7 Ajout tirage de la force des rencontres avec /tmrr, ajout de bouton pour appliquer complètement les blessures 2024-01-30 23:18:21 +01:00
LeRatierBretonnien 669982ec4a Ajout tirage de la force des rencontres avec /tmrr, ajout de bouton pour appliquer complètement les blessures 2024-01-28 20:43:23 +01:00
LeRatierBretonnien 34183cd1a7 Ajout tirage de la force des rencontres avec /tmrr, ajout de bouton pour appliquer complètement les blessures 2024-01-28 20:41:00 +01:00
LeRatierBretonnien f7eae3ac1e Fix version+changelog 2024-01-02 18:51:22 +01:00
LeRatierBretonnien 623044c936 Sync fiche 2024-01-02 18:43:42 +01:00
LeRatierBretonnien 94caf4040b Affichage souffle 2023-12-30 14:20:05 +01:00
uberwald d577e2d2ec Merge pull request '11.2.13 - Les cent pas d'Akarlikarlikar' (#694) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #694
2023-12-26 23:44:30 +01:00
Vincent Vandemeulebrouck 050cd80dae Version 11.2.13 2023-12-26 19:07:36 +01:00
Vincent Vandemeulebrouck 3f098cab31 Commande /voyage
Ajout de la commande /voyage pour gérer la fatigue en voyage
2023-12-26 19:06:13 +01:00
Vincent Vandemeulebrouck 4274bce7d5 minor cleanup 2023-12-26 19:06:13 +01:00
Vincent Vandemeulebrouck 25d68d265e Image acteur dans les message de tours 2023-12-26 19:06:13 +01:00
uberwald c1c192f710 Merge pull request '11.2.12 - Le somnifère d'Akarlikarlikar' (#693) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #693
2023-12-24 12:42:15 +01:00
Vincent Vandemeulebrouck 7f64cd03f9 Version 11.2.12 2023-12-22 23:55:21 +01:00
Vincent Vandemeulebrouck 3ac9f487d0 Fix: perte de rêve potions enchantées
La perte de rêve des potions enchantées bloquait le processus de
récupération de château dormant
2023-12-22 20:12:58 +01:00
uberwald fa67c3d9c1 Merge pull request 'Version 11.2.11' (#692) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #692
2023-12-22 09:30:48 +01:00
Vincent Vandemeulebrouck 5b443f9ac0 Version 11.2.11 2023-12-22 02:25:30 +01:00
Vincent Vandemeulebrouck b0098574a0 Fix: refoulement
Le refoulement ne fonctionnait plus. Merci à javascript+VSCode
pour l'incapacité de fournir de l'analyse de code statique...
2023-12-22 02:21:22 +01:00
Vincent Vandemeulebrouck 5729f7e926 Bordure des images de profils
Remplacement de la bordure noire inesthétique avec des images de
profil sous forme de badge ronds, en utilisant juste une variation
de couleur de fond.
2023-12-22 02:21:22 +01:00
Vincent Vandemeulebrouck 0b66c945b8 Mise à jour couleur images compcreature
Passage du blanc à la couleur habituelle
2023-12-22 02:21:22 +01:00
uberwald f0fc44e00f Merge pull request '11.2.10 - Les expériences d'Akarlikarlikar' (#691) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #691
2023-12-11 09:34:21 +01:00
Vincent Vandemeulebrouck 6b7c2ad2f9 Version 11.2.10 2023-12-10 22:26:52 +01:00
Vincent Vandemeulebrouck 0ac5d317ce Icônes des boutons cuisiner/manger 2023-12-10 22:19:51 +01:00
Vincent Vandemeulebrouck f8a90fc3c3 Fontawsome solid
traduction de fas => fa-solid
2023-12-10 22:19:51 +01:00
Vincent Vandemeulebrouck 6dd647b787 Expérience des caractéristiques dérivées
Une fenêtre de répartition est ouverte quand plusieurs
caractéristiques peuvent recevoir l'expérience. Sinon,
l'expérience est attribuée automatiquement.

L'expérience n'est plus ajoutée en Force si supérieure à Taille+4
2023-12-10 22:19:51 +01:00
Vincent Vandemeulebrouck 1c55491ac7 Ajustements des tooltips TMR 2023-12-10 22:19:50 +01:00
uberwald 2b08678518 Merge pull request 'Version 11.2.9 - La barbe d'Akarlikarlikar' (#690) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #690
2023-12-09 16:23:41 +01:00
Vincent Vandemeulebrouck 355f2e4088 Version 11.2.9 2023-12-09 15:33:33 +01:00
Vincent Vandemeulebrouck e0862105f9 Icône d'état empoignade 2023-12-09 15:33:33 +01:00
Vincent Vandemeulebrouck 3ab48511a0 Sort en réserve en fleuve
Les sorts en réserve en fleuve sont indiqués sur toutes les cases fleuve
2023-12-09 15:33:33 +01:00
Vincent Vandemeulebrouck 05cd02b694 Fix: deprecation effects flags.core.statusId
Remplacement de la logique basée sur les flags par le set de "statuses"
2023-12-09 15:33:33 +01:00
Vincent Vandemeulebrouck 56a5d06f16 Fix erreur console ouverture TMR
quand TMR pas affichées, bringToTop ne marche pas
2023-12-09 15:33:32 +01:00
Vincent Vandemeulebrouck f34db764cb Permettre les jets de chance sans astrologie
Quand on fait un jet de chance pour la journée, permettre de
ne pas utiliser l'ajustement astrologique
2023-12-09 15:33:32 +01:00
Vincent Vandemeulebrouck 7267cd4096 Amélioration de tooltips
- style en phase avec le système
- icones attaque/d6/soins pour le HUD
- tooltip plus détaillé pour le HUD
- icône et bouton pour déterminer les chiffres astraux (astrologie)
- tooltips pour les boutons archétype
- suppression de log sur chaque point de coeur
2023-12-09 15:33:32 +01:00
152 changed files with 1658 additions and 872 deletions

View File

@ -1,4 +1,68 @@
# 11.2 # 11.2
## 11.2.20 - Le soulagement d'Akarlikarlikar
- L'option 'ajout de la difficulté d'attaque à l'encaissement est affichée comme un modificateur d'encaissement
- Les options d'encaissement alternative fonctionnent avec la validation du gardien
- La fenêtre d'astrologie du gardien affiche toutes les heures lues par un personnage
- Si aucune expérience n'est gagnée, les autres effets à appliquer (comme la récupération de seuil après avoir vaincu un rêve de Dragon) s'appliquent normalement
- Les tooltips de Foundry sont maintenant lisibles
- On n'accorde plus les entités de cauchemar deux fois quand le gardien valide les encaissements
- Les messages de récupération de rêve en cas de Rêve de Dragon sont clarifiés
## 11.2.19 - Les hémorroïdes d'Akarlikarlikar
- La validation des jets d'encaissement par le Gardien fonctionne de nouveau
## 11.2.18 - Le bourrichon d'Akarlikarlikar
- Les différentes listes de la feuille de personnage ont maintenant le bouton pour envoyer dans le tchat
## 11.2.17 - Le cache-oeil d'Akarlikarlikar
- Le titre des fenêtre d'objet affiche de nouveau le type traduit
- Les tooltips des boutons edit/delete sont maintenant en Français
- La case à cocher "Cacher les points de tâches" fonctionne de nouveau
- Les personnages non-liés ne sont plus dans les liste de personnages joueurs pour le repos, le stress, la fatigue
- L'utilisation de Thanatos est visible dans l'onglet Haut-Rêve pour indiquer que la prochaine queue est une ombre
- La fenêtre des TMRs ne devrait plus afficher une zone noire au lieu de la carte.
## 11.2.16 - Le Tri d'Akarlikarlikar
- Tri alphabétique des items dans la fenêtre de création
- Mise à jour comptage de monde
## 11.2.15 - La Table d'Akarlikarlikar
- Tirage automatique de la foce d'une rencontre (via la commande /tmrr)
- Ajout de boutons pour ajouter des blessures "complètes" (ie avec perte d'endurance/vie)
## 11.2.14 - Les petits pas d'Akarlikarlikar
- Correction sur la gestion de la surprise
- Ordre des messages sur les cases humides
## 11.2.13 - Les cent pas d'Akarlikarlikar
- Ajout de la commande /voyage pour gérer la fatigue de marche des voyageurs
## 11.2.12 - Le somnifère d'Akarlikarlikar
- Fix: les potions enchantées n'empêchent plus de finir correctement Château Dormant
## 11.2.11 - Le miroir d'Akarlikarlikar
- Changement des images de compétence de créatures morsure/pinces pour être dans le thème
- Suppression de la bordure autour des portraits d'acteurs, remplacés par un légèr éclaircissement du fond
- Fix: le refoulement ajoute correctement un souffle et revient à 0 en cas d'échec
## 11.2.10 - Les expériences d'Akarlikarlikar
- En cas d'expérience des caractéristiques dérivées,
- si plusieurs caractéristiques pourraient recevoir l'expérience, une fenêtre demande au joueur
- si une seule caractéristique peut recevoir de l'expérience, c'est attribué automatiquement
- Si la force est au maximum pour la taille personnage, on ne peut plus gagner d'expérience
## 11.2.9 - La barbe d'Akarlikarlikar
- Amélioration des textes de tooltips
- Les tooltips sont plus dans le thème de couleur du système Rêve de Dragon
- Ajouts d'icones pour les attaque/initiative/soins dans les raccourcis sur les tokens (HUD)
- Ajout d'une icône et transformation en bouton du lien pour accéder à l'astrologie et aux chiffres astraux
- Suppression de message de log inutile sur chaque point de coeur
- On peut désactiver l'ajustement astrologique sur les jets de chance (pour des jts de chances non liés à une heure)- Fix: suppression de quelques cas d'erreur lors de l'ouverture des TMR
- Fix: suppression du warning de depréciation effects flags.core.statusId
- Les sorts en réserve en fleuve sont indiqués sur toutes les cases fleuve
- Changement de l'icône d'état d'empoignade pour suivre les couleurs des autres icônes d'état
## 11.2.8 - L'éclairage d'Akarlikarlikar ## 11.2.8 - L'éclairage d'Akarlikarlikar
- l'ajustement de la lumière jour/nuit s'étale sur moins de temps (vaisseau et Lyre) - l'ajustement de la lumière jour/nuit s'étale sur moins de temps (vaisseau et Lyre)
- les nouveaux tooltips ne masquent plus l'information d'expérience - les nouveaux tooltips ne masquent plus l'information d'expérience

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 11 KiB

BIN
icons/empoignade.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 512 512"
style="height: 256px; width: 256px;"
version="1.1"
id="svg24"
sodipodi:docname="sort-reserve-humide3.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
<metadata
id="metadata30">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs28" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2794"
inkscape:window-height="1756"
id="namedview26"
showgrid="false"
inkscape:zoom="2.8786993"
inkscape:cx="323.66586"
inkscape:cy="227.70764"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg24" />
<g
id="g881"
transform="translate(2.1482304,2.80716)">
<path
d="m 243.94189,104.37921 -82.23331,178.13543 82.23331,27.44784 z"
class=""
fill="#f4e3d7"
fill-opacity="1"
id="path2"
style="stroke-width:1.10232" />
<path
d="m 263.7837,104.37921 v 205.58327 l 82.23331,-27.44784 z"
class=""
fill="#f4e3d7"
fill-opacity="1"
id="path4"
style="stroke-width:1.10232" />
<path
d="M 168.21228,221.005 18.274279,239.7445 141.75653,278.32581 Z"
class=""
fill="#f4e3d7"
fill-opacity="1"
id="path6"
style="stroke-width:1.10232" />
<path
d="M 339.51331,221.005 365.96906,278.32581 489.5395,239.7445 Z"
class=""
fill="#f4e3d7"
fill-opacity="1"
id="path8"
style="stroke-width:1.10232" />
<path
d="M -0.24475089,254.73609 114.97007,398.80973 230.27308,326.7178 Z"
class=""
fill="#f4e3d7"
fill-opacity="1"
id="path10"
style="stroke-width:1.10232" />
<path
d="M 507.94829,254.73609 277.45251,326.7178 392.75552,398.80973 Z"
class=""
fill="#f4e3d7"
fill-opacity="1"
id="path12"
style="stroke-width:1.10232" />
<path
d="M 253.8628,335.42615 147.37837,402.00647 H 360.34722 Z"
class=""
fill="#f4e3d7"
fill-opacity="1"
id="path14"
style="stroke-width:1.10232" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -1,55 +1,56 @@
{ {
"TYPES": { "TYPES": {
"Actor": { "Actor": {
"Personnage": "Personnage", "personnage": "Personnage",
"Creature": "Créature", "creature": "Créature",
"Entite": "Entité de cauchemar", "entite": "Entité de cauchemar",
"Commerce": "Commerce", "commerce": "Commerce",
"Vehicule": "Véhicule" "vehicule": "Véhicule"
}, },
"Item": { "Item": {
"Arme": "Arme", "arme": "Arme",
"Armure": "Armure", "armure": "Armure",
"Blessure": "Blessure", "blessure": "Blessure",
"Casetmr": "TMR spéciale", "casetmr": "Case TMR spéciale",
"Chant": "Chant", "chant": "Chant",
"Competence": "Compétence", "competence": "Compétence",
"Competencecreature": "Compétence de créature", "competencecreature": "Compétence de créature",
"Conteneur": "Conteneur", "conteneur": "Conteneur",
"Danse": "Danse", "danse": "Danse",
"Extraitpoetique": "Extrait poetique", "empoignade": "Empoignade",
"Faune": "Faune", "extraitpoetique": "Extrait poetique",
"Gemme": "Gemme", "faune": "Faune",
"Herbe": "Herbe", "gemme": "Gemme",
"Ingredient": "Ingrédient", "herbe": "Herbe",
"Jeu": "Jeu", "ingredient": "Ingrédient",
"Livre": "Livre", "jeu": "Jeu",
"Maladie": "Maladie", "livre": "Livre",
"Meditation": "Méditation", "maladie": "Maladie",
"Monnaie": "Monnaie", "meditation": "Méditation",
"Munition": "Munition", "monnaie": "Monnaie",
"Musique": "Musique", "munition": "Munition",
"Nombreastral": "Nombre astral", "musique": "Musique",
"Nourritureboisson": "Nourriture & boisson", "nombreastral": "Nombre astral",
"Objet": "Objet", "nourritureboisson": "Nourriture & boisson",
"Oeuvre": "Oeuvre", "objet": "Objet",
"Ombre": "Ombre de Thanatos", "oeuvre": "Oeuvre",
"Plante": "Plante", "ombre": "Ombre de Thanatos",
"Poison": "Poison", "plante": "Plante",
"Possession": "Possession", "poison": "Poison",
"Potion": "Potion", "possession": "Possession",
"Queue": "Queue de Dragon", "potion": "Potion",
"Recettealchimique": "Recette alchimique", "queue": "Queue de Dragon",
"Recettecuisine": "Recette de cuisine", "recettealchimique": "Recette alchimique",
"Rencontre": "Rencontre TMR", "recettecuisine": "Recette de cuisine",
"Service": "Service", "rencontre": "Rencontre TMR",
"Signedraconique": "Signe draconique", "service": "Service",
"Sort": "Sort", "signedraconique": "Signe draconique",
"Sortreserve": "Sort en réserve", "sort": "Sort",
"Souffle": "Souffle de Dragon", "sortreserve": "Sort en réserve",
"Tache": "Tâche", "souffle": "Souffle de Dragon",
"Tarot": "Carte de tarot", "tache": "Tâche",
"Tete": "Tête de Dragon" "tarot": "Carte de tarot",
"tete": "Tête de Dragon"
} }
}, },
"EFFECT": { "EFFECT": {

View File

@ -28,7 +28,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(RdDBaseActorReveSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html",
width: 550, width: 550,
showCompNiveauBase: false, showCompNiveauBase: false,
@ -39,7 +39,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
let formData = await super.getData(); let formData = await super.getData();
mergeObject(formData, foundry.utils.mergeObject(formData,
{ {
editable: this.isEditable, editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked", cssClass: this.isEditable ? "editable" : "locked",
@ -49,7 +49,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
biographie: await TextEditor.enrichHTML(this.actor.system.biographie, { async: true }), biographie: await TextEditor.enrichHTML(this.actor.system.biographie, { async: true }),
notes: await TextEditor.enrichHTML(this.actor.system.notes, { async: true }), notes: await TextEditor.enrichHTML(this.actor.system.notes, { async: true }),
}); });
mergeObject(formData.calc, { foundry.utils.mergeObject(formData.calc, {
surenc: this.actor.computeMalusSurEncombrement(), surenc: this.actor.computeMalusSurEncombrement(),
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),
@ -80,7 +80,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
// toujours avoir une liste d'armes (pour mettre esquive et corps à corps) // toujours avoir une liste d'armes (pour mettre esquive et corps à corps)
const actor = this.actor; const actor = this.actor;
formData.combat = duplicate(formData.armes); formData.combat = foundry.utils.duplicate(formData.armes);
RdDItemArme.computeNiveauArmes(formData.combat, formData.competences); RdDItemArme.computeNiveauArmes(formData.combat, formData.competences);
formData.combat.push(RdDItemArme.mainsNues(actor)); formData.combat.push(RdDItemArme.mainsNues(actor));
formData.combat.push(RdDItemArme.empoignade(actor)); formData.combat.push(RdDItemArme.empoignade(actor));
@ -221,7 +221,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
// Points de reve actuel // Points de reve actuel
this.html.find('.ptreve-actuel a').click(async event => this.actor.rollCarac('reve-actuel', true)) this.html.find('.ptreve-actuel a').click(async event => this.actor.rollCarac('reve-actuel', true))
this.html.find('.empoignade-label a').click(async event => RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor))) this.html.find('.empoignade-label a').click(async event => RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor)))
this.html.find('.arme-label a').click(async event => this.actor.rollArme(duplicate(this._getEventArmeCombat(event)))) this.html.find('.arme-label a').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event))))
// Initiative pour l'arme // Initiative pour l'arme
this.html.find('.arme-initiative a').click(async event => { this.html.find('.arme-initiative a').click(async event => {
@ -388,7 +388,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
async _onSplitItem(item, split) { async _onSplitItem(item, split) {
if (split >= 1 && split < item.system.quantite) { if (split >= 1 && split < item.system.quantite) {
await item.diminuerQuantite(split); await item.diminuerQuantite(split);
const splitItem = duplicate(item); const splitItem = foundry.utils.duplicate(item);
splitItem.system.quantite = split; splitItem.system.quantite = split;
await this.actor.createEmbeddedDocuments('Item', [splitItem]) await this.actor.createEmbeddedDocuments('Item', [splitItem])
} }

View File

@ -35,6 +35,7 @@ import { ExperienceLog, XP_TOPIC } from "./actor/experience-log.js";
import { TYPES } from "./item.js"; import { TYPES } from "./item.js";
import { RdDBaseActorSang } from "./actor/base-actor-sang.js"; import { RdDBaseActorSang } from "./actor/base-actor-sang.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js";
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre'] export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
@ -56,21 +57,20 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
$computeCaracDerivee() { $computeCaracDerivee() {
this.system.carac.force.value = Math.min(this.system.carac.force.value, parseInt(this.system.carac.taille.value) + 4); this.system.carac.force.value = Math.min(this.system.carac.force.value, parseInt(this.system.carac.taille.value) + 4);
this.system.carac.derobee.value = Math.floor(parseInt(((21 - this.system.carac.taille.value)) + parseInt(this.system.carac.agilite.value)) / 2);
let bonusDomKey = Math.floor((parseInt(this.system.carac.force.value) + parseInt(this.system.carac.taille.value)) / 2);
let tailleData = RdDCarac.getCaracDerivee(bonusDomKey);
this.system.attributs.plusdom.value = tailleData.plusdom;
this.system.attributs.sconst.value = RdDCarac.calculSConst(this.system.carac.constitution.value);
this.system.attributs.sust.value = RdDCarac.getCaracDerivee(this.system.carac.taille.value).sust;
this.system.attributs.encombrement.value = (parseInt(this.system.carac.force.value) + parseInt(this.system.carac.taille.value)) / 2;
this.system.carac.melee.value = Math.floor((parseInt(this.system.carac.force.value) + parseInt(this.system.carac.agilite.value)) / 2); this.system.carac.melee.value = Math.floor((parseInt(this.system.carac.force.value) + parseInt(this.system.carac.agilite.value)) / 2);
this.system.carac.tir.value = Math.floor((parseInt(this.system.carac.vue.value) + parseInt(this.system.carac.dexterite.value)) / 2); this.system.carac.tir.value = Math.floor((parseInt(this.system.carac.vue.value) + parseInt(this.system.carac.dexterite.value)) / 2);
this.system.carac.lancer.value = Math.floor((parseInt(this.system.carac.tir.value) + parseInt(this.system.carac.force.value)) / 2); this.system.carac.lancer.value = Math.floor((parseInt(this.system.carac.tir.value) + parseInt(this.system.carac.force.value)) / 2);
this.system.carac.derobee.value = Math.floor(parseInt(((21 - this.system.carac.taille.value)) + parseInt(this.system.carac.agilite.value)) / 2);
let bonusDomKey = Math.floor((parseInt(this.system.carac.force.value) + parseInt(this.system.carac.taille.value)) / 2);
let tailleData = RdDCarac.getCaracDerivee(bonusDomKey);
this.system.attributs.plusdom.value = tailleData.plusdom;
this.system.attributs.encombrement.value = (parseInt(this.system.carac.force.value) + parseInt(this.system.carac.taille.value)) / 2;
this.system.attributs.sconst.value = RdDCarac.calculSConst(this.system.carac.constitution.value);
this.system.attributs.sust.value = RdDCarac.getCaracDerivee(this.system.carac.taille.value).sust;
this.system.sante.vie.max = Math.ceil((parseInt(this.system.carac.taille.value) + parseInt(this.system.carac.constitution.value)) / 2); this.system.sante.vie.max = Math.ceil((parseInt(this.system.carac.taille.value) + parseInt(this.system.carac.constitution.value)) / 2);
this.system.sante.vie.value = Math.min(this.system.sante.vie.value, this.system.sante.vie.max) this.system.sante.vie.value = Math.min(this.system.sante.vie.value, this.system.sante.vie.max)
@ -95,30 +95,32 @@ export class RdDActor extends RdDBaseActorSang {
return ![TYPES.competencecreature, TYPES.tarot, TYPES.service].includes(item.type) return ![TYPES.competencecreature, TYPES.tarot, TYPES.service].includes(item.type)
} }
isPersonnageJoueur() {
return this.hasPlayerOwner && this.prototypeToken.actorLink
}
isPersonnage() { return true } isPersonnage() { return true }
isHautRevant() { return this.system.attributs.hautrevant.value != "" } isHautRevant() { return this.system.attributs.hautrevant.value != "" }
/* -------------------------------------------- */ /* -------------------------------------------- */
getAgilite() { return Number(this.system.carac.agilite?.value ?? 0) } getAgilite() { return this.system.carac.agilite?.value ?? 0 }
getChance() { return Number(this.system.carac.chance?.value ?? 0) } getChance() { return this.system.carac.chance?.value ?? 0 }
getReveActuel() { return Misc.toInt(this.system.reve?.reve?.value ?? this.carac.reve.value) } getReveActuel() { return this.system.reve?.reve?.value ?? this.carac.reve.value ?? 0 }
getChanceActuel() { return Misc.toInt(this.system.compteurs.chance?.value ?? 10) } getChanceActuel() { return this.system.compteurs.chance?.value ?? 10 }
getMoralTotal() { return Number(this.system.compteurs.moral?.value ?? 0) } getMoralTotal() { return this.system.compteurs.moral?.value ?? 0 }
/* -------------------------------------------- */ /* -------------------------------------------- */
getEtatGeneral(options = { ethylisme: false }) { getEtatGeneral(options = { ethylisme: false }) {
const etatGeneral = Misc.toInt(this.system.compteurs.etat?.value) const etatGeneral = this.system.compteurs.etat?.value ?? 0
if (options.ethylisme) { // Pour les jets d'Ethylisme, on retire le malus d'éthylisme (p.162)
// Pour les jets d'Ethylisme, on retire le malus d'éthylisme (p.162) const annuleMalusEthylisme = options.ethylisme ? this.malusEthylisme() : 0
return etatGeneral - this.malusEthylisme() return etatGeneral - annuleMalusEthylisme
}
return etatGeneral
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getActivePoisons() { getActivePoisons() {
return duplicate(this.items.filter(item => item.type == 'poison' && item.system.active)) return foundry.utils.duplicate(this.items.filter(item => item.type == 'poison' && item.system.active))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -141,7 +143,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
getDemiReve() { return this.system.reve.tmrpos.coord } getDemiReve() { return this.system.reve.tmrpos.coord }
getDraconicList() { return this.itemTypes[TYPES.competence].filter(it => it.system.categorie == 'draconic') } getDraconicList() { return this.itemTypes[TYPES.competence].filter(it => it.system.categorie == 'draconic') }
getBestDraconic() { return duplicate(this.getDraconicList().sort(Misc.descending(it => it.system.niveau)).find(it => true)) } getBestDraconic() { return foundry.utils.duplicate(this.getDraconicList().sort(Misc.descending(it => it.system.niveau)).find(it => true)) }
getDraconicOuPossession() { getDraconicOuPossession() {
return [...this.getDraconicList().filter(it => it.system.niveau >= 0), return [...this.getDraconicList().filter(it => it.system.niveau >= 0),
super.getDraconicOuPossession()] super.getDraconicOuPossession()]
@ -152,23 +154,26 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async $perteRevePotionsEnchantees() { async $perteRevePotionsEnchantees() {
let potions = this.itemTypes[TYPES.potion] let potions = this.itemTypes[TYPES.potion]
.filter(it => it.system.categorie.toLowerCase().includes('enchant') && !potion.system.prpermanent) .filter(it => Grammar.includesLowerCaseNoAccent(it.system.categorie, 'enchanté') && !it.system.prpermanent)
const potionUpdates = await Promise.all(potions.map(async potion => { const potionUpdates = await Promise.all(potions.map(async it => {
console.log(potion) const nouveauReve = Math.max(it.system.pr - 1, 0)
let nouveauReve = (potion.system.pr > 0) ? potion.system.pr - 1 : 0;
const message = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-potionenchantee-chateaudormant.html`, {
pr: nouveauReve,
alias: this.name,
potionName: potion.name,
potionImg: potion.img
})
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name), whisper: ChatUtility.getWhisperRecipientsAndGMs(this.name),
content: message content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-potionenchantee-chateaudormant.html`, {
}); pr: nouveauReve,
return { _id: potion._id, 'system.pr': nouveauReve }; alias: this.name,
potionName: it.name,
potionImg: it.img
})
})
return {
_id: it._id,
'system.pr': nouveauReve,
'system.quantite': nouveauReve > 0 ? it.system.quantite : 0
}
})) }))
await this.updateEmbeddedDocuments('Item', potionUpdates); await this.updateEmbeddedDocuments('Item', potionUpdates);
} }
@ -342,7 +347,7 @@ export class RdDActor extends RdDBaseActorSang {
const timestamp = game.system.rdd.calendrier.getTimestamp() const timestamp = game.system.rdd.calendrier.getTimestamp()
const blessures = this.filterItems(it => it.system.gravite > 0, TYPES.blessure).sort(Misc.ascending(it => it.system.gravite)) const blessures = this.filterItems(it => it.system.gravite > 0, TYPES.blessure).sort(Misc.ascending(it => it.system.gravite))
await Promise.all(blessures.map(b => b.recuperationBlessure({ await Promise.all(blessures.map(async b => b.recuperationBlessure({
actor: this, actor: this,
timestamp, timestamp,
message, message,
@ -399,7 +404,7 @@ export class RdDActor extends RdDBaseActorSang {
content: 'Remise à neuf de ' + this.name content: 'Remise à neuf de ' + this.name
}); });
await this.supprimerBlessures(it => true); await this.supprimerBlessures(it => true);
await this.removeEffects(e => e.flags.core.statusId !== STATUSES.StatusDemiReve); await this.removeEffects(e => e.id != STATUSES.StatusDemiReve);
const updates = { const updates = {
'system.sante.endurance.value': this.system.sante.endurance.max, 'system.sante.endurance.value': this.system.sante.endurance.max,
'system.sante.vie.value': this.system.sante.vie.max, 'system.sante.vie.value': this.system.sante.vie.max,
@ -424,7 +429,7 @@ export class RdDActor extends RdDBaseActorSang {
let jetsReve = []; let jetsReve = [];
let dormi = await this.dormirDesHeures(jetsReve, message, heures, options); let dormi = await this.dormirDesHeures(jetsReve, message, heures, options);
if (jetsReve.length > 0) { if (jetsReve.length > 0) {
message.content += `Vous récupérez ${jetsReve.map(it => it < 0 ? '(dragon)' : it).reduce(Misc.joining("+"))} Points de rêve. `; message.content += `Vous récupérez ${jetsReve.map(it => it < 0 ? '0 (réveil)' : it).reduce(Misc.joining("+"))} Points de rêve. `;
} }
if (dormi.etat == 'eveil') { if (dormi.etat == 'eveil') {
await this.reveilReveDeDragon(message, dormi.heures); await this.reveilReveDeDragon(message, dormi.heures);
@ -445,7 +450,6 @@ export class RdDActor extends RdDBaseActorSang {
} }
async reveilReveDeDragon(message, heures) { async reveilReveDeDragon(message, heures) {
message.content += 'Vous êtes réveillé par un Rêve de Dragon.';
const restant = Math.max(this.system.sommeil?.heures - heures, 0) const restant = Math.max(this.system.sommeil?.heures - heures, 0)
if (restant > 0) { if (restant > 0) {
await this.update({ 'system.sommeil': { heures: restant } }); await this.update({ 'system.sommeil': { heures: restant } });
@ -659,7 +663,7 @@ export class RdDActor extends RdDBaseActorSang {
this.setPointsDeChance(to); this.setPointsDeChance(to);
} }
} }
let selectedCarac = RdDBaseActor._findCaracByName(this.system.carac, caracName); let selectedCarac = this.findCaracByName(caracName);
const from = selectedCarac.value const from = selectedCarac.value
await this.update({ [`system.carac.${caracName}.value`]: to }); await this.update({ [`system.carac.${caracName}.value`]: to });
await ExperienceLog.add(this, XP_TOPIC.CARAC, from, to, caracName); await ExperienceLog.add(this, XP_TOPIC.CARAC, from, to, caracName);
@ -670,7 +674,7 @@ export class RdDActor extends RdDBaseActorSang {
if (caracName == 'Taille') { if (caracName == 'Taille') {
return; return;
} }
let selectedCarac = RdDBaseActor._findCaracByName(this.system.carac, caracName); let selectedCarac = this.findCaracByName(caracName);
if (!selectedCarac.derivee) { if (!selectedCarac.derivee) {
const from = Number(selectedCarac.xp); const from = Number(selectedCarac.xp);
await this.update({ [`system.carac.${caracName}.xp`]: to }); await this.update({ [`system.carac.${caracName}.xp`]: to });
@ -684,9 +688,9 @@ export class RdDActor extends RdDBaseActorSang {
if (caracName == 'Taille') { if (caracName == 'Taille') {
return; return;
} }
let carac = RdDBaseActor._findCaracByName(this.system.carac, caracName); let carac = this.findCaracByName(caracName);
if (carac) { if (carac) {
carac = duplicate(carac); carac = foundry.utils.duplicate(carac);
const fromXp = Number(carac.xp); const fromXp = Number(carac.xp);
const fromValue = Number(carac.value); const fromValue = Number(carac.value);
let toXp = fromXp; let toXp = fromXp;
@ -822,7 +826,7 @@ export class RdDActor extends RdDBaseActorSang {
async deleteExperienceLog(from, count) { async deleteExperienceLog(from, count) {
if (from >= 0 && count > 0) { if (from >= 0 && count > 0) {
let expLog = duplicate(this.system.experiencelog); let expLog = foundry.utils.duplicate(this.system.experiencelog);
expLog.splice(from, count); expLog.splice(from, count);
await this.update({ [`system.experiencelog`]: expLog }); await this.update({ [`system.experiencelog`]: expLog });
} }
@ -896,7 +900,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async ajouterRefoulement(value = 1, refouler) { async ajouterRefoulement(value = 1, refouler) {
const refoulement = this.system.reve.refoulement.value + value; let refoulement = this.system.reve.refoulement.value + value;
const roll = new Roll("1d20"); const roll = new Roll("1d20");
await roll.evaluate({ async: true }); await roll.evaluate({ async: true });
await roll.toMessage({ flavor: `${this.name} refoule ${refouler} pour ${value} points de refoulement (total: ${refoulement})` }); await roll.toMessage({ flavor: `${this.name} refoule ${refouler} pour ${value} points de refoulement (total: ${refoulement})` });
@ -1166,8 +1170,8 @@ export class RdDActor extends RdDBaseActorSang {
title: "Nourriture brute", title: "Nourriture brute",
content: `Que faire de votre ${item.name}`, content: `Que faire de votre ${item.name}`,
buttons: { buttons: {
'cuisiner': { icon: '<i class="fas fa-check"></i>', label: 'Cuisiner', callback: async () => await this.preparerNourriture(item) }, 'cuisiner': { icon: '<i class="fa-solid fa-utensils"></i>', label: 'Cuisiner', callback: async () => await this.preparerNourriture(item) },
'manger': { icon: '<i class="fas fa-check"></i>', label: 'Manger cru', callback: async () => await this.mangerNourriture(item, onActionItem) } 'manger': { icon: '<i class="fa-solid fa-drumstick-bite"></i>', label: 'Manger cru', callback: async () => await this.mangerNourriture(item, onActionItem) }
} }
}); });
return utilisation.render(true); return utilisation.render(true);
@ -1307,7 +1311,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async saouler(forceAlcool, alcool = undefined) { async saouler(forceAlcool, alcool = undefined) {
let ethylisme = duplicate(this.system.compteurs.ethylisme); let ethylisme = foundry.utils.duplicate(this.system.compteurs.ethylisme);
const etat = this.getEtatGeneral({ ethylisme: true }); const etat = this.getEtatGeneral({ ethylisme: true });
const nbDoses = Number(this.system.compteurs.ethylisme.nb_doses || 0); const nbDoses = Number(this.system.compteurs.ethylisme.nb_doses || 0);
@ -1328,7 +1332,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
await RdDResolutionTable.rollData(ethylismeData.jetVie); await RdDResolutionTable.rollData(ethylismeData.jetVie);
this._appliquerExperienceRollData(ethylismeData.jetVie); this._gererExperience(ethylismeData.jetVie);
RollDataAjustements.calcul(ethylismeData.jetVie, this); RollDataAjustements.calcul(ethylismeData.jetVie, this);
if (ethylismeData.jetVie.rolled.isSuccess) { if (ethylismeData.jetVie.rolled.isSuccess) {
ethylisme.nb_doses++; ethylisme.nb_doses++;
@ -1360,7 +1364,7 @@ export class RdDActor extends RdDBaseActorSang {
finalLevel: Number(ethylisme.value) + Number(this.system.compteurs.moral.value) finalLevel: Number(ethylisme.value) + Number(this.system.compteurs.moral.value)
} }
await RdDResolutionTable.rollData(ethylismeData.jetVolonte); await RdDResolutionTable.rollData(ethylismeData.jetVolonte);
this._appliquerExperienceRollData(ethylismeData.jetVolonte); this._gererExperience(ethylismeData.jetVolonte);
RollDataAjustements.calcul(ethylismeData.jetVolonte, this); RollDataAjustements.calcul(ethylismeData.jetVolonte, this);
} }
} }
@ -1472,13 +1476,19 @@ export class RdDActor extends RdDBaseActorSang {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
isCaracMax(code) {
if (code == 'force' && parseInt(this.system.carac.force.value) >= parseInt(this.system.carac.taille.value) + 4) {
return true;
}
return false
}
async checkCaracXP(caracName, display = true) { async checkCaracXP(caracName, display = true) {
let carac = RdDBaseActor._findCaracByName(this.system.carac, caracName); let carac = this.findCaracByName(caracName);
if (carac && carac.xp > 0) { if (carac && carac.xp > 0) {
const niveauSuivant = Number(carac.value) + 1; const niveauSuivant = Number(carac.value) + 1;
let xpNeeded = RdDCarac.getCaracNextXp(niveauSuivant); let xpNeeded = RdDCarac.getCaracNextXp(niveauSuivant);
if (carac.xp >= xpNeeded) { if (carac.xp >= xpNeeded) {
carac = duplicate(carac); carac = foundry.utils.duplicate(carac);
carac.value = niveauSuivant; carac.value = niveauSuivant;
let checkXp = { let checkXp = {
@ -1508,7 +1518,7 @@ export class RdDActor extends RdDBaseActorSang {
if (compData && newXP > 0) { if (compData && newXP > 0) {
let xpNeeded = RdDItemCompetence.getCompetenceNextXp(compData.system.niveau + 1); let xpNeeded = RdDItemCompetence.getCompetenceNextXp(compData.system.niveau + 1);
if (newXP >= xpNeeded) { if (newXP >= xpNeeded) {
let newCompData = duplicate(compData); let newCompData = foundry.utils.duplicate(compData);
newCompData.system.niveau += 1; newCompData.system.niveau += 1;
newCompData.system.xp = newXP; newCompData.system.xp = newXP;
let checkXp = { let checkXp = {
@ -1534,8 +1544,11 @@ export class RdDActor extends RdDBaseActorSang {
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { async appliquerAjoutExperience(rollData, hideChatMessage = 'show') {
hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM) hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM)
let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence, rollData.jetResistance); let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence, rollData.jetResistance);
if (xpData) { if (xpData.length) {
const content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-gain-xp.html`, xpData); const content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-gain-xp.html`, {
actor: this,
xpData
})
if (hideChatMessage) { if (hideChatMessage) {
ChatUtility.blindMessageToGM({ content: content }); ChatUtility.blindMessageToGM({ content: content });
} }
@ -1611,14 +1624,14 @@ export class RdDActor extends RdDBaseActorSang {
return; return;
} }
// Duplication car les pts de reve sont modifiés dans le sort // Duplication car les pts de reve sont modifiés dans le sort
let sorts = duplicate(this.$filterSortList(this.itemTypes['sort'], coord)); let sorts = foundry.utils.duplicate(this.$filterSortList(this.itemTypes['sort'], coord));
if (sorts.length == 0) { if (sorts.length == 0) {
ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`); ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`);
return; return;
} }
const draconicList = this.computeDraconicAndSortIndex(sorts); const draconicList = this.computeDraconicAndSortIndex(sorts);
const reve = duplicate(this.system.carac.reve); const reve = foundry.utils.duplicate(this.system.carac.reve);
const dialog = await this.openRollDialog({ const dialog = await this.openRollDialog({
name: 'lancer-un-sort', name: 'lancer-un-sort',
@ -1698,7 +1711,7 @@ export class RdDActor extends RdDBaseActorSang {
if (rollData.competence.name.includes('Thanatos')) { // Si Thanatos if (rollData.competence.name.includes('Thanatos')) { // Si Thanatos
await this.update({ "system.reve.reve.thanatosused": true }); await this.update({ "system.reve.reve.thanatosused": true });
} }
let reveActuel = this.system.reve.reve.value; let reveActuel = parseInt(this.system.reve.reve.value)
if (rolled.isSuccess) { // Réussite du sort ! if (rolled.isSuccess) { // Réussite du sort !
if (rolled.isPart) { if (rolled.isPart) {
rollData.depenseReve = Math.max(Math.floor(rollData.depenseReve / 2), 1); rollData.depenseReve = Math.max(Math.floor(rollData.depenseReve / 2), 1);
@ -1717,7 +1730,7 @@ export class RdDActor extends RdDBaseActorSang {
else { else {
rollData.depenseReve = 0; rollData.depenseReve = 0;
rollData.show.reveInsuffisant = true; rollData.show.reveInsuffisant = true;
mergeObject(rollData.rolled, RdDResolutionTable.getResultat("echec"), { overwrite: true }); foundry.utils.mergeObject(rollData.rolled, RdDResolutionTable.getResultat("echec"), { overwrite: true });
} }
} else { } else {
if (rolled.isETotal) { // Echec total ! if (rolled.isETotal) { // Echec total !
@ -1765,13 +1778,13 @@ export class RdDActor extends RdDBaseActorSang {
}; };
RollDataAjustements.calcul(rollData, this); RollDataAjustements.calcul(rollData, this);
await RdDResolutionTable.rollData(rollData); await RdDResolutionTable.rollData(rollData);
this._appliquerExperienceRollData(rollData); this._gererExperience(rollData);
await RdDResolutionTable.displayRollData(rollData, this) await RdDResolutionTable.displayRollData(rollData, this)
return rollData.rolled; return rollData.rolled;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_appliquerExperienceRollData(rollData) { _gererExperience(rollData) {
const callback = this.createCallbackExperience(); const callback = this.createCallbackExperience();
if (callback.condition(rollData)) { if (callback.condition(rollData)) {
callback.action(rollData); callback.action(rollData);
@ -1804,7 +1817,10 @@ export class RdDActor extends RdDBaseActorSang {
} }
blessuresASoigner() { blessuresASoigner() {
return this.filterItems(it => it.system.gravite > 0 && it.system.gravite <= 6 && !(it.system.premierssoins.done && it.system.soinscomplets.done), 'blessure') return (this.itemTypes[TYPES.blessure])
.filter(it => it.system.gravite > 0 && it.system.gravite <= 6)
.filter(it => !(it.system.premierssoins.done && it.system.soinscomplets.done))
.sort(Misc.descending(b => (b.system.premierssoins.done ? "A" : "B") + b.system.gravite))
} }
async getTacheBlessure(blesse, blessure) { async getTacheBlessure(blesse, blessure) {
@ -1856,7 +1872,7 @@ export class RdDActor extends RdDBaseActorSang {
diffConditions: 0, diffConditions: 0,
use: { libre: false, conditions: true }, use: { libre: false, conditions: true },
carac: { carac: {
[tacheData.system.carac]: duplicate(this.system.carac[tacheData.system.carac]) [tacheData.system.carac]: foundry.utils.duplicate(this.system.carac[tacheData.system.carac])
} }
}, },
callbackAction: r => this._tacheResult(r, options) callbackAction: r => this._tacheResult(r, options)
@ -1867,7 +1883,7 @@ export class RdDActor extends RdDBaseActorSang {
async _tacheResult(rollData, options) { async _tacheResult(rollData, options) {
// Mise à jour de la tache // Mise à jour de la tache
rollData.appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue"); rollData.appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue");
rollData.tache = duplicate(rollData.tache); rollData.tache = foundry.utils.duplicate(rollData.tache);
rollData.tache.system.points_de_tache_courant += rollData.rolled.ptTache; rollData.tache.system.points_de_tache_courant += rollData.rolled.ptTache;
if (rollData.rolled.isETotal) { if (rollData.rolled.isETotal) {
rollData.tache.system.difficulte--; rollData.tache.system.difficulte--;
@ -1891,21 +1907,21 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _rollArt(artData, selected, oeuvre, callbackAction = r => this._resultArt(r)) { async _rollArt(artData, selected, oeuvre, callbackAction = r => this._resultArt(r)) {
oeuvre.system.niveau = oeuvre.system.niveau ?? 0; oeuvre.system.niveau = oeuvre.system.niveau ?? 0;
mergeObject(artData, foundry.utils.mergeObject(artData,
{ {
oeuvre: oeuvre, oeuvre: oeuvre,
art: oeuvre.type, art: oeuvre.type,
competence: duplicate(this.getCompetence(artData.compName ?? oeuvre.system.competence ?? artData.art)), competence: foundry.utils.duplicate(this.getCompetence(artData.compName ?? oeuvre.system.competence ?? artData.art)),
diffLibre: - oeuvre.system.niveau, diffLibre: - oeuvre.system.niveau,
diffConditions: 0, diffConditions: 0,
use: { libre: false, conditions: true, surenc: false }, use: { libre: false, conditions: true, surenc: false },
selectedCarac: duplicate(this.system.carac[selected]) selectedCarac: foundry.utils.duplicate(this.system.carac[selected])
}, },
{ overwrite: false }); { overwrite: false });
artData.competence.system.defaut_carac = selected; artData.competence.system.defaut_carac = selected;
if (!artData.forceCarac) { if (!artData.forceCarac) {
artData.forceCarac = {}; artData.forceCarac = {};
artData.forceCarac[selected] = duplicate(this.system.carac[selected]); artData.forceCarac[selected] = foundry.utils.duplicate(this.system.carac[selected]);
} }
await this.openRollDialog({ await this.openRollDialog({
@ -1929,19 +1945,19 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollChant(id) { async rollChant(id) {
const artData = { art: 'chant', verbe: 'Chanter' }; const artData = { art: 'chant', verbe: 'Chanter' };
const oeuvre = duplicate(this.getChant(id)); const oeuvre = foundry.utils.duplicate(this.getChant(id));
await this._rollArt(artData, "ouie", oeuvre); await this._rollArt(artData, "ouie", oeuvre);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollDanse(id) { async rollDanse(id) {
const artData = { art: 'danse', verbe: 'Danser', forceCarac: {} }; const artData = { art: 'danse', verbe: 'Danser', forceCarac: {} };
const oeuvre = duplicate(this.findItemLike(id, artData.art)); const oeuvre = foundry.utils.duplicate(this.findItemLike(id, artData.art));
if (oeuvre.system.agilite) { if (oeuvre.system.agilite) {
artData.forceCarac['agilite'] = duplicate(this.system.carac.agilite); artData.forceCarac['agilite'] = foundry.utils.duplicate(this.system.carac.agilite);
} }
if (oeuvre.system.apparence) { if (oeuvre.system.apparence) {
artData.forceCarac['apparence'] = duplicate(this.system.carac.apparence); artData.forceCarac['apparence'] = foundry.utils.duplicate(this.system.carac.apparence);
} }
const selectedCarac = this._getCaracDanse(oeuvre); const selectedCarac = this._getCaracDanse(oeuvre);
await this._rollArt(artData, selectedCarac, oeuvre); await this._rollArt(artData, selectedCarac, oeuvre);
@ -2044,7 +2060,7 @@ export class RdDActor extends RdDBaseActorSang {
const artData = { const artData = {
art: 'jeu', verbe: 'Jeu', art: 'jeu', verbe: 'Jeu',
use: { libre: true, conditions: true, }, use: { libre: true, conditions: true, },
competence: duplicate(this.getCompetence('jeu')), competence: foundry.utils.duplicate(this.getCompetence('jeu')),
forceCarac: {} forceCarac: {}
}; };
listCarac.forEach(c => artData.forceCarac[c] = this.system.carac[c]); listCarac.forEach(c => artData.forceCarac[c] = this.system.carac[c]);
@ -2055,14 +2071,14 @@ export class RdDActor extends RdDBaseActorSang {
async rollOeuvre(id) { async rollOeuvre(id) {
const artData = { art: 'oeuvre', verbe: 'Interpréter' } const artData = { art: 'oeuvre', verbe: 'Interpréter' }
const oeuvre = duplicate(this.findItemLike(id, artData.art)) const oeuvre = foundry.utils.duplicate(this.findItemLike(id, artData.art))
await this._rollArt(artData, oeuvre.system.default_carac, oeuvre) await this._rollArt(artData, oeuvre.system.default_carac, oeuvre)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollMeditation(id) { async rollMeditation(id) {
const meditation = duplicate(this.getMeditation(id)); const meditation = foundry.utils.duplicate(this.getMeditation(id));
const competence = duplicate(this.getCompetence(meditation.system.competence)); const competence = foundry.utils.duplicate(this.getCompetence(meditation.system.competence));
competence.system.defaut_carac = "intellect"; // Meditation = toujours avec intellect competence.system.defaut_carac = "intellect"; // Meditation = toujours avec intellect
let meditationData = { let meditationData = {
competence: competence, competence: competence,
@ -2128,7 +2144,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
let draconicList = this.getDraconicList() let draconicList = this.getDraconicList()
.map(draconic => { .map(draconic => {
let draconicLecture = duplicate(draconic); let draconicLecture = foundry.utils.duplicate(draconic);
draconicLecture.system.defaut_carac = "intellect"; draconicLecture.system.defaut_carac = "intellect";
return draconicLecture; return draconicLecture;
}); });
@ -2252,7 +2268,7 @@ export class RdDActor extends RdDBaseActorSang {
async _appliquerExperience(rolled, caracName, competence, jetResistance) { async _appliquerExperience(rolled, caracName, competence, jetResistance) {
// Pas d'XP // Pas d'XP
if (!rolled.isPart || rolled.finalLevel >= 0) { if (!rolled.isPart || rolled.finalLevel >= 0) {
return undefined; return []
} }
if (this.checkDesirLancinant()) { if (this.checkDesirLancinant()) {
// Cas de désir lancinant, pas d'expérience sur particulière // Cas de désir lancinant, pas d'expérience sur particulière
@ -2260,11 +2276,9 @@ export class RdDActor extends RdDBaseActorSang {
content: `Vous souffrez au moins d'un Désir Lancinant, vous ne pouvez pas gagner d'expérience sur une Particulière tant que le désir n'est pas assouvi`, content: `Vous souffrez au moins d'un Désir Lancinant, vous ne pouvez pas gagner d'expérience sur une Particulière tant que le désir n'est pas assouvi`,
whisper: ChatMessage.getWhisperRecipients(this.name) whisper: ChatMessage.getWhisperRecipients(this.name)
}); });
return undefined; return []
} }
if (caracName == 'Vie') caracName = 'constitution';
if (caracName == 'derobee') caracName = 'agilite';
if (caracName == 'reve-actuel') caracName = 'reve';
let xp = Math.abs(rolled.finalLevel); let xp = Math.abs(rolled.finalLevel);
// impair: arrondi inférieur en carac // impair: arrondi inférieur en carac
let xpCarac = competence ? Math.floor(xp / 2) : Math.max(Math.floor(xp / 2), 1); let xpCarac = competence ? Math.floor(xp / 2) : Math.max(Math.floor(xp / 2), 1);
@ -2277,11 +2291,10 @@ export class RdDActor extends RdDBaseActorSang {
// max 1 xp sur jets de résistance // max 1 xp sur jets de résistance
xpCarac = Math.min(1, xpCarac); xpCarac = Math.min(1, xpCarac);
} }
let xpData = { alias: this.name, caracName, xpCarac, competence, xpCompetence }; return [
...(await this._xpCompetence({ competence, xpCompetence })),
await this._xpCompetence(xpData); ...(await this._xpCarac({ caracName, xpCarac }))
await this._xpCarac(xpData); ];
return xpData;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -2289,52 +2302,87 @@ export class RdDActor extends RdDBaseActorSang {
if (xpData.competence) { if (xpData.competence) {
const from = Number(xpData.competence.system.xp); const from = Number(xpData.competence.system.xp);
const to = from + xpData.xpCompetence; const to = from + xpData.xpCompetence;
let update = { _id: xpData.competence._id, 'system.xp': to }; await this.updateEmbeddedDocuments('Item', [{ _id: xpData.competence._id, 'system.xp': to }]);
await this.updateEmbeddedDocuments('Item', [update]);
xpData.checkComp = await this.checkCompetenceXP(xpData.competence.name, undefined, false); xpData.checkComp = await this.checkCompetenceXP(xpData.competence.name, undefined, false);
await ExperienceLog.add(this, XP_TOPIC.XP, from, to, xpData.competence.name); await ExperienceLog.add(this, XP_TOPIC.XP, from, to, xpData.competence.name);
return [xpData]
} }
return []
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _xpCarac(xpData) { async _xpCarac(xpData) {
if (xpData.xpCarac > 0) { if (xpData.xpCarac > 0) {
let carac = duplicate(this.system.carac); const carac = foundry.utils.duplicate(this.system.carac)
let selectedCarac = RdDBaseActor._findCaracByName(carac, xpData.caracName); const code = RdDBaseActor._findCaracNode(carac, xpData.caracName)
if (!selectedCarac.derivee) { const selectedCarac = carac[code]
const from = Number(selectedCarac.xp); if (this.isCaracMax(code)) {
const to = from + xpData.xpCarac; ui.notifications.info(`Pas d'expérience: la caractéristique '${selectedCarac.label}' est déjà au maximum pour ${this.name}`)
selectedCarac.xp = to; return []
await this.update({ "system.carac": carac });
xpData.checkCarac = await this.checkCaracXP(selectedCarac.label, false);
await ExperienceLog.add(this, XP_TOPIC.XPCARAC, from, to, xpData.caracName);
} else {
xpData.caracRepartitionManuelle = true;
} }
if (selectedCarac && !selectedCarac.derivee) {
const from = Number(selectedCarac.xp)
const to = from + xpData.xpCarac
selectedCarac.xp = to
await this.update({ "system.carac": carac })
xpData.checkCarac = await this.checkCaracXP(selectedCarac.label, false)
await ExperienceLog.add(this, XP_TOPIC.XPCARAC, from, to, xpData.caracName)
return [xpData]
} else {
return await this._xpCaracDerivee(xpData)
}
}
return []
}
async _xpCaracDerivee(xpData) {
const caracs = RdDActor._getComposantsCaracDerivee(xpData.caracName)
.map(c => foundry.utils.mergeObject(this.system.carac[c], { isMax: this.isCaracMax(c) }))
switch (caracs.filter(it => !it.isMax).length) {
case 0:
xpData.caracRepartitionManuelle = true;
return [xpData]
case 1:
xpData.caracName = caracs.find(it => !it.isMax).label
return this._xpCarac(xpData)
default:
await DialogChoixXpCarac.choix(this, xpData, caracs)
return []
} }
} }
static _getComposantsCaracDerivee(caracName) {
switch (Grammar.toLowerCaseNoAccent(caracName)) {
case 'vie': return ['constitution']
case 'tir': return ['vue', 'dexterite']
case 'lancer': return ['force', 'dexterite', 'vue']
case 'melee': return ['force', 'agilite']
case 'derobee': return ['agilite']
}
return []
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async resetNombresAstraux() { async deleteNombresAstraux() {
const deletions = this.itemTypes['nombreastral'].map(it => it._id); const deletions = this.itemTypes['nombreastral'].map(it => it._id);
await this.deleteEmbeddedDocuments("Item", deletions); await this.deleteEmbeddedDocuments("Item", deletions);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async ajouteNombreAstral(callData) { async ajouteNombreAstral(date, nbAstral, isValid) {
const indexDate = Number.parseInt(callData.date); const indexDate = Number.parseInt(date);
// Ajout du nombre astral // Ajout du nombre astral
const item = { const item = {
name: "Nombre Astral", type: "nombreastral", system: name: "Nombre Astral", type: "nombreastral", system:
{ {
value: callData.nbAstral, value: nbAstral,
istrue: callData.isvalid, istrue: isValid,
jourindex: indexDate, jourindex: indexDate,
jourlabel: RdDTimestamp.formatIndexDate(indexDate) jourlabel: RdDTimestamp.formatIndexDate(indexDate)
} }
}; };
await this.createEmbeddedDocuments("Item", [item]); await this.createEmbeddedDocuments("Item", [item]);
game.system.rdd.calendrier.notifyChangeNombresAstraux();
} }
async supprimerAnciensNombresAstraux() { async supprimerAnciensNombresAstraux() {
@ -2415,7 +2463,7 @@ export class RdDActor extends RdDBaseActorSang {
draconic: this.getDraconicList(), draconic: this.getDraconicList(),
sort: this.itemTypes['sort'], sort: this.itemTypes['sort'],
signes: this.itemTypes['signedraconique'], signes: this.itemTypes['signedraconique'],
caracReve: this.system.carac.reve.value, caracReve: parseInt(this.system.carac.reve.value),
pointsReve: this.getReveActuel(), pointsReve: this.getReveActuel(),
isRapide: isRapide, isRapide: isRapide,
isGM: game.user.isGM, isGM: game.user.isGM,
@ -2506,7 +2554,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
verifierForceMin(item) { verifierForceMin(item) {
if (item.type == 'arme' && item.system.force > this.system.carac.force.value) { if (item.type == 'arme' && item.system.force > parseInt(this.system.carac.force.value)) {
ChatMessage.create({ ChatMessage.create({
content: `<strong>${this.name} s'est équipé(e) de l'arme ${item.name}, mais n'a pas une force suffisante pour l'utiliser normalement </strong> content: `<strong>${this.name} s'est équipé(e) de l'arme ${item.name}, mais n'a pas une force suffisante pour l'utiliser normalement </strong>
(${item.system.force} nécessaire pour une Force de ${this.system.carac.force.value})` (${item.system.force} nécessaire pour une Force de ${this.system.carac.force.value})`
@ -2568,7 +2616,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async incDecItemUse(itemId, inc = 1) { async incDecItemUse(itemId, inc = 1) {
let itemUse = duplicate(this.getFlag(SYSTEM_RDD, 'itemUse') ?? {}); let itemUse = foundry.utils.duplicate(this.getFlag(SYSTEM_RDD, 'itemUse') ?? {});
itemUse[itemId] = (itemUse[itemId] ?? 0) + inc; itemUse[itemId] = (itemUse[itemId] ?? 0) + inc;
await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse); await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse);
console.log("ITEM USE INC", inc, itemUse); console.log("ITEM USE INC", inc, itemUse);
@ -2636,7 +2684,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
static $transformSubActeurSuivant = (suivant, link) => { static $transformSubActeurSuivant = (suivant, link) => {
return mergeObject(RdDBaseActor.extractActorMin(suivant), { return foundry.utils.mergeObject(RdDBaseActor.extractActorMin(suivant), {
ephemere: !suivant.prototypeToken.actorLink, ephemere: !suivant.prototypeToken.actorLink,
coeur: link.coeur ?? 0, coeur: link.coeur ?? 0,
prochainCoeur: link.prochainCoeur ?? link.coeur ?? 0 prochainCoeur: link.prochainCoeur ?? link.coeur ?? 0
@ -2662,7 +2710,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
async setPointsCoeur(subActorId, coeurs, options = { immediat: false }) { async setPointsCoeur(subActorId, coeurs, options = { immediat: false }) {
const newSuivants = duplicate(this.system.subacteurs.suivants) const newSuivants = foundry.utils.duplicate(this.system.subacteurs.suivants)
const amoureux = newSuivants.find(it => it.id == subActorId); const amoureux = newSuivants.find(it => it.id == subActorId);
if (amoureux) { if (amoureux) {
amoureux[options.immediat ? 'coeur' : 'prochainCoeur'] = coeurs amoureux[options.immediat ? 'coeur' : 'prochainCoeur'] = coeurs
@ -2672,7 +2720,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
static $transformSubActeurVehicule = (vehicle, link) => { static $transformSubActeurVehicule = (vehicle, link) => {
return mergeObject(RdDBaseActor.extractActorMin(vehicle), { return foundry.utils.mergeObject(RdDBaseActor.extractActorMin(vehicle), {
system: { categorie: vehicle.system.categorie, etat: vehicle.system.etat } system: { categorie: vehicle.system.categorie, etat: vehicle.system.etat }
}) })
}; };
@ -2920,9 +2968,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
isEffectAllowed(statusId) { isEffectAllowed(effectId) { return true }
return true
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async onPreUpdateItem(item, change, options, id) { async onPreUpdateItem(item, change, options, id) {
@ -3018,7 +3064,7 @@ export class RdDActor extends RdDBaseActorSang {
incarnation.name = 'Réincarnation de ' + incarnation.name incarnation.name = 'Réincarnation de ' + incarnation.name
incarnation.system = { incarnation.system = {
carac: duplicate(this.system.carac), carac: foundry.utils.duplicate(this.system.carac),
heure: RdDTimestamp.defHeure(await RdDDice.rollTotal("1dh", { rollMode: "selfroll", showDice: SHOW_DICE })).key, heure: RdDTimestamp.defHeure(await RdDDice.rollTotal("1dh", { rollMode: "selfroll", showDice: SHOW_DICE })).key,
age: 18, age: 18,
biographie: '', biographie: '',

View File

@ -11,7 +11,7 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(RdDBaseActorSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorSheet.defaultOptions, {
width: 550 width: 550
}); });
} }

View File

@ -180,32 +180,32 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
isEffectAllowed(statusId) { return true } isEffectAllowed(effectId) { return true }
getEffects(filter = e => true) { getEffects(filter = e => true) {
return this.getEmbeddedCollection("ActiveEffect").filter(filter); return this.getEmbeddedCollection("ActiveEffect").filter(filter);
} }
getEffect(statusId) { getEffect(effectId) {
return this.getEmbeddedCollection("ActiveEffect").find(it => it.flags?.core?.statusId == statusId); return this.getEmbeddedCollection("ActiveEffect").find(it => it.statuses?.has(effectId));
} }
async setEffect(statusId, status) { async setEffect(effectId, status) {
if (this.isEffectAllowed(statusId)) { if (this.isEffectAllowed(effectId)) {
const effect = this.getEffect(statusId); const effect = this.getEffect(effectId);
if (!status && effect) { if (!status && effect) {
await this.deleteEmbeddedDocuments('ActiveEffect', [effect.id]); await this.deleteEmbeddedDocuments('ActiveEffect', [effect.id]);
} }
if (status && !effect) { if (status && !effect) {
await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.status(statusId)]); await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.prepareActiveEffect(effectId)]);
} }
} }
} }
async removeEffect(statusId) { async removeEffect(id) {
const effect = this.getEffect(statusId); const effect = this.getEmbeddedCollection("ActiveEffect").find(it => it.id == id);
if (effect) { if (effect) {
await this.deleteEmbeddedDocuments('ActiveEffect', [effect.id]); await this.deleteEmbeddedDocuments('ActiveEffect', [id]);
} }
} }
@ -286,7 +286,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
getCarac() { getCarac() {
// TODO: le niveau d'une entité de cauchemar devrait être exclu... // TODO: le niveau d'une entité de cauchemar devrait être exclu...
const carac = mergeObject(duplicate(this.system.carac), const carac = foundry.utils.mergeObject(foundry.utils.duplicate(this.system.carac),
{ {
'reve-actuel': this.getCaracReveActuel(), 'reve-actuel': this.getCaracReveActuel(),
'chance-actuelle': this.getCaracChanceActuelle() 'chance-actuelle': this.getCaracChanceActuelle()
@ -425,28 +425,31 @@ export class RdDBaseActorReve extends RdDBaseActor {
if (attacker && !await attacker.accorder(this, 'avant-encaissement')) { if (attacker && !await attacker.accorder(this, 'avant-encaissement')) {
return; return;
} }
const attackerId = attacker?.id;
if (ReglesOptionnelles.isUsing('validation-encaissement-gr') && !game.user.isGM) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'encaisserDommages',
args: [rollData, show, attackerId]
});
return;
}
const armure = await this.computeArmure(rollData); const armure = await this.computeArmure(rollData);
if (ReglesOptionnelles.isUsing('validation-encaissement-gr')) { if (ReglesOptionnelles.isUsing('validation-encaissement-gr')){
DialogValidationEncaissement.validerEncaissement(this, rollData, armure, await this.encaisserDommagesValidationGR(rollData, armure, attacker?.id, show);
jet => this.$onEncaissement(jet, show, attacker)); }
}
else { else {
const jet = await RdDUtility.jetEncaissement(rollData, armure, { showDice: SHOW_DICE }); const jet = await RdDUtility.jetEncaissement(rollData, armure, { showDice: SHOW_DICE });
await this.$onEncaissement(jet, show, attacker); await this.$onEncaissement(jet, show, attacker);
} }
} }
async encaisserDommagesValidationGR(rollData, armure, attackerId, show) {
if (!game.user.isGM) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'encaisserDommagesValidationGR',
args: [rollData, armure, attackerId, show]
});
} else {
const attacker = game.actors.get(attackerId);
DialogValidationEncaissement.validerEncaissement(this, rollData, armure,
jet => this.$onEncaissement(jet, show, attacker));
}
}
async $onEncaissement(jet, show, attacker) { async $onEncaissement(jet, show, attacker) {
await this.onAppliquerJetEncaissement(jet, attacker); await this.onAppliquerJetEncaissement(jet, attacker);
await this.$afficherEncaissement(jet, show); await this.$afficherEncaissement(jet, show);
@ -455,7 +458,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
async onAppliquerJetEncaissement(encaissement, attacker) { } async onAppliquerJetEncaissement(encaissement, attacker) { }
async $afficherEncaissement(encaissement, show) { async $afficherEncaissement(encaissement, show) {
mergeObject(encaissement, { foundry.utils.mergeObject(encaissement, {
alias: this.name, alias: this.name,
hasPlayerOwner: this.hasPlayerOwner, hasPlayerOwner: this.hasPlayerOwner,
show: show ?? {} show: show ?? {}
@ -467,7 +470,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
}); });
if (!encaissement.hasPlayerOwner && encaissement.endurance != 0) { if (!encaissement.hasPlayerOwner && encaissement.endurance != 0) {
encaissement = duplicate(encaissement); encaissement = foundry.utils.duplicate(encaissement);
encaissement.isGM = true; encaissement.isGM = true;
ChatMessage.create({ ChatMessage.create({
whisper: ChatMessage.getWhisperRecipients("GM"), whisper: ChatMessage.getWhisperRecipients("GM"),

View File

@ -21,6 +21,11 @@ export class RdDBaseActorSangSheet extends RdDBaseActorReveSheet {
this.html.find('.creer-blessure-grave').click(async event => RdDItemBlessure.createBlessure(this.actor, 4)); this.html.find('.creer-blessure-grave').click(async event => RdDItemBlessure.createBlessure(this.actor, 4));
this.html.find('.creer-blessure-critique').click(async event => RdDItemBlessure.createBlessure(this.actor, 6)); this.html.find('.creer-blessure-critique').click(async event => RdDItemBlessure.createBlessure(this.actor, 6));
this.html.find('.subir-blessure-contusion').click(async event => RdDItemBlessure.applyFullBlessure(this.actor, 2));
this.html.find('.subir-blessure-legere').click(async event => RdDItemBlessure.applyFullBlessure(this.actor, 2));
this.html.find('.subir-blessure-grave').click(async event => RdDItemBlessure.applyFullBlessure(this.actor, 4));
this.html.find('.subir-blessure-critique').click(async event => RdDItemBlessure.applyFullBlessure(this.actor, 6));
this.html.find('.jet-vie').click(async event => this.actor.jetDeVie()) this.html.find('.jet-vie').click(async event => this.actor.jetDeVie())
this.html.find('.jet-endurance').click(async event => await this.jetEndurance()) this.html.find('.jet-endurance').click(async event => await this.jetEndurance())

View File

@ -89,12 +89,12 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
/* -------------------------------------------- */ /* -------------------------------------------- */
async onAppliquerJetEncaissement(encaissement, attacker) { async onAppliquerJetEncaissement(encaissement, attacker) {
const santeOrig = duplicate(this.system.sante); const santeOrig = foundry.utils.duplicate(this.system.sante);
const blessure = await this.ajouterBlessure(encaissement, attacker); // Will update the result table const blessure = await this.ajouterBlessure(encaissement, attacker); // Will update the result table
const perteVie = await this.santeIncDec("vie", -encaissement.vie); const perteVie = await this.santeIncDec("vie", -encaissement.vie);
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, blessure?.isCritique()); const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, blessure?.isCritique());
mergeObject(encaissement, { foundry.utils.mergeObject(encaissement, {
resteEndurance: perteEndurance.newValue, resteEndurance: perteEndurance.newValue,
sonne: perteEndurance.sonne, sonne: perteEndurance.sonne,
jetEndurance: perteEndurance.jetEndurance, jetEndurance: perteEndurance.jetEndurance,
@ -108,7 +108,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) { if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
return; return;
} }
const sante = duplicate(this.system.sante) const sante = foundry.utils.duplicate(this.system.sante)
let compteur = sante[name]; let compteur = sante[name];
if (!compteur) { if (!compteur) {
return; return;
@ -135,7 +135,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
result.perte = perte; result.perte = perte;
if (perte > 1) { if (perte > 1) {
// Peut-être sonné si 2 points d'endurance perdus d'un coup // Peut-être sonné si 2 points d'endurance perdus d'un coup
mergeObject(result, await this.jetEndurance(result.newValue)); foundry.utils.mergeObject(result, await this.jetEndurance(result.newValue));
} else if (inc > 0) { } else if (inc > 0) {
await this.setSonne(false); await this.setSonne(false);
} }

View File

@ -15,7 +15,7 @@ export class RdDBaseActorSheet extends ActorSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(ActorSheet.defaultOptions, { return foundry.utils.mergeObject(ActorSheet.defaultOptions, {
classes: ["rdd", "sheet", "actor"], classes: ["rdd", "sheet", "actor"],
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 }],
@ -312,7 +312,7 @@ export class RdDBaseActorSheet extends ActorSheet {
async _onSplitItem(item, split) { async _onSplitItem(item, split) {
if (split >= 1 && split < item.system.quantite) { if (split >= 1 && split < item.system.quantite) {
await item.diminuerQuantite(split); await item.diminuerQuantite(split);
const splitItem = duplicate(item); const splitItem = foundry.utils.duplicate(item);
splitItem.system.quantite = split; splitItem.system.quantite = split;
await this.actor.createEmbeddedDocuments('Item', [splitItem]) await this.actor.createEmbeddedDocuments('Item', [splitItem])
} }

View File

@ -11,16 +11,14 @@ import { SystemCompendiums } from "../settings/system-compendiums.js";
import { APP_ASTROLOGIE_REFRESH } from "../sommeil/app-astrologie.js"; import { APP_ASTROLOGIE_REFRESH } from "../sommeil/app-astrologie.js";
export class RdDBaseActor extends Actor { export class RdDBaseActor extends Actor {
/* -------------------------------------------- */
static _findCaracByName(carac, name) {
name = Grammar.toLowerCaseNoAccent(name);
switch (name) {
case 'reve-actuel': case 'reve actuel':
return carac.reve;
case 'chance-actuelle': case 'chance actuelle':
return carac.chance;
}
static _findCaracNode(carac, name) {
return Object.entries(carac)
.filter(it => Grammar.equalsInsensitive(it[1].label, name))
.map(it => it[0])
.find(it => it);
}
static $findCaracByName(carac, name) {
const caracList = Object.entries(carac); const caracList = Object.entries(carac);
let entry = Misc.findFirstLike(name, caracList, { mapper: it => it[0], description: 'caractéristique' }); let entry = Misc.findFirstLike(name, caracList, { mapper: it => it[0], description: 'caractéristique' });
if (!entry || entry.length == 0) { if (!entry || entry.length == 0) {
@ -44,13 +42,6 @@ export class RdDBaseActor extends Actor {
switch (sockmsg.msg) { switch (sockmsg.msg) {
case "msg_remote_actor_call": case "msg_remote_actor_call":
return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId); return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId);
case "msg_reset_nombre_astral":
game.user.character.resetNombresAstraux();
game.system.rdd.calendrier.notifyChangeNombresAstraux();
return;
case "msg_refresh_nombre_astral":
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
return;
} }
} }
@ -87,6 +78,8 @@ export class RdDBaseActor extends Actor {
return game.actors.get(actorId) return game.actors.get(actorId)
} }
isPersonnageJoueur() { return false }
static extractActorMin = (actor) => { return { id: actor?.id, type: actor?.type, name: actor?.name, img: actor?.img }; }; static extractActorMin = (actor) => { return { id: actor?.id, type: actor?.type, name: actor?.name, img: actor?.img }; };
static getParentActor(document) { static getParentActor(document) {
@ -123,7 +116,7 @@ export class RdDBaseActor extends Actor {
constructor(docData, context = {}) { constructor(docData, context = {}) {
if (!context.rdd?.ready) { if (!context.rdd?.ready) {
mergeObject(context, { rdd: { ready: true } }); foundry.utils.mergeObject(context, { rdd: { ready: true } });
const ActorConstructor = game.system.rdd.actorClasses[docData.type]; const ActorConstructor = game.system.rdd.actorClasses[docData.type];
if (ActorConstructor) { if (ActorConstructor) {
if (!docData.img) { if (!docData.img) {
@ -135,6 +128,21 @@ export class RdDBaseActor extends Actor {
super(docData, context); super(docData, context);
} }
findCaracByName(name) {
name = Grammar.toLowerCaseNoAccent(name)
switch (name) {
case 'reve-actuel': case 'reve actuel':
return this.system.carac.reve
case 'chance-actuelle': case 'chance actuelle':
return this.system.carac.chance
case 'vie':
return this.system.sante.vie
}
const carac = this.system.carac;
return RdDBaseActor.$findCaracByName(carac, name);
}
getCaracByName(name) { getCaracByName(name) {
switch (Grammar.toLowerCaseNoAccent(name)) { switch (Grammar.toLowerCaseNoAccent(name)) {
case 'reve-actuel': case 'reve actuel': case 'reve-actuel': case 'reve actuel':
@ -142,7 +150,7 @@ export class RdDBaseActor extends Actor {
case 'chance-actuelle': case 'chance-actuelle': case 'chance-actuelle': case 'chance-actuelle':
return this.getCaracChanceActuelle(); return this.getCaracChanceActuelle();
} }
return RdDBaseActor._findCaracByName(this.system.carac, name); return this.findCaracByName(name);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -187,7 +195,7 @@ export class RdDBaseActor extends Actor {
} }
listeSuivants(filter = suivant => true) { return [] } listeSuivants(filter = suivant => true) { return [] }
listeSuivants(filter = suivant =>true) { return [] } listeSuivants(filter = suivant => true) { return [] }
listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); } listItems(type = undefined) { return (type ? this.itemTypes[type] : this.items); }
filterItems(filter, type = undefined) { return (type ? this.itemTypes[type] : this.items)?.filter(filter) ?? []; } filterItems(filter, type = undefined) { return (type ? this.itemTypes[type] : this.items)?.filter(filter) ?? []; }
findItemLike(idOrName, type) { findItemLike(idOrName, type) {
@ -362,7 +370,7 @@ export class RdDBaseActor extends Actor {
if (cout > 0) { if (cout > 0) {
RdDAudio.PlayContextAudio("argent"); RdDAudio.PlayContextAudio("argent");
} }
const chatAchatItem = duplicate(achat.vente); const chatAchatItem = foundry.utils.duplicate(achat.vente);
chatAchatItem.quantiteTotal = quantite; chatAchatItem.quantiteTotal = quantite;
ChatMessage.create({ ChatMessage.create({
user: achat.userId, user: achat.userId,
@ -438,7 +446,7 @@ export class RdDBaseActor extends Actor {
type: item.type, type: item.type,
img: item.img, img: item.img,
name: item.name, name: item.name,
system: mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }) system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined })
}; };
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem); const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
const items = await this.createEmbeddedDocuments("Item", newItems); const items = await this.createEmbeddedDocuments("Item", newItems);
@ -634,7 +642,7 @@ export class RdDBaseActor extends Actor {
sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list
const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id)) const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id))
.map(it => duplicate(it)) .map(it => foundry.utils.duplicate(it))
.map(it => { it.system.contenu = []; return it; }); .map(it => { it.system.contenu = []; return it; });
let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate); let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate);

View File

@ -11,7 +11,7 @@ export class RdDCommerceSheet extends RdDBaseActorSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.html",
width: 600, height: 720, width: 600, height: 720,
tabs: [] tabs: []
@ -27,7 +27,7 @@ export class RdDCommerceSheet extends RdDBaseActorSheet {
async getData() { async getData() {
const formData = await super.getData(); const formData = await super.getData();
if (this.actor.token && this.actor.token != this.actor.prototypeToken) { if (this.actor.token && this.actor.token != this.actor.prototypeToken) {
mergeObject(formData, foundry.utils.mergeObject(formData,
{ {
title: this.actor.token.name, title: this.actor.token.name,
token: { token: {

View File

@ -9,7 +9,7 @@ export class RdDCreatureSheet extends RdDBaseActorSangSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(RdDBaseActorSangSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorSangSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html",
width: 640, height: 720 width: 640, height: 720
}); });

View File

@ -33,8 +33,8 @@ export class RdDCreature extends RdDBaseActorSang {
} }
} }
isEffectAllowed(statusId) { isEffectAllowed(effectId) {
return [STATUSES.StatusComma].includes(statusId); return [STATUSES.StatusComma].includes(effectId);
} }
isEntiteAccordee(attacker) { isEntiteAccordee(attacker) {
@ -48,7 +48,7 @@ export class RdDCreature extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async setEntiteReveAccordee(attacker) { async setEntiteReveAccordee(attacker) {
if (this.isEntite([ENTITE_INCARNE])) { if (this.isEntite([ENTITE_INCARNE])) {
let resonnance = duplicate(this.system.sante.resonnance); let resonnance = foundry.utils.duplicate(this.system.sante.resonnance);
if (resonnance.actors.find(it => it == attacker.id)) { if (resonnance.actors.find(it => it == attacker.id)) {
// déjà accordé // déjà accordé
return; return;

View File

@ -6,7 +6,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(RdDBaseActorReveSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html",
width: 640, height: 720, width: 640, height: 720,
}); });

View File

@ -70,13 +70,13 @@ export class RdDEntite extends RdDBaseActorReve {
await RdDEncaisser.encaisser(this) await RdDEncaisser.encaisser(this)
} }
isEffectAllowed(statusId) { isEffectAllowed(effectId) {
return [STATUSES.StatusComma].includes(statusId); return [STATUSES.StatusComma].includes(effectId);
} }
async onAppliquerJetEncaissement(encaissement, attacker) { async onAppliquerJetEncaissement(encaissement, attacker) {
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance); const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance);
mergeObject(encaissement, { foundry.utils.mergeObject(encaissement, {
resteEndurance: perteEndurance.newValue, resteEndurance: perteEndurance.newValue,
endurance: perteEndurance.perte endurance: perteEndurance.perte
}); });
@ -93,7 +93,7 @@ export class RdDEntite extends RdDBaseActorReve {
/* -------------------------------------------- */ /* -------------------------------------------- */
async setEntiteReveAccordee(attacker) { async setEntiteReveAccordee(attacker) {
if (this.isEntite([ENTITE_INCARNE])) { if (this.isEntite([ENTITE_INCARNE])) {
let resonnance = duplicate(this.system.sante.resonnance); let resonnance = foundry.utils.duplicate(this.system.sante.resonnance);
if (resonnance.actors.find(it => it == attacker.id)) { if (resonnance.actors.find(it => it == attacker.id)) {
// déjà accordé // déjà accordé
return; return;

View File

@ -12,7 +12,7 @@ export const XP_TOPIC = {
export class ExperienceLog { export class ExperienceLog {
static async add(actor, topic, from, to, raison, manuel = false) { static async add(actor, topic, from, to, raison, manuel = false) {
if (!actor.hasPlayerOwner || !actor.isPersonnage()) { if (!actor.isPersonnageJoueur()) {
return return
} }
if (from == to) { if (from == to) {

View File

@ -6,7 +6,7 @@ export class RdDActorVehiculeSheet extends RdDBaseActorSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(RdDBaseActorSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html",
width: 640, height: 720, width: 640, height: 720,
}); });
@ -15,7 +15,7 @@ export class RdDActorVehiculeSheet extends RdDBaseActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
let formData = await super.getData(); let formData = await super.getData();
mergeObject(formData, foundry.utils.mergeObject(formData,
{ {
editable: this.isEditable, editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked", cssClass: this.isEditable ? "editable" : "locked",

View File

@ -131,7 +131,7 @@ export class ChatUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static blindMessageToGM(chatOptions) { static blindMessageToGM(chatOptions) {
let chatGM = duplicate(chatOptions); let chatGM = foundry.utils.duplicate(chatOptions);
chatGM.whisper = ChatUtility.getUsers(user => user.isGM); chatGM.whisper = ChatUtility.getUsers(user => user.isGM);
chatGM.content = "Message aveugle de " + game.user.name + "<br>" + chatOptions.content; chatGM.content = "Message aveugle de " + game.user.name + "<br>" + chatOptions.content;
console.log("blindMessageToGM", chatGM); console.log("blindMessageToGM", chatGM);

View File

@ -69,7 +69,7 @@ export class RdDCoeur {
} }
static async applyCoeurChateauDormant(actor, message) { static async applyCoeurChateauDormant(actor, message) {
const newSuivants = duplicate(actor.system.subacteurs.suivants) const newSuivants = foundry.utils.duplicate(actor.system.subacteurs.suivants)
let count = 0 let count = 0
newSuivants.forEach(async link => { newSuivants.forEach(async link => {
const suivant = game.actors.get(link.id) const suivant = game.actors.get(link.id)

View File

@ -0,0 +1,84 @@
export class DialogChoixXpCarac extends Dialog {
static async choix(actor, xpData, caracs) {
caracs = caracs.map(it => foundry.utils.mergeObject({ ajout: 0 }, it))
xpData = foundry.utils.mergeObject({ reste: xpData.xpCarac }, xpData)
const dialogData = {
title: `Choisissez la répartition d'expérience`,
content: await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-choix-xp-carac.hbs", {
actor,
caracDerivee: actor.findCaracByName(xpData.caracName),
xpData,
caracs
}),
}
const dialogOptions = {
classes: ["rdd-dialog-select"],
width: 400,
height: 'fit-content',
'z-index': 99999
}
new DialogChoixXpCarac(dialogData, dialogOptions, actor, xpData, caracs).render(true)
}
constructor(dialogData, dialogOptions, actor, xpData, caracs) {
dialogData = foundry.utils.mergeObject(dialogData, {
default: 'appliquer',
buttons: {
'appliquer': { icon:'<i class="fa-solid fa-check"></i>', label: "Ajouter la répartition", callback: it => this.appliquerSelection() }
}
})
super(dialogData, dialogOptions)
this.actor = actor
this.xpData = xpData
this.caracs = caracs
}
activateListeners(html) {
//TODO
super.activateListeners(html)
this.html = html
this.html.find("li.xpCarac-option .xpCarac-moins").click(event =>
this.ajouterXp(event, -1)
)
this.html.find("li.xpCarac-option .xpCarac-plus").click(event =>
this.ajouterXp(event, 1)
)
}
async ajouterXp(event, delta) {
const liCarac = this.html.find(event.currentTarget)?.parents("li.xpCarac-option")
const label = liCarac?.data("carac-label")
const carac = this.caracs.find(c => c.label == label)
if (carac.ajout + delta < 0) {
ui.notifications.warn(`Impossible de diminuer les points à répartir en ${carac.label} en dessous de 0`)
return
}
if (this.xpData.reste - delta < 0) {
ui.notifications.warn(`Il ne reste plus de points à répartir en ${carac.label}`)
return
}
carac.ajout += delta
this.xpData.reste -= delta
liCarac.find("input.xpCarac-view-ajout").val(carac.ajout)
this.html.find("input.xpCarac-reste").val(this.xpData.reste)
}
async appliquerSelection() {
if (this.xpData.reste > 0) {
ui.notifications.warn(`Il vous reste ${this.xpData.reste} points à répartir`)
return
}
this.caracs.filter(c => c.ajout > 0).forEach(c => {
const xpData = { caracName: c.label, xpCarac: c.ajout }
this.actor._xpCarac(xpData)
})
await super.close()
}
async close() { }
_getHeaderButtons() { return [] }
}

View File

@ -21,7 +21,7 @@ export class DialogFabriquerPotion extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
static prepareData(actor, item) { static prepareData(actor, item) {
let potionData = duplicate(item) let potionData = foundry.utils.duplicate(item)
potionData.nbBrinsSelect = RdDUtility.buildListOptions( potionData.nbBrinsSelect = RdDUtility.buildListOptions(
DialogFabriquerPotion.nombreBrinsMinimum(item), DialogFabriquerPotion.nombreBrinsMinimum(item),
DialogFabriquerPotion.nombreBrinsOptimal(item)); DialogFabriquerPotion.nombreBrinsOptimal(item));

View File

@ -47,7 +47,7 @@ export class DialogConsommer extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
static prepareData(actor, item) { static prepareData(actor, item) {
let consommerData = { let consommerData = {
item: duplicate(item), item: foundry.utils.duplicate(item),
cuisine: actor.getCompetence('cuisine'), cuisine: actor.getCompetence('cuisine'),
choix: { choix: {
doses: 1, doses: 1,

View File

@ -56,7 +56,7 @@ export class DialogItemVente extends Dialog {
} }
updateVente(update) { updateVente(update) {
mergeObject(this.venteData, update); foundry.utils.mergeObject(this.venteData, update);
} }
getChoixVente() { getChoixVente() {

View File

@ -139,7 +139,7 @@ export class RdDItemArme extends Item {
const uneOuDeuxMains = armeData.system.unemain && armeData.system.deuxmains; const uneOuDeuxMains = armeData.system.unemain && armeData.system.deuxmains;
const containsSlash = !Number.isInteger(armeData.system.dommages) && armeData.system.dommages.includes("/"); const containsSlash = !Number.isInteger(armeData.system.dommages) && armeData.system.dommages.includes("/");
if (containsSlash) { // Sanity check if (containsSlash) { // Sanity check
armeData = duplicate(armeData); armeData = foundry.utils.duplicate(armeData);
const tableauDegats = armeData.system.dommages.split("/"); const tableauDegats = armeData.system.dommages.split("/");
if (aUneMain) if (aUneMain)

View File

@ -199,7 +199,7 @@ export class RdDItemCompetence extends Item {
if (idOrName == undefined || idOrName == "") { if (idOrName == undefined || idOrName == "") {
return RdDItemCompetence.sansCompetence(); return RdDItemCompetence.sansCompetence();
} }
options = mergeObject(options, { preFilter: it => it.isCompetence(), description: 'compétence' }, { overwrite: false }); options = foundry.utils.mergeObject(options, { preFilter: it => it.isCompetence(), description: 'compétence' }, { overwrite: false });
return RdDItemCompetence.findFirstItem(list, idOrName, options); return RdDItemCompetence.findFirstItem(list, idOrName, options);
} }
@ -257,7 +257,7 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeResumeArchetype(competences) { static computeResumeArchetype(competences) {
const computed = duplicate(limitesArchetypes); const computed = foundry.utils.duplicate(limitesArchetypes);
computed.forEach(it => { it.nombre = 0; it.reste = it.nombreMax; }); computed.forEach(it => { it.nombre = 0; it.reste = it.nombreMax; });
competences.map(it => Math.max(0, it.system.niveau_archetype)) competences.map(it => Math.max(0, it.system.niveau_archetype))

View File

@ -33,7 +33,7 @@ export class RdDItemCompetenceCreature extends Item {
if (categorieAttaque != undefined) { if (categorieAttaque != undefined) {
// si c'est un Item compétence: cloner pour ne pas modifier la compétence // si c'est un Item compétence: cloner pour ne pas modifier la compétence
let arme = item.clone(); let arme = item.clone();
mergeObject(arme, foundry.utils.mergeObject(arme,
{ {
action: item.isCompetencePossession() ? 'possession' : 'attaque', action: item.isCompetencePossession() ? 'possession' : 'attaque',
system: { system: {

View File

@ -57,7 +57,7 @@ export class Monnaie {
} }
static creerDeniers(fortune) { static creerDeniers(fortune) {
const deniers = duplicate(MONNAIE_ETAIN); const deniers = foundry.utils.duplicate(MONNAIE_ETAIN);
deniers.system.quantite = fortune; deniers.system.quantite = fortune;
return deniers; return deniers;
} }

View File

@ -39,7 +39,7 @@ export class RdDItemSheet extends ItemSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
classes: [SYSTEM_RDD, "sheet", "item"], classes: [SYSTEM_RDD, "sheet", "item"],
template: RdDItemSheet.defaultTemplate(RdDItemSheet.ITEM_TYPE), template: RdDItemSheet.defaultTemplate(RdDItemSheet.ITEM_TYPE),
width: 550, width: 550,
@ -108,8 +108,8 @@ export class RdDItemSheet extends ItemSheet {
const competences = await SystemCompendiums.getCompetences('personnage'); const competences = await SystemCompendiums.getCompetences('personnage');
formData.categories = this.item.getCategories() formData.categories = this.item.getCategories()
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') { if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
formData.caracList = duplicate(game.system.model.Actor.personnage.carac) formData.caracList = foundry.utils.duplicate(game.system.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve) formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.system.model.Actor.personnage.reve.reve)
formData.competences = competences; formData.competences = competences;
} }
if (this.item.type == 'arme') { if (this.item.type == 'arme') {
@ -228,7 +228,7 @@ export class RdDItemSheet extends ItemSheet {
}); });
} }
const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: duplicate(timestamp) }) const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: foundry.utils.duplicate(timestamp) })
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.debut', updateItemTimestamp); RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.debut', updateItemTimestamp);
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp); RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp);

View File

@ -317,8 +317,8 @@ export class RdDItem extends Item {
const timestampFin = await this.calculerFinPeriodeTemporel(timestampDebut); const timestampFin = await this.calculerFinPeriodeTemporel(timestampDebut);
await actor.updateEmbeddedDocuments('Item', [{ await actor.updateEmbeddedDocuments('Item', [{
_id: this.id, _id: this.id,
'system.temporel.debut': duplicate(timestampDebut), 'system.temporel.debut': foundry.utils.duplicate(timestampDebut),
'system.temporel.fin': duplicate(timestampFin), 'system.temporel.fin': foundry.utils.duplicate(timestampFin),
}]) }])
} }
} }

View File

@ -1,6 +1,7 @@
import { RdDItem } from "../item.js"; import { RdDItem } from "../item.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDTimestamp } from "../time/rdd-timestamp.js"; import { RdDTimestamp } from "../time/rdd-timestamp.js";
import { ChatUtility } from "../chat-utility.js";
const BASE_TACHE_SOIN_BLESSURE = { const BASE_TACHE_SOIN_BLESSURE = {
type: "tache", type: "tache",
@ -14,10 +15,10 @@ const TACHES_SOIN_BLESSURE = {
} }
const definitionsBlessures = [ const definitionsBlessures = [
{ type: "contusion", gravite: 0, label: 'Contusion/éraflure', max: 100, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/eraflure.webp" }, { type: "contusion", gravite: 0, endurance: "1d4", vie: 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: "legere", gravite: 2, endurance: "1d6", vie: 0, 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: "grave", gravite: 4, endurance: "2d6", vie: -2, 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: "critique", gravite: 6, endurance: "-100", vie: -4, 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" } { type: "mort", gravite: 8, label: 'Mort', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/mort.webp" }
] ]
@ -38,8 +39,34 @@ export class RdDItemBlessure extends RdDItem {
ui.notifications.warn(`Pas de tâche de soins pour une blessure ${gravite}`) ui.notifications.warn(`Pas de tâche de soins pour une blessure ${gravite}`)
return undefined; return undefined;
} }
return mergeObject(duplicate(BASE_TACHE_SOIN_BLESSURE), tache) return foundry.utils.mergeObject(foundry.utils.duplicate(BASE_TACHE_SOIN_BLESSURE), tache)
} }
static async applyFullBlessure(actor, gravite) {
const definition = RdDItemBlessure.getDefinition(gravite)
let lostEndurance = 0
let lostVie = 0
if (definition.endurance) {
lostEndurance = new Roll(definition.endurance).roll({async: false}).total;
actor.santeIncDec("endurance", -Number(lostEndurance));
}
if (definition.vie) {
lostVie = definition.vie
actor.santeIncDec("vie", definition.vie)
}
await this.createBlessure(actor, gravite)
ChatMessage.create({
content: `Blessure ${definition.label} appliquée à ${actor.name}`+
`<br>Perte d'endurance : ${lostEndurance}`+
`<br>Perte de Vie : ${lostVie}`,
whisper: ChatUtility.getWhisperRecipientsAndGMs(actor.name)
});
}
static async createBlessure(actor, gravite, localisation = '', attacker) { static async createBlessure(actor, gravite, localisation = '', attacker) {
const definition = RdDItemBlessure.getDefinition(gravite) const definition = RdDItemBlessure.getDefinition(gravite)
const blessure = { const blessure = {
@ -79,7 +106,7 @@ export class RdDItemBlessure extends RdDItem {
} }
async setSoinsBlessure(systemUpdate = {}) { async setSoinsBlessure(systemUpdate = {}) {
systemUpdate = mergeObject(systemUpdate, this.system, { overwrite: false }), systemUpdate = foundry.utils.mergeObject(systemUpdate, this.system, { overwrite: false }),
systemUpdate.soinscomplets.done = systemUpdate.premierssoins.done && systemUpdate.soinscomplets.done systemUpdate.soinscomplets.done = systemUpdate.premierssoins.done && systemUpdate.soinscomplets.done
await this.update({ await this.update({
img: this.getImgSoins(systemUpdate.gravite, systemUpdate.soinscomplets.done), img: this.getImgSoins(systemUpdate.gravite, systemUpdate.soinscomplets.done),
@ -107,14 +134,14 @@ export class RdDItemBlessure extends RdDItem {
if (rolled.isETotal) { if (rolled.isETotal) {
message.content += ` -- une blessure ${label} s'infecte (temps de guérison augmenté de ${gravite} jours, perte de vie)`; message.content += ` -- une blessure ${label} s'infecte (temps de guérison augmenté de ${gravite} jours, perte de vie)`;
await actor.santeIncDec("vie", -1); await actor.santeIncDec("vie", -1);
mergeObject(update, { foundry.utils.mergeObject(update, {
system: { fin: { indexDate: timestamp.addJours(gravite).indexDate } } system: { fin: { indexDate: timestamp.addJours(gravite).indexDate } }
}); });
} }
else { else {
if (!isMaladeEmpoisonne && rolled.isSuccess && this.peutRetrograder(graviteMoindre, moindres)) { if (!isMaladeEmpoisonne && rolled.isSuccess && this.peutRetrograder(graviteMoindre, moindres)) {
message.content += ` -- une blessure ${label} cicatrise`; message.content += ` -- une blessure ${label} cicatrise`;
mergeObject(update, { foundry.utils.mergeObject(update, {
system: { system: {
gravite: graviteMoindre, gravite: graviteMoindre,
temporel: { fin: { indexDate: timestamp.addJours(graviteMoindre).indexDate } } temporel: { fin: { indexDate: timestamp.addJours(graviteMoindre).indexDate } }

View File

@ -38,7 +38,7 @@ export class RdDItemMaladie extends RdDItem {
await mal.actor.updateEmbeddedDocuments('Item', [{ await mal.actor.updateEmbeddedDocuments('Item', [{
_id: mal.id, _id: mal.id,
'system.temporel.fin': duplicate(timestampFin), 'system.temporel.fin': foundry.utils.duplicate(timestampFin),
}]) }])
} }
} }

View File

@ -8,7 +8,7 @@ const TYPE_ITEMS_NATURELS = ["faune", "herbe", "plante", "ingredient"];
export class RdDItemInventaireSheet extends RdDItemSheet { export class RdDItemInventaireSheet extends RdDItemSheet {
static get defaultOptions() { static get defaultOptions() {
return mergeObject(RdDItemSheet.defaultOptions, { return foundry.utils.mergeObject(RdDItemSheet.defaultOptions, {
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }] tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }]
}); });
} }
@ -23,7 +23,7 @@ export class RdDItemInventaireSheet extends RdDItemSheet {
async getData() { async getData() {
const formData = await super.getData(); const formData = await super.getData();
return mergeObject(formData, { return foundry.utils.mergeObject(formData, {
milieux: await game.system.rdd.environnement.autresMilieux(this.item) milieux: await game.system.rdd.environnement.autresMilieux(this.item)
}); });
} }

View File

@ -6,7 +6,7 @@ export class RdDRencontreItemSheet extends RdDItemSheet {
static get ITEM_TYPE() { return "rencontre" }; static get ITEM_TYPE() { return "rencontre" };
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }] tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }]
}); });
} }
@ -24,7 +24,7 @@ export class RdDRencontreItemSheet extends RdDItemSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
const formData = await super.getData(); const formData = await super.getData();
mergeObject(formData, { foundry.utils.mergeObject(formData, {
effets: { effets: {
succes: { succes: {
liste: RdDRencontre.getEffetsSucces(), liste: RdDRencontre.getEffetsSucces(),

View File

@ -5,6 +5,7 @@ import { Monnaie } from "./item-monnaie.js";
import { RdDItem, TYPES } from "./item.js"; import { RdDItem, TYPES } from "./item.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDRaretes } from "./item/raretes.js"; import { RdDRaretes } from "./item/raretes.js";
import { RdDCalendrier } from "./time/rdd-calendrier.js";
class Migration { class Migration {
get code() { return "sample"; } get code() { return "sample"; }
@ -70,17 +71,17 @@ class _10_0_16_MigrationSortsReserve extends Migration {
get version() { return "10.0.16"; } get version() { return "10.0.16"; }
async migrate() { async migrate() {
await game.actors const actors = game.actors.filter((actor) => actor.type == "personnage" && (actor.system.reve?.reserve?.list?.length ?? 0 > 0))
.filter((actor) => actor.type == "personnage") Promise.all(actors.map(async it => await this.convertirSortsReserveActeur(it)))
.filter((actor) => actor.system.reve?.reserve?.list?.length ?? 0 > 0) }
.forEach(async (actor) => {
const sortsReserve = actor.system.reve.reserve.list.map(this.conversionSortReserve); async convertirSortsReserveActeur(actor) {
console.log(`${LOG_HEAD} Migration des sorts en réserve de ${actor.name}`, sortsReserve); const sortsReserve = actor.system.reve.reserve.list.map(this.conversionSortReserve);
await actor.createEmbeddedDocuments("Item", sortsReserve, { console.log(`${LOG_HEAD} Migration des sorts en réserve de ${actor.name}`, sortsReserve);
renderSheet: false, await actor.createEmbeddedDocuments("Item", sortsReserve, {
}); renderSheet: false,
await actor.update({ 'system.reve.reserve': undefined }) });
}); await actor.update({ 'system.reve.reserve': undefined });
} }
conversionSortReserve(it) { conversionSortReserve(it) {
@ -189,7 +190,7 @@ class _10_2_5_ArmesTirLancer extends Migration {
get version() { return "10.2.5"; } get version() { return "10.2.5"; }
migrateArmeTirLancer(it) { migrateArmeTirLancer(it) {
let updates = mergeObject({ _id: it.id }, this.getMapping(it).updates); let updates = foundry.utils.mergeObject({ _id: it.id }, this.getMapping(it).updates);
console.log(it.name, updates); console.log(it.name, updates);
return updates; return updates;
} }
@ -364,7 +365,7 @@ class _10_4_6_ServicesEnCommerces extends Migration {
const item = await RdDItem.getCorrespondingItem(serviceRefItem); const item = await RdDItem.getCorrespondingItem(serviceRefItem);
const itemToCreate = { const itemToCreate = {
name: item.name, img: item.img, type: item.type, name: item.name, img: item.img, type: item.type,
system: mergeObject({ cout: serviceRefItem.system.cout, quantite: serviceRefItem.system.quantite }, item.system, { overwrite: false }) system: foundry.utils.mergeObject({ cout: serviceRefItem.system.cout, quantite: serviceRefItem.system.quantite }, item.system, { overwrite: false })
}; };
return itemToCreate; return itemToCreate;
} }
@ -507,13 +508,28 @@ class _10_7_19_PossessionsEntiteVictime extends Migration {
} }
migratePossession(it) { migratePossession(it) {
return { _id: it.id, return {
_id: it.id,
'system.entite.actorid': it.system.possesseurid, 'system.entite.actorid': it.system.possesseurid,
'system.victime.actorid': it.system.possedeid 'system.victime.actorid': it.system.possedeid
} }
} }
} }
class _11_2_20_MigrationAstrologie extends Migration {
get code() { return "migration-astrologie" }
get version() { return "11.2.20" }
async migrate() {
const nombresAstraux = game.system.rdd.calendrier.getNombresAstraux()
nombresAstraux.forEach(na => {
na.lectures = na.valeursFausses
na.valeursFausses = undefined
})
await game.system.rdd.calendrier.setNombresAstraux(nombresAstraux)
}
}
export class Migrations { export class Migrations {
static getMigrations() { static getMigrations() {
return [ return [
@ -532,6 +548,7 @@ export class Migrations {
new _10_7_0_MigrationBlessures(), new _10_7_0_MigrationBlessures(),
new _10_7_19_CategorieCompetenceCreature(), new _10_7_19_CategorieCompetenceCreature(),
new _10_7_19_PossessionsEntiteVictime(), new _10_7_19_PossessionsEntiteVictime(),
new _11_2_20_MigrationAstrologie(),
]; ];
} }
@ -546,7 +563,10 @@ export class Migrations {
} }
migrate() { migrate() {
const currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion"); let currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion")
if (currentVersion.startsWith("v")) {
currentVersion = currentVersion.substring(1)
}
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));
@ -554,7 +574,7 @@ export class Migrations {
migrations.sort((a, b) => this.compareVersions(a, b)); migrations.sort((a, b) => this.compareVersions(a, b));
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}` `${LOG_HEAD} Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}`
); );
await m.migrate(); await m.migrate();
}); });
@ -562,9 +582,7 @@ export class Migrations {
`Migrations done, version will change to ${game.system.version}` `Migrations done, version will change to ${game.system.version}`
); );
} else { } else {
console.log( console.log(`${LOG_HEAD} No migration needeed, version will change to ${game.system.version}`
LOG_HEAD +
`No migration needeed, version will change to ${game.system.version}`
); );
} }
@ -574,7 +592,7 @@ export class Migrations {
game.system.version game.system.version
); );
} else { } else {
console.log(LOG_HEAD + `No system version changed`); console.log(`${LOG_HEAD} No system version changed`);
} }
} }

View File

@ -46,7 +46,7 @@ export class Misc {
} }
static typeName(type, subType) { static typeName(type, subType) {
return subType ? game.i18n.localize(`TYPES.${type}.${Misc.upperFirst(subType)}`) return subType ? game.i18n.localize(`TYPES.${type}.${subType}`)
: ''; : '';
} }
@ -200,7 +200,7 @@ export class Misc {
/* -------------------------------------------- */ /* -------------------------------------------- */
static findFirstLike(value, elements, options = {}) { static findFirstLike(value, elements, options = {}) {
options = mergeObject({ options = foundry.utils.mergeObject({
mapper: it => it.name, mapper: it => it.name,
preFilter: it => true, preFilter: it => true,
description: 'valeur', description: 'valeur',
@ -225,7 +225,7 @@ export class Misc {
} }
static findAllLike(value, elements, options = {}) { static findAllLike(value, elements, options = {}) {
options = mergeObject({ options = foundry.utils.mergeObject({
mapper: it => it.name, mapper: it => it.name,
preFilter: it => true, preFilter: it => true,
description: 'valeur', description: 'valeur',

View File

@ -19,10 +19,6 @@ export class RdDBonus {
} }
static isAjustementAstrologique(rollData) {
return RdDCarac.isChance(rollData.selectedCarac) ||
rollData.selectedSort?.system.isrituel;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static isDefenseAttaqueFinesse(rollData) { static isDefenseAttaqueFinesse(rollData) {
if (rollData.isEmpoignade && rollData.rolled?.isPart) { if (rollData.isEmpoignade && rollData.rolled?.isPart) {

View File

@ -128,7 +128,7 @@ export class RdDCombatManager extends Combat {
// 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");
let messageData = mergeObject( let messageData = foundry.utils.mergeObject(
{ {
speaker: { speaker: {
scene: canvas.scene._id, scene: canvas.scene._id,
@ -218,7 +218,7 @@ export class RdDCombatManager extends Combat {
static $prepareAttaqueArme(infoAttaque) { static $prepareAttaqueArme(infoAttaque) {
const comp = infoAttaque.competences.find(c => c.name == infoAttaque.competence); const comp = infoAttaque.competences.find(c => c.name == infoAttaque.competence);
const attaque = duplicate(infoAttaque.arme); const attaque = foundry.utils.duplicate(infoAttaque.arme);
attaque.action = 'attaque'; attaque.action = 'attaque';
attaque.system.competence = infoAttaque.competence; attaque.system.competence = infoAttaque.competence;
attaque.system.dommagesReels = infoAttaque.dommagesReel; attaque.system.dommagesReels = infoAttaque.dommagesReel;
@ -328,8 +328,8 @@ export class RdDCombatManager extends Combat {
} }
} }
options = [ options = [
{ name: "Incrémenter initiative", condition: true, icon: '<i class="fas fa-plus"></i>', callback: target => { RdDCombatManager.incDecInit(target.data('combatant-id'), +0.01); } }, { name: "Incrémenter initiative", condition: true, icon: '<i class="fa-solid fa-plus"></i>', callback: target => { RdDCombatManager.incDecInit(target.data('combatant-id'), +0.01); } },
{ name: "Décrémenter initiative", condition: true, icon: '<i class="fas fa-minus"></i>', callback: target => { RdDCombatManager.incDecInit(target.data('combatant-id'), -0.01); } } { name: "Décrémenter initiative", condition: true, icon: '<i class="fa-solid fa-minus"></i>', callback: target => { RdDCombatManager.incDecInit(target.data('combatant-id'), -0.01); } }
].concat(options); ].concat(options);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -885,12 +885,12 @@ export class RdDCombat {
this.removeChatMessageActionsPasseArme(attackerRoll.passeArme); this.removeChatMessageActionsPasseArme(attackerRoll.passeArme);
if (essaisPrecedents) { if (essaisPrecedents) {
mergeObject(attackerRoll.essais, essaisPrecedents, { overwrite: true }); foundry.utils.mergeObject(attackerRoll.essais, essaisPrecedents, { overwrite: true });
} }
// # utilisation esquive // # utilisation esquive
const corpsACorps = this.defender.getCompetenceCorpsACorps({ onMessage: it => console.info(it, this.defender) }); const corpsACorps = this.defender.getCompetenceCorpsACorps({ onMessage: it => console.info(it, this.defender) });
const esquives = duplicate(this.defender.getCompetencesEsquive()) const esquives = foundry.utils.duplicate(this.defender.getCompetencesEsquive())
esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0); esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0);
const paramChatDefense = { const paramChatDefense = {
@ -1282,7 +1282,7 @@ export class RdDCombat {
attackerRoll.defenderTokenId = defenderTokenId; attackerRoll.defenderTokenId = defenderTokenId;
await this.computeRecul(defenderRoll); await this.computeRecul(defenderRoll);
this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll?.show); await this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll?.show);
} }
else { // envoi à un GM: les joueurs n'ont pas le droit de modifier les personnages qu'ils ne possèdent pas else { // envoi à un GM: les joueurs n'ont pas le droit de modifier les personnages qu'ils ne possèdent pas
game.socket.emit(SYSTEM_SOCKET_ID, { game.socket.emit(SYSTEM_SOCKET_ID, {
@ -1307,6 +1307,7 @@ export class RdDCombat {
blessuresStatus: actor.computeResumeBlessure(), blessuresStatus: actor.computeResumeBlessure(),
SConst: actor.getSConst(), SConst: actor.getSConst(),
actorId: actor.id, actorId: actor.id,
actor: actor,
tokenId: tokenId, tokenId: tokenId,
isGrave: actor.countBlessures(it => it.isGrave()) > 0, isGrave: actor.countBlessures(it => it.isGrave()) > 0,
isCritique: actor.countBlessures(it => it.isCritique()) > 0 isCritique: actor.countBlessures(it => it.isCritique()) > 0

View File

@ -16,6 +16,7 @@ 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 { FenetreRechercheTirage } from "./tirage/fenetre-recherche-tirage.js";
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
import { DialogFatigueVoyage } from "./voyage/dialog-fatigue-voyage.js";
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/; const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
@ -76,6 +77,7 @@ export class RdDCommands {
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: ["/tirage"], func: (content, msg, params) => this.tirage(), descr: "Ouvre la fenêtre de recherche et tirage" });
this.registerCommand({ path: ["/voyage"], func: (content, msg, params) => this.voyage(msg, params), descr: "Gérer le voyage" });
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: ["/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" });
@ -298,7 +300,7 @@ export class RdDCommands {
async getRencontreTMR(params) { async getRencontreTMR(params) {
if (params.length == 1 || params.length == 2) { if (params.length == 1 || params.length == 2) {
return game.system.rdd.rencontresTMR.rollRencontre(params[0], params[1]) return game.system.rdd.rencontresTMR.rollRencontre(params[0], params[1])
} }
return false; return false;
} }
@ -461,14 +463,13 @@ export class RdDCommands {
let motif = params.slice(1, params.length - 2); let motif = params.slice(1, params.length - 2);
let name = params[params.length - 1]; let name = params[params.length - 1];
const personnages = game.actors.filter(actor => actor.isPersonnageJoueur());
if (name == undefined) { if (name == undefined) {
for (let actor of game.actors) { for (let actor of personnages) {
// TODO: ne plus stresser les entités de cauchemar!
await actor.distribuerStress('stress', stress, motif); await actor.distribuerStress('stress', stress, motif);
} }
} else { } else {
//console.log(stressValue, nomJoueur); let actor = Misc.findActor(name, personnages) ?? 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); await actor.distribuerStress('stress', stress, motif);
} }
@ -485,10 +486,13 @@ export class RdDCommands {
} }
async tirage() { async tirage() {
FenetreRechercheTirage.create(); FenetreRechercheTirage.create()
}
async voyage() {
DialogFatigueVoyage.create()
} }
async sommeil() { async sommeil() {
DialogChateauDormant.create(); DialogChateauDormant.create()
} }
} }

View File

@ -14,10 +14,10 @@ export class RdDConfirm {
"cancel": RdDConfirm._createButtonCancel() "cancel": RdDConfirm._createButtonCancel()
}; };
if (options.settingConfirmer) { if (options.settingConfirmer) {
buttons = mergeObject(RdDConfirm._createButtonActionSave(options), buttons); buttons = foundry.utils.mergeObject(RdDConfirm._createButtonActionSave(options), buttons);
} }
if (autresActions) { if (autresActions) {
buttons = mergeObject(autresActions, buttons); buttons = foundry.utils.mergeObject(autresActions, buttons);
} }
const dialogDetails = { const dialogDetails = {
title: options.title, title: options.title,

View File

@ -98,7 +98,7 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static getEmpoignadeById(actor, id) { static getEmpoignadeById(actor, id) {
let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id) let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id)
return emp && duplicate(emp) || undefined; return emp && foundry.utils.duplicate(emp) || undefined;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -108,7 +108,7 @@ export class RdDEmpoignade {
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id) (it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
) )
if (emp) { if (emp) {
return duplicate(emp); return foundry.utils.duplicate(emp);
} }
return undefined; return undefined;
} }
@ -267,7 +267,7 @@ export class RdDEmpoignade {
return return
} }
empoignade = duplicate(empoignade) empoignade = foundry.utils.duplicate(empoignade)
let defenderRoll = { let defenderRoll = {
mode, attacker, defender, empoignade, attackerRoll, mode, attacker, defender, empoignade, attackerRoll,
diffLibre: attackerRoll.diffLibre, diffLibre: attackerRoll.diffLibre,

View File

@ -266,16 +266,16 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
/* -------------------------------------------- */ /* -------------------------------------------- */
// CSS patch for v9
if (game.version) {
let sidebar = document.getElementById("sidebar");
sidebar.style.width = "min-content";
}
game.system.rdd.calendrier = new RdDCalendrier(); game.system.rdd.calendrier = new RdDCalendrier();
if (Misc.isUniqueConnectedGM()) { if (Misc.isUniqueConnectedGM()) {
new Migrations().migrate(); new Migrations().migrate();
this.messageDeBienvenue(); this.messageDeBienvenue();
this.registerUsageCount(SYSTEM_RDD); import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter=>{
console.log("ClassCounter loaded", moduleCounter)
moduleCounter.ClassCounter.registerUsageCount()
}).catch(err=>
console.log("No stats available, giving up.")
)
} }
StatusEffects.onReady(); StatusEffects.onReady();
@ -306,30 +306,6 @@ export class SystemReveDeDragon {
` }); ` });
} }
} }
/* -------------------------------------------- */
// Register world usage statistics
async registerUsageCount(registerKey) {
if (game.user.isGM) {
game.settings.register("world", "world-key", {
name: "Unique world key",
scope: "world",
config: false,
default: "NONE",
type: String
});
let worldKey = game.settings.get("world", "world-key")
if (worldKey == undefined || worldKey == "") {
worldKey = randomID(32)
game.settings.set("world", "world-key", worldKey)
}
let regURL = `https://www.uberwald.me/fvtt_appcount/count.php?name="${registerKey}"&worldKey="${worldKey}"&version="${game.release.generation}.${game.release.build}"&system="${game.system.id}"&systemversion="${game.system.version}"`
$.ajax(regURL)
/* -------------------------------------------- */
}
}
} }
SystemReveDeDragon.start(); SystemReveDeDragon.start();

View File

@ -24,7 +24,7 @@ export class RdDPossession {
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 == TYPES.possession && poss.system.victime.actorid == defender.id);
} }
return poss && duplicate(poss) || undefined; return poss && foundry.utils.duplicate(poss) || undefined;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -52,7 +52,7 @@ export class RdDPossession {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async onConjurerPossession(attacker, possession) { static async onConjurerPossession(attacker, possession) {
possession = duplicate(possession); possession = foundry.utils.duplicate(possession);
RdDPossession.$updateEtatPossession(possession) RdDPossession.$updateEtatPossession(possession)
const defender = game.actors.get(possession.system.entite.actorid); const defender = game.actors.get(possession.system.entite.actorid);
@ -80,7 +80,7 @@ export class RdDPossession {
ui.notifications.warn("Une erreur s'est produite : Aucune possession trouvée !!") ui.notifications.warn("Une erreur s'est produite : Aucune possession trouvée !!")
return return
} }
possession = duplicate(possession) possession = foundry.utils.duplicate(possession)
// Update for draconic roll // Update for draconic roll
let rollData = { let rollData = {
mode: "defense", mode: "defense",

View File

@ -114,7 +114,7 @@ export class RdDResolutionTable {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async roll(caracValue, finalLevel, rollData = {}) { static async roll(caracValue, finalLevel, rollData = {}) {
let chances = duplicate(this.computeChances(caracValue, finalLevel)); let chances = foundry.utils.duplicate(this.computeChances(caracValue, finalLevel));
this._updateChancesWithBonus(chances, rollData.bonus, finalLevel); this._updateChancesWithBonus(chances, rollData.bonus, finalLevel);
this._updateChancesFactor(chances, rollData.diviseurSignificative); this._updateChancesFactor(chances, rollData.diviseurSignificative);
chances.showDice = rollData.showDice; chances.showDice = rollData.showDice;
@ -158,7 +158,7 @@ export class RdDResolutionTable {
static _updateChancesFactor(chances, diviseur) { static _updateChancesFactor(chances, diviseur) {
if (chances.level > -11 && diviseur && diviseur > 1) { if (chances.level > -11 && diviseur && diviseur > 1) {
let newScore = Math.floor(chances.score / diviseur); let newScore = Math.floor(chances.score / diviseur);
mergeObject(chances, this._computeCell(undefined, newScore), { overwrite: true }); foundry.utils.mergeObject(chances, this._computeCell(undefined, newScore), { overwrite: true });
} }
} }
@ -166,27 +166,27 @@ export class RdDResolutionTable {
static _updateChancesWithBonus(chances, bonus, finalLevel) { static _updateChancesWithBonus(chances, bonus, finalLevel) {
if (bonus && finalLevel > -11) { if (bonus && finalLevel > -11) {
let newScore = Number(chances.score) + bonus; let newScore = Number(chances.score) + bonus;
mergeObject(chances, this._computeCell(undefined, newScore), { overwrite: true }); foundry.utils.mergeObject(chances, this._computeCell(undefined, newScore), { overwrite: true });
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static significativeRequise(chances) { static significativeRequise(chances) {
chances.roll = Math.floor(chances.score / 2); chances.roll = Math.floor(chances.score / 2);
mergeObject(chances, reussites.find(x => x.code == 'sign'), { overwrite: true }); foundry.utils.mergeObject(chances, reussites.find(x => x.code == 'sign'), { overwrite: true });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static succesRequis(chances) { static succesRequis(chances) {
chances.roll = chances.score; chances.roll = chances.score;
mergeObject(chances, reussites.find(x => x.code == 'norm'), { overwrite: true }); foundry.utils.mergeObject(chances, reussites.find(x => x.code == 'norm'), { overwrite: true });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async rollChances(chances, diviseur, forceDiceResult = -1) { static async rollChances(chances, diviseur, forceDiceResult = -1) {
chances.forceDiceResult = forceDiceResult <= 0 || forceDiceResult > 100 ? undefined : { total: forceDiceResult }; chances.forceDiceResult = forceDiceResult <= 0 || forceDiceResult > 100 ? undefined : { total: forceDiceResult };
chances.roll = await RdDDice.rollTotal("1d100", chances); chances.roll = await RdDDice.rollTotal("1d100", chances);
mergeObject(chances, this.computeReussite(chances, chances.roll, diviseur), { overwrite: true }); foundry.utils.mergeObject(chances, this.computeReussite(chances, chances.roll, diviseur), { overwrite: true });
return chances; return chances;
} }

View File

@ -38,7 +38,7 @@ export class RdDRollResolutionTable extends Dialog {
diffLibre: 0, diffLibre: 0,
use: { conditions:true, libre:true } use: { conditions:true, libre:true }
} }
mergeObject(rollData, defRollData, { overwrite: false }); foundry.utils.mergeObject(rollData, defRollData, { overwrite: false });
for (let i = 1; i < 21; i++) { for (let i = 1; i < 21; i++) {
const key = `${i}`; const key = `${i}`;
rollData.carac[key] = { type: "number", value: i, label: key } rollData.carac[key] = { type: "number", value: i, label: key }

View File

@ -44,6 +44,7 @@ export class RdDRoll extends Dialog {
diffLibre: rollData.competence?.system.default_diffLibre ?? 0, diffLibre: rollData.competence?.system.default_diffLibre ?? 0,
perteMoralEchec: false, /* Pour l'affichage dans le chat */ perteMoralEchec: false, /* Pour l'affichage dans le chat */
use: { use: {
astrologique: true,
moral: false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */ moral: false, /* Est-ce que le joueur demande d'utiliser le moral ? Utile si le joueur change plusieurs fois de carac associée. */
libre: true, libre: true,
coeur: undefined, coeur: undefined,
@ -64,7 +65,7 @@ export class RdDRoll extends Dialog {
defaultRollData.carac["reve-actuel"] = actor.system.reve.reve defaultRollData.carac["reve-actuel"] = actor.system.reve.reve
} }
mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false }); foundry.utils.mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false });
if (rollData.forceCarac) { if (rollData.forceCarac) {
rollData.carac = rollData.forceCarac; rollData.carac = rollData.forceCarac;
} }
@ -214,6 +215,10 @@ export class RdDRoll extends Dialog {
this.rollData[attribute] = event.currentTarget.checked; this.rollData[attribute] = event.currentTarget.checked;
this.updateRollResult(html); this.updateRollResult(html);
}); });
this.html.find('input.use-astrologique').change((event) => {
this.rollData.use.astrologique = event.currentTarget.checked;
this.updateRollResult(html);
});
this.html.find('input.use-encTotal').change((event) => { this.html.find('input.use-encTotal').change((event) => {
this.rollData.use.encTotal = event.currentTarget.checked; this.rollData.use.encTotal = event.currentTarget.checked;
this.updateRollResult(html); this.updateRollResult(html);
@ -314,6 +319,7 @@ export class RdDRoll extends Dialog {
HtmlUtility.showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac)); HtmlUtility.showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac));
HtmlUtility.showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac)); HtmlUtility.showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac));
HtmlUtility.showControlWhen(this.html.find(".use-astrologique"), rollData.ajustements.astrologique.visible);
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(".divAppelAuMoral"), rollData.use.appelAuMoral);
HtmlUtility.showControlWhen(this.html.find(".utilisation-coeur"), rollData.ajustements.coeur.visible); HtmlUtility.showControlWhen(this.html.find(".utilisation-coeur"), rollData.ajustements.coeur.visible);

View File

@ -16,7 +16,7 @@ export class RdDSheetUtility {
isObserver: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER, isObserver: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OBSERVER,
isOwner: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER isOwner: userRightLevel >= CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER
} }
mergeObject(options, newOptions); foundry.utils.mergeObject(options, newOptions);
return options; return options;
} }
@ -76,7 +76,7 @@ export class RdDSheetUtility {
static async _onSplitItem(item, split, actor) { static async _onSplitItem(item, split, actor) {
if (split >= 1 && split < item.system.quantite) { if (split >= 1 && split < item.system.quantite) {
await item.diminuerQuantite(split); await item.diminuerQuantite(split);
const splitItem = duplicate(item); const splitItem = foundry.utils.duplicate(item);
// todo: ajouter dans le même conteneur? // todo: ajouter dans le même conteneur?
splitItem.system.quantite = split; splitItem.system.quantite = split;
await actor.createEmbeddedDocuments('Item', [splitItem]) await actor.createEmbeddedDocuments('Item', [splitItem])

View File

@ -17,6 +17,7 @@ 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 { RdDTimestamp } from "./time/rdd-timestamp.js";
import { TYPES } from "./item.js"; import { TYPES } from "./item.js";
import { Misc } from "./misc.js";
const TMR_DISPLAY_SIZE = { const TMR_DISPLAY_SIZE = {
code: 'tmr-display-size', code: 'tmr-display-size',
@ -43,16 +44,15 @@ export class RdDTMRDialog extends Dialog {
type: Number, type: Number,
range: TMR_DISPLAY_SIZE.range range: TMR_DISPLAY_SIZE.range
}) })
await PixiTMR.init()
} }
static async create(actor, tmrData) { static async create(actor, tmrData) {
await PixiTMR.init()
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', tmrData); let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', tmrData);
if (tmrData.mode != 'visu' && !game.user.isGM) { if (tmrData.mode != 'visu' && !game.user.isGM) {
ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatMessage.getWhisperRecipients("GM") }); ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatMessage.getWhisperRecipients("GM") });
} }
return new RdDTMRDialog(html, actor, tmrData); return new RdDTMRDialog(html, actor, tmrData)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -70,7 +70,7 @@ export class RdDTMRDialog extends Dialog {
'z-index': 40 'z-index': 40
} }
super(dialogConf, dialogOptions); super(dialogConf, dialogOptions);
this.tmrdata = duplicate(tmrData); this.tmrdata = foundry.utils.duplicate(tmrData);
this.actor = actor; this.actor = actor;
this.actor.tmrApp = this; // reference this app in the actor structure this.actor.tmrApp = this; // reference this app in the actor structure
this.viewOnly = tmrData.mode == "visu" this.viewOnly = tmrData.mode == "visu"
@ -141,7 +141,7 @@ export class RdDTMRDialog extends Dialog {
// Le reste... // Le reste...
this.updateValuesDisplay(); this.updateValuesDisplay();
} }
async onDeplacement() { async onDeplacement() {
await this.manageRencontre(TMRUtility.getTMR(this._getCoordActor())); await this.manageRencontre(TMRUtility.getTMR(this._getCoordActor()));
} }
@ -162,9 +162,11 @@ export class RdDTMRDialog extends Dialog {
} }
async forceTMRDisplay() { async forceTMRDisplay() {
this.bringToTop() if (this.rendered) {
if (this.subdialog?.bringToTop) { this.bringToTop()
this.subdialog.bringToTop(); if (this.subdialog?.bringToTop) {
this.subdialog.bringToTop();
}
} }
} }
@ -247,26 +249,21 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
_getTokensCasesTmr() { _getTokensCasesTmr() {
return this.casesSpeciales.map(c => this._tokenCaseSpeciale(c)).filter(token => token); return Misc.concat(this.casesSpeciales.map(caseSpeciale =>
} Draconique.get(caseSpeciale.system.specific)?.token(this.pixiTMR, caseSpeciale, () => caseSpeciale.system.coord)
_getTokensRencontres() { ))
return this.rencontresExistantes.map(it => this._tokenRencontre(it));
}
_getTokensSortsReserve() {
return this.actor.itemTypes[TYPES.sortreserve].map(it => this._tokenSortEnReserve(it));
} }
/* -------------------------------------------- */ _getTokensRencontres() {
_tokenRencontre(rencontre) { return Misc.concat(this.rencontresExistantes.map(rencontre =>
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.system.coord); EffetsDraconiques.rencontre.tokens(this.pixiTMR, rencontre, () => rencontre.system.coord)
))
} }
_tokenCaseSpeciale(casetmr) {
const caseData = casetmr; _getTokensSortsReserve() {
const draconique = Draconique.get(caseData.system.specific); const sortsReserve = this.actor.itemTypes[TYPES.sortreserve];
return draconique?.token(this.pixiTMR, caseData, () => caseData.system.coord); return Misc.concat(sortsReserve.map(sortReserve =>
} EffetsDraconiques.sortReserve.tokens(this.pixiTMR, sortReserve, () => sortReserve.system.coord)))
_tokenSortEnReserve(sortReserve) {
return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortReserve, () => sortReserve.system.coord);
} }
_tokenDemiReve() { _tokenDemiReve() {
@ -300,13 +297,12 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async updateValuesDisplay() { async updateValuesDisplay() {
if (!this.rendered) { if (this.viewOnly || !this.rendered) {
return; return;
} }
const coord = this._getCoordActor(); const coord = this._getCoordActor();
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;
@ -342,7 +338,7 @@ export class RdDTMRDialog extends Dialog {
this._tellToGM(this.actor.name + " a quitté les terres médianes"); this._tellToGM(this.actor.name + " a quitté les terres médianes");
} }
await this.actor.santeIncDec((ReglesOptionnelles.isUsing("appliquer-fatigue") ? "fatigue" : "endurance"), await this.actor.santeIncDec((ReglesOptionnelles.isUsing("appliquer-fatigue") ? "fatigue" : "endurance"),
this.cumulFatigue) this.cumulFatigue)
} }
await super.close(); await super.close();
this.pixiTMR.close() this.pixiTMR.close()
@ -411,7 +407,7 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
$marquerCasesTMR(listCoordTMR) { $marquerCasesTMR(listCoordTMR) {
this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location this.currentRencontre.locList = foundry.utils.duplicate(listCoordTMR); // And track of allowed location
this.currentRencontre.graphics = listCoordTMR.map(coordTMR => this.pixiTMR.addMarkTMR(coordTMR)) this.currentRencontre.graphics = listCoordTMR.map(coordTMR => this.pixiTMR.addMarkTMR(coordTMR))
} }
@ -540,7 +536,7 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
_rollPresentCite(rencData) { _rollPresentCite(rencData) {
let rolled = RdDResolutionTable.computeChances(rencData.reve, 0); let rolled = RdDResolutionTable.computeChances(rencData.reve, 0);
mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score }); foundry.utils.mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score });
RdDResolutionTable.succesRequis(rolled); RdDResolutionTable.succesRequis(rolled);
return rolled; return rolled;
} }
@ -581,7 +577,7 @@ export class RdDTMRDialog extends Dialog {
} }
this.descenteTMR = false; this.descenteTMR = false;
this.currentRencontre = undefined; this.currentRencontre = undefined;
if (this._presentCite(tmr)) { if (await this._presentCite(tmr)) {
return; return;
} }
this.currentRencontre = await this._jetDeRencontre(tmr); this.currentRencontre = await this._jetDeRencontre(tmr);
@ -592,7 +588,7 @@ export class RdDTMRDialog extends Dialog {
} }
else { else {
const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr); const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr);
dialog.render(true); await dialog.render(true);
this.setTMRPendingAction(dialog); this.setTMRPendingAction(dialog);
} }
} }
@ -602,11 +598,11 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_presentCite(tmr) { async _presentCite(tmr) {
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord)); const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
if (presentCite) { if (presentCite) {
const caseData = presentCite; const caseData = presentCite;
const dialog = EffetsDraconiques.presentCites.choisirUnPresent(caseData, present => { const dialog = await EffetsDraconiques.presentCites.choisirUnPresent(caseData, present => {
this._utiliserPresentCite(presentCite, present, tmr) this._utiliserPresentCite(presentCite, present, tmr)
this.restoreTMRAfterAction(); this.restoreTMRAfterAction();
}); });
@ -683,7 +679,7 @@ export class RdDTMRDialog extends Dialog {
if (this.isCaseHumide(tmr)) { if (this.isCaseHumide(tmr)) {
let rollData = { let rollData = {
actor: this.actor, actor: this.actor,
competence: duplicate(this.actor.getBestDraconic()), competence: foundry.utils.duplicate(this.actor.getBestDraconic()),
tmr: tmr, tmr: tmr,
canClose: false, canClose: false,
diffLibre: -7, diffLibre: -7,
@ -702,7 +698,6 @@ export class RdDTMRDialog extends Dialog {
} }
async _resultatMaitriseCaseHumide(rollData) { async _resultatMaitriseCaseHumide(rollData) {
await this.souffleSiEchecTotal(rollData);
if (rollData.rolled.isSuccess && rollData.double) { if (rollData.rolled.isSuccess && rollData.double) {
rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements }; rollData.previous = { rolled: rollData.rolled, ajustements: rollData.ajustements };
rollData.double = undefined; rollData.double = undefined;
@ -717,6 +712,7 @@ export class RdDTMRDialog extends Dialog {
if (rollData.rolled.isEchec) { if (rollData.rolled.isEchec) {
await this.close(); await this.close();
} }
await this.souffleSiEchecTotal(rollData);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -808,7 +804,7 @@ export class RdDTMRDialog extends Dialog {
async _conquerir(tmr, options) { async _conquerir(tmr, options) {
let rollData = { let rollData = {
actor: this.actor, actor: this.actor,
competence: duplicate(this.actor.getBestDraconic()), competence: foundry.utils.duplicate(this.actor.getBestDraconic()),
tmr: tmr, tmr: tmr,
canClose: options.canClose ?? false, canClose: options.canClose ?? false,
diffLibre: options.difficulte ?? -7, diffLibre: options.difficulte ?? -7,
@ -1126,6 +1122,9 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
_trackToken(token) { _trackToken(token) {
if (!token) {
return
}
if (this.demiReve === token && this.isDemiReveCache()) { if (this.demiReve === token && this.isDemiReveCache()) {
return; return;
} }

View File

@ -90,7 +90,6 @@ export class RdDTokenHud {
if (target?.actor) { if (target?.actor) {
const hudSoins = { blessures: target.actor.blessuresASoigner() ?? [] }; const hudSoins = { blessures: target.actor.blessuresASoigner() ?? [] };
if (hudSoins.blessures.length > 0) { if (hudSoins.blessures.length > 0) {
// soins
const controlIconTarget = html.find('.control-icon[data-action=combat]'); const controlIconTarget = html.find('.control-icon[data-action=combat]');
await RdDTokenHud._configureSubMenu(controlIconTarget, await RdDTokenHud._configureSubMenu(controlIconTarget,
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-soins.hbs', 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-soins.hbs',

View File

@ -18,6 +18,7 @@ import { RdDRaretes } from "./item/raretes.js";
import { RdDEmpoignade } from "./rdd-empoignade.js"; import { RdDEmpoignade } from "./rdd-empoignade.js";
import { ExperienceLog } from "./actor/experience-log.js"; import { ExperienceLog } from "./actor/experience-log.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { APP_ASTROLOGIE_REFRESH } from "./sommeil/app-astrologie.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
// This table starts at 0 -> niveau -10 // This table starts at 0 -> niveau -10
@ -31,7 +32,7 @@ function _buildAllSegmentsFatigue(max) {
const cycle = [5, 2, 4, 1, 3, 0]; const cycle = [5, 2, 4, 1, 3, 0];
const fatigue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; const fatigue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
for (let i = 0; i <= max; i++) { for (let i = 0; i <= max; i++) {
const ligneFatigue = duplicate(fatigue[i]); const ligneFatigue = foundry.utils.duplicate(fatigue[i]);
const caseIncrementee = cycle[i % 6]; const caseIncrementee = cycle[i % 6];
ligneFatigue[caseIncrementee]++; ligneFatigue[caseIncrementee]++;
ligneFatigue[caseIncrementee + 6]++; ligneFatigue[caseIncrementee + 6]++;
@ -45,7 +46,7 @@ function _buildAllSegmentsFatigue(max) {
function _cumulSegmentsFatigue(matrix) { function _cumulSegmentsFatigue(matrix) {
let cumulMatrix = []; let cumulMatrix = [];
for (let line of matrix) { for (let line of matrix) {
let cumul = duplicate(line); let cumul = foundry.utils.duplicate(line);
for (let i = 1; i < 12; i++) { for (let i = 1; i < 12; i++) {
cumul[i] += cumul[i - 1]; cumul[i] += cumul[i - 1];
@ -63,12 +64,6 @@ const cumulFatigueMatrix = _cumulSegmentsFatigue(fatigueMatrix);
const fatigueMalus = [0, 0, 0, -1, -1, -1, -2, -3, -4, -5, -6, -7]; // Provides the malus for each segment of fatigue const fatigueMalus = [0, 0, 0, -1, -1, -1, -2, -3, -4, -5, -6, -7]; // Provides the malus for each segment of fatigue
const fatigueLineSize = [3, 6, 7, 8, 9, 10, 11, 12]; const fatigueLineSize = [3, 6, 7, 8, 9, 10, 11, 12];
const fatigueLineMalus = [0, -1, -2, -3, -4, -5, -6, -7]; const fatigueLineMalus = [0, -1, -2, -3, -4, -5, -6, -7];
const fatigueMarche = {
"aise": { "4": 1, "6": 2, "8": 3, "10": 4, "12": 6 },
"malaise": { "4": 2, "6": 3, "8": 4, "10": 6 },
"difficile": { "4": 3, "6": 4, "8": 6 },
"tresdifficile": { "4": 4, "6": 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"];
@ -208,6 +203,8 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/coeur/afficher-coeur.hbs', 'systems/foundryvtt-reve-de-dragon/templates/coeur/afficher-coeur.hbs',
'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs', 'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs',
'systems/foundryvtt-reve-de-dragon/templates/time/horloge.hbs', 'systems/foundryvtt-reve-de-dragon/templates/time/horloge.hbs',
'systems/foundryvtt-reve-de-dragon/templates/voyage/fatigue-actor.hbs',
'systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs', 'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs', 'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs', 'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
@ -215,15 +212,16 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-astrologique.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-coeur.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-competences.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffFixe.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffFixe.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffCondition.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffCondition.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-coeur.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-competences.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-item-hautrevant.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-item-hautrevant.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-item-frequence.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-item-frequence.html',
@ -287,6 +285,7 @@ export class RdDUtility {
Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree()); Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree());
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode()); Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());
Handlebars.registerHelper('array-includes', (array, value) => array.includes(value));
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) => ReglesOptionnelles.isUsing(option)); Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionnelles.isUsing(option));
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name))); Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
@ -551,49 +550,54 @@ export class RdDUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async jetEncaissement(rollData, armure, options = { showDice: HIDE_DICE }) { static async jetEncaissement(rollData, armure, options = { showDice: HIDE_DICE }) {
let formula = "2d10"; const diff = Math.abs(rollData.diffLibre);
let formula = RdDUtility.formuleEncaissement(diff, options)
const roll = await RdDDice.roll(formula, options);
// Chaque dé fait au minmum la difficulté libre RdDUtility.remplaceDeMinParDifficulte(roll, diff, options);
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre')) {
if (rollData.diffLibre < 0) {
let valeurMin = Math.abs(rollData.diffLibre);
formula += "min" + valeurMin;
}
}
// Chaque dé fait au minmum la difficulté libre
if (ReglesOptionnelles.isUsing('degat-ajout-malus-libre')) {
if (rollData.diffLibre < 0) {
let valeurMin = Math.abs(rollData.diffLibre);
formula += "+" + valeurMin;
}
}
let roll = await RdDDice.roll(formula, options);
// 1 dé fait au minmum la difficulté libre
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre-simple')) {
if (rollData.diffLibre < 0) {
let valeurMin = Math.abs(rollData.diffLibre);
if (roll.terms[0].results[0].result < valeurMin) {
roll.terms[0].results[0].result = valeurMin;
} else if (roll.terms[0].results[1].result < valeurMin) {
roll.terms[0].results[1].result = valeurMin;
}
roll._total = roll.terms[0].results[0].result + roll.terms[0].results[1].result;
}
}
return await RdDUtility.prepareEncaissement(rollData, roll, armure); return await RdDUtility.prepareEncaissement(rollData, roll, armure);
} }
static remplaceDeMinParDifficulte(roll, diff, options) {
if (!ReglesOptionnelles.isUsing('degat-minimum-malus-libre-simple')) {
return
}
// 1 dé fait au minmum la difficulté libre
const total = options.forceDiceResult?.total;
if (total) {
const reste = Math.max(total - diff, 1)
roll.terms[0].number = reste + diff
}
else {
if (roll.terms[0].results[0].result < diff) {
roll.terms[0].results[0].result = diff;
} else if (roll.terms[0].results[1].result < diff) {
roll.terms[0].results[1].result = diff;
}
roll._total = roll.terms[0].results[0].result + roll.terms[0].results[1].result;
}
}
static formuleEncaissement(diff, options) {
// Chaque dé fait au minimum la difficulté libre
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre')) {
return `2d10min${diff}`
}
return '2d10'
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async prepareEncaissement(rollData, roll, armure) { static async prepareEncaissement(rollData, roll, armure) {
const jetTotal = roll.total + rollData.dmg.total - armure; // La difficulté d'ataque s'ajoute aux dégâts
let encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite); const bonusDegatsDiffLibre = ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(rollData.diffLibre ?? 0) : 0
let over20 = Math.max(jetTotal - 20, 0); const jetTotal = roll.total + rollData.dmg.total - armure + bonusDegatsDiffLibre
const encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite);
const over20 = Math.max(jetTotal - 20, 0);
encaissement.dmg = rollData.dmg; encaissement.dmg = rollData.dmg;
encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(this.type); encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(this.type);
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;'; encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;';
encaissement.dmg.bonusDegatsDiffLibre = bonusDegatsDiffLibre
encaissement.roll = roll; encaissement.roll = roll;
encaissement.armure = armure; encaissement.armure = armure;
encaissement.penetration = rollData.arme?.system.penetration ?? 0; encaissement.penetration = rollData.arme?.system.penetration ?? 0;
@ -609,10 +613,10 @@ export class RdDUtility {
for (let encaissement of table) { for (let encaissement of table) {
if ((encaissement.minimum === undefined || encaissement.minimum <= degats) if ((encaissement.minimum === undefined || encaissement.minimum <= degats)
&& (encaissement.maximum === undefined || degats <= encaissement.maximum)) { && (encaissement.maximum === undefined || degats <= encaissement.maximum)) {
return duplicate(encaissement); return foundry.utils.duplicate(encaissement);
} }
} }
return duplicate(table[0]); return foundry.utils.duplicate(table[0]);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -622,21 +626,15 @@ export class RdDUtility {
return perte.total; return perte.total;
} }
/* -------------------------------------------- */
static async responseNombreAstral(callData) {
let actor = game.actors.get(callData.id);
actor.ajouteNombreAstral(callData);
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static onSocketMessage(sockmsg) { static onSocketMessage(sockmsg) {
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_app_astrologie_refresh":
return Hooks.callAll(APP_ASTROLOGIE_REFRESH);
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":
return RdDUtility.responseNombreAstral(sockmsg.data);
case "msg_tmr_move": case "msg_tmr_move":
let actor = game.actors.get(sockmsg.data.actorId); let actor = game.actors.get(sockmsg.data.actorId);
if (actor.isOwner || game.user.isGM) { if (actor.isOwner || game.user.isGM) {

View File

@ -74,6 +74,17 @@ export const referenceAjustements = {
getLabel: (rollData, actor) => 'Sur-encombrement', getLabel: (rollData, actor) => 'Sur-encombrement',
getValue: (rollData, actor) => actor.computeMalusSurEncombrement() getValue: (rollData, actor) => actor.computeMalusSurEncombrement()
}, },
rituel: {
isUsed: (rollData, actor) => actor.isPersonnage() && ReglesOptionnelles.isUsing("astrologie") && rollData.selectedSort?.system.isrituel,
getLabel: (rollData, actor) => 'Astrologique',
getValue: (rollData, actor) => actor.ajustementAstrologique()
},
astrologique: {
isVisible: (rollData, actor) => actor.isPersonnage() && ReglesOptionnelles.isUsing("astrologie") && RdDCarac.isChance(rollData.selectedCarac),
isUsed: (rollData, actor) => RdDCarac.isChance(rollData.selectedCarac) && rollData.use.astrologique,
getLabel: (rollData, actor) => 'Astrologique',
getValue: (rollData, actor) => actor.ajustementAstrologique()
},
moral: { moral: {
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac) && rollData.use?.moral, isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac) && rollData.use?.moral,
isUsed: (rollData, actor) => rollData.use.moral, isUsed: (rollData, actor) => rollData.use.moral,
@ -84,18 +95,13 @@ export const referenceAjustements = {
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isVolonte(rollData.selectedCarac), isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isVolonte(rollData.selectedCarac),
isUsed: (rollData, actor) => rollData.use.coeur != undefined, isUsed: (rollData, actor) => rollData.use.coeur != undefined,
getLabel: (rollData, actor) => 'Ajustement de c&oelig;ur', getLabel: (rollData, actor) => 'Ajustement de c&oelig;ur',
getValue: (rollData, actor) => -2 * (rollData.use?.coeur?.coeur ?? 0) getValue: (rollData, actor) => -2 * (rollData.use.coeur?.coeur ?? 0)
}, },
moralTotal: { moralTotal: {
isUsed: (rollData, actor) => RdDCarac.isVolonte(rollData.selectedCarac), isUsed: (rollData, actor) => RdDCarac.isVolonte(rollData.selectedCarac),
getLabel: (rollData, actor) => 'Moral', getLabel: (rollData, actor) => 'Moral',
getValue: (rollData, actor) => actor.getMoralTotal() getValue: (rollData, actor) => actor.getMoralTotal()
}, },
astrologique: {
isUsed: (rollData, actor) => ReglesOptionnelles.isUsing("astrologie") && RdDBonus.isAjustementAstrologique(rollData),
getLabel: (rollData, actor) => 'Astrologique',
getValue: (rollData, actor) => actor.ajustementAstrologique()
},
facteurSign: { facteurSign: {
isUsed: (rollData, actor) => rollData.diviseurSignificative > 1, isUsed: (rollData, actor) => rollData.diviseurSignificative > 1,
getLabel: (rollData, actor) => Misc.getFractionHtml(rollData.diviseurSignificative), getLabel: (rollData, actor) => Misc.getFractionHtml(rollData.diviseurSignificative),
@ -160,7 +166,7 @@ export class RollDataAjustements {
/* -------------------------------------------- */ /* -------------------------------------------- */
static calcul(rollData, actor) { static calcul(rollData, actor) {
// s'assurer de la correction des infos rollData // s'assurer de la correction des infos rollData
mergeObject(rollData, { ajustements: {}, use: {} }, { overwrite: false }) foundry.utils.mergeObject(rollData, { ajustements: {}, use: {} }, { overwrite: false })
for (var key in referenceAjustements) { for (var key in referenceAjustements) {
const reference = referenceAjustements[key]; const reference = referenceAjustements[key];
@ -193,4 +199,5 @@ export class RollDataAjustements {
RdDCarac.isChance(selectedCarac) || RdDCarac.isChance(selectedCarac) ||
(RdDCarac.isReve(selectedCarac) && !rollData.competence); (RdDCarac.isReve(selectedCarac) && !rollData.competence);
} }
} }

View File

@ -71,7 +71,7 @@ export class ReglesOptionnelles extends FormApplication {
static get defaultOptions() { static get defaultOptions() {
const options = super.defaultOptions; const options = super.defaultOptions;
mergeObject(options, { foundry.utils.mergeObject(options, {
id: "regles-optionnelles", id: "regles-optionnelles",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.html", template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.html",
height: 650, height: 650,
@ -86,7 +86,7 @@ export class ReglesOptionnelles extends FormApplication {
getData() { getData() {
let formData = super.getData(); let formData = super.getData();
const regles = listeReglesOptionnelles.filter(it => game.user.isGM || it.scope == "client").map(it => { const regles = listeReglesOptionnelles.filter(it => game.user.isGM || it.scope == "client").map(it => {
it = duplicate(it); it = foundry.utils.duplicate(it);
it.id = ReglesOptionnelles._getIdRegle(it.name); it.id = ReglesOptionnelles._getIdRegle(it.name);
it.active = ReglesOptionnelles.isSet(it.name); it.active = ReglesOptionnelles.isSet(it.name);
return it; return it;

View File

@ -1,13 +1,13 @@
import { SYSTEM_RDD } from "../constants.js"; import { SYSTEM_RDD } from "../constants.js";
export const STATUSES = { export const STATUSES = {
StatusStunned : 'stun', StatusStunned: 'stun',
StatusBleeding: 'bleeding', StatusBleeding: 'bleeding',
StatusProne: 'prone', StatusProne: 'prone',
StatusGrappling: 'grappling', StatusGrappling: 'grappling',
StatusGrappled: 'grappled', StatusGrappled: 'grappled',
StatusRestrained: 'restrain', StatusRestrained: 'restrain',
StatusUnconscious: 'unconscious', StatusUnconscious: 'unconscious',
StatusBlind: 'blind', StatusBlind: 'blind',
StatusComma: 'comma', StatusComma: 'comma',
StatusDead: 'dead', StatusDead: 'dead',
@ -18,8 +18,8 @@ const rddStatusEffects = [
{ rdd: true, id: STATUSES.StatusStunned, label: 'EFFECT.StatusStunned', icon: 'icons/svg/stoned.svg', "duration.rounds": 1 }, { rdd: true, id: STATUSES.StatusStunned, label: 'EFFECT.StatusStunned', icon: 'icons/svg/stoned.svg', "duration.rounds": 1 },
{ rdd: true, id: STATUSES.StatusBleeding, label: 'EFFECT.StatusBleeding', icon: 'icons/svg/blood.svg' }, { rdd: true, id: STATUSES.StatusBleeding, label: 'EFFECT.StatusBleeding', icon: 'icons/svg/blood.svg' },
{ rdd: true, id: STATUSES.StatusProne, label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg' }, { rdd: true, id: STATUSES.StatusProne, label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg' },
{ rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' }, { rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.svg' },
{ rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' }, { rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.svg' },
{ rdd: true, id: STATUSES.StatusRestrained, label: 'EFFECT.StatusRestrained', icon: 'icons/svg/net.svg' }, { rdd: true, id: STATUSES.StatusRestrained, label: 'EFFECT.StatusRestrained', icon: 'icons/svg/net.svg' },
{ rdd: true, id: STATUSES.StatusUnconscious, label: 'EFFECT.StatusUnconscious', icon: 'icons/svg/unconscious.svg' }, { rdd: true, id: STATUSES.StatusUnconscious, label: 'EFFECT.StatusUnconscious', icon: 'icons/svg/unconscious.svg' },
{ rdd: true, id: STATUSES.StatusBlind, label: 'EFFECT.StatusBlind', icon: 'icons/svg/blind.svg' }, { rdd: true, id: STATUSES.StatusBlind, label: 'EFFECT.StatusBlind', icon: 'icons/svg/blind.svg' },
@ -29,13 +29,16 @@ const rddStatusEffects = [
]; ];
const demiReveStatusEffect = rddStatusEffects.find(it => it.id == STATUSES.StatusDemiReve); const demiReveStatusEffect = rddStatusEffects.find(it => it.id == STATUSES.StatusDemiReve);
const statusDemiSurprise = [STATUSES.StatusStunned, STATUSES.StatusProne, STATUSES.StatusRestrained]; const statusDemiSurprise = new Set([STATUSES.StatusStunned, STATUSES.StatusProne, STATUSES.StatusRestrained])
const statusSurpriseTotale = [STATUSES.StatusUnconscious, STATUSES.StatusBlind, STATUSES.StatusComma]; const statusSurpriseTotale = new Set([STATUSES.StatusUnconscious, STATUSES.StatusBlind, STATUSES.StatusComma])
export class StatusEffects extends FormApplication { export class StatusEffects extends FormApplication {
static onReady() { static onReady() {
const rddStatusIds = rddStatusEffects.map(it => it.id); const rddEffectIds = rddStatusEffects.map(it => it.id);
rddStatusEffects.forEach(it => it.flags = { core: { statusId: it.id } }); rddStatusEffects.forEach(it => {
it.statuses = new Set()
it.statuses.add(it.id)
})
const defaultStatusEffectIds = CONFIG.statusEffects.map(it => it.id); const defaultStatusEffectIds = CONFIG.statusEffects.map(it => it.id);
game.settings.register(SYSTEM_RDD, "use-status-effects", { game.settings.register(SYSTEM_RDD, "use-status-effects", {
name: "use-status-effects", name: "use-status-effects",
@ -54,37 +57,47 @@ export class StatusEffects extends FormApplication {
restricted: true restricted: true
}); });
CONFIG.RDD.allEffects = rddStatusEffects.concat(CONFIG.statusEffects.filter(it => !rddStatusIds.includes(it.id))); CONFIG.RDD.allEffects = rddStatusEffects.concat(CONFIG.statusEffects.filter(it => !rddEffectIds.includes(it.id)));
StatusEffects._setUseStatusEffects(StatusEffects._getUseStatusEffects()); StatusEffects._setUseStatusEffects(StatusEffects._getUseStatusEffects());
console.log('statusEffects', CONFIG.statusEffects); console.log('statusEffects', CONFIG.statusEffects);
} }
static valeurSurprise(effect, isCombat) { static valeurSurprise(effect, isCombat) {
// const id = StatusEffects.statusId(effect); if (statusSurpriseTotale.intersects(effect.statuses)) {
if (statusSurpriseTotale.includes(effect.flags?.core?.statusId)) {
return 2; return 2;
} }
return statusDemiSurprise.includes(effect.flags?.core?.statusId) || (isCombat && effect.flags?.core?.statusId == STATUSES.StatusDemiReve) ? 1 : 0; if (statusDemiSurprise.intersects(effect.statuses)) {
return 1
}
if (isCombat && effect.statuses.find(e => e == STATUSES.StatusDemiReve)) {
return 1
}
return 0
} }
static _getUseStatusEffects() { static _getUseStatusEffects() {
return game.settings.get(SYSTEM_RDD, "use-status-effects")?.split(',') ?? []; return game.settings.get(SYSTEM_RDD, "use-status-effects")?.split(',') ?? [];
} }
static _setUseStatusEffects(statusIds) { static _setUseStatusEffects(effectIds) {
if (game.user.isGM) { if (game.user.isGM) {
game.settings.set(SYSTEM_RDD, "use-status-effects", statusIds.join()); game.settings.set(SYSTEM_RDD, "use-status-effects", effectIds.join());
} }
for (let effect of CONFIG.RDD.allEffects) { for (let effect of CONFIG.RDD.allEffects) {
effect.active = effect.rdd || statusIds.includes(effect.flags?.core?.statusId); effect.active = effect.rdd || effectIds.includes(effect.id);
} }
CONFIG.statusEffects = CONFIG.RDD.allEffects.filter(it => it.active); CONFIG.statusEffects = CONFIG.RDD.allEffects.filter(it => it.active);
} }
static status(statusId) { static prepareActiveEffect(effectId) {
return rddStatusEffects.find(it => it.flags?.core?.statusId == statusId); let status = rddStatusEffects.find(it => it.id == effectId)
if (status) {
status = foundry.utils.duplicate(status)
status.statuses = [effectId]
}
return status;
} }
static demiReve() { static demiReve() {
@ -112,7 +125,7 @@ export class StatusEffects extends FormApplication {
getData() { getData() {
const used = StatusEffects._getUseStatusEffects(); const used = StatusEffects._getUseStatusEffects();
let formData = super.getData(); let formData = super.getData();
formData.effects = duplicate(CONFIG.RDD.allEffects); formData.effects = foundry.utils.duplicate(CONFIG.RDD.allEffects);
formData.effects.forEach(it => it.active = used.includes(it.id)) formData.effects.forEach(it => it.active = used.includes(it.id))
return formData; return formData;
} }

View File

@ -27,7 +27,7 @@ export class SystemCompendiums extends FormApplication {
static init() { static init() {
Object.keys(CONFIGURABLE_COMPENDIUMS).forEach(compendium => { Object.keys(CONFIGURABLE_COMPENDIUMS).forEach(compendium => {
const definition = CONFIGURABLE_COMPENDIUMS[compendium]; const definition = CONFIGURABLE_COMPENDIUMS[compendium];
mergeObject(definition, { foundry.utils.mergeObject(definition, {
compendium: compendium, compendium: compendium,
default: SystemCompendiums._getDefaultCompendium(compendium), default: SystemCompendiums._getDefaultCompendium(compendium),
setting: SystemCompendiums._getSettingCompendium(compendium) setting: SystemCompendiums._getSettingCompendium(compendium)
@ -138,7 +138,7 @@ export class SystemCompendiums extends FormApplication {
static get defaultOptions() { static get defaultOptions() {
const options = super.defaultOptions; const options = super.defaultOptions;
mergeObject(options, { foundry.utils.mergeObject(options, {
id: "system-compendiums", id: "system-compendiums",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/system-compendiums.html", template: "systems/foundryvtt-reve-de-dragon/templates/settings/system-compendiums.html",
height: 'fit-content', height: 'fit-content',
@ -152,7 +152,7 @@ export class SystemCompendiums extends FormApplication {
getData() { getData() {
const systemCompendiums = Object.values(CONFIGURABLE_COMPENDIUMS) const systemCompendiums = Object.values(CONFIGURABLE_COMPENDIUMS)
.map(it => mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) })); .map(it => foundry.utils.mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) }));
const availableCompendiums = game.packs.map(pack => { const availableCompendiums = game.packs.map(pack => {
return { return {
name: pack.collection, name: pack.collection,
@ -160,7 +160,7 @@ export class SystemCompendiums extends FormApplication {
type: pack.metadata.type type: pack.metadata.type
} }
}); });
return mergeObject(super.getData(), { return foundry.utils.mergeObject(super.getData(), {
systemCompendiums: systemCompendiums, systemCompendiums: systemCompendiums,
availableCompendiums: availableCompendiums availableCompendiums: availableCompendiums
}); });

View File

@ -17,7 +17,7 @@ export class AppAstrologie extends Application {
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/sommeil/app-astrologie.hbs", template: "systems/foundryvtt-reve-de-dragon/templates/sommeil/app-astrologie.hbs",
title: "Astrologie", title: "Astrologie",
width: 'fit-content', width: 'fit-content',
@ -31,13 +31,12 @@ export class AppAstrologie extends Application {
constructor(actor, options = {}) { constructor(actor, options = {}) {
super(options); super(options);
this.actor = actor; this.actor = actor;
this.hookReference = Hooks.on(APP_ASTROLOGIE_REFRESH, () => this.refreshAstrologie());
} }
getData(options) { getData(options) {
this.appData = super.getData(options) this.appData = super.getData(options)
const calendrier = game.system.rdd.calendrier; const calendrier = game.system.rdd.calendrier;
mergeObject(this.appData, { foundry.utils.mergeObject(this.appData, {
isGM: game.user.isGM, isGM: game.user.isGM,
isActor: this.actor != undefined, isActor: this.actor != undefined,
calendrier: calendrier.getTimestamp().toCalendrier(), calendrier: calendrier.getTimestamp().toCalendrier(),
@ -85,9 +84,10 @@ export class AppAstrologie extends Application {
const nbAstral = calendrier.getNombreAstral() const nbAstral = calendrier.getNombreAstral()
const heures = RdDTimestamp.heures(); const heures = RdDTimestamp.heures();
return { return {
ajustementsActors: game.actors.filter(it => it.isPersonnage() && it.hasPlayerOwner) ajustementsActors: game.actors.filter(actor => actor.isPersonnageJoueur())
.map(actor => this.getAjustementActor(actor, nbAstral, heures)), .map(actor => this.getAjustementActor(actor, nbAstral, heures)),
nombresAstraux: calendrier.getNombresAstraux().map(na => this.getDetailNombreAstral(na)) nombresAstraux: game.system.rdd.calendrier.getNombresAstraux()
.map(na => this.getDetailNombreAstral(na))
} }
} }
return {} return {}
@ -104,22 +104,25 @@ export class AppAstrologie extends Application {
} }
getDetailNombreAstral(nombreAstral) { getDetailNombreAstral(nombreAstral) {
const detail = duplicate(nombreAstral); const detail = foundry.utils.duplicate(nombreAstral);
const timestamp = new RdDTimestamp({ indexDate: nombreAstral.index }); const timestamp = new RdDTimestamp({ indexDate: nombreAstral.index });
detail.date = { mois: timestamp.mois, jour: timestamp.jour + 1 }; detail.date = { mois: timestamp.mois, jour: timestamp.jour + 1 };
detail.valeursFausses.forEach(fausse => fausse.actorName = game.actors.get(fausse.actorId).name ?? "Inconnu"); detail.lectures.forEach(lecture => lecture.actorName = game.actors.get(lecture.actorId).name ?? "Inconnu");
return detail; return detail;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
activateListeners(html) { activateListeners(html) {
if (!this.hookReference){
this.hookReference = Hooks.on(APP_ASTROLOGIE_REFRESH, () => this.refreshAstrologie());
}
super.activateListeners(html); super.activateListeners(html);
this.html = html; this.html = html;
this.html.find('select[name="signe-astral"]').change(event => { this.html.find('select[name="signe-astral"]').change(event => {
this.selectNombreAstral(this.html.find('select[name="signe-astral"]').val()); this.selectNombreAstral(event.currentTarget.value);
}) })
this.html.find('select[name="signe-naissance"]').change(event => { this.html.find('select[name="signe-naissance"]').change(event => {
this.selectHeureNaissance(this.html.find('select[name="signe-naissance"]').val()); this.selectHeureNaissance(event.currentTarget.value);
}) })
this.html.find('td.nombre-astral').click(event => { this.html.find('td.nombre-astral').click(event => {
this.selectNombreAstral(Number.parseInt(event.currentTarget.attributes['data-nombre-astral'].value) - 1); this.selectNombreAstral(Number.parseInt(event.currentTarget.attributes['data-nombre-astral'].value) - 1);
@ -145,8 +148,7 @@ export class AppAstrologie extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
async onRebuild() { async onRebuild() {
game.system.rdd.calendrier.resetNombresAstraux(); await game.system.rdd.calendrier.resetNombresAstraux();
await game.system.rdd.calendrier.rebuildNombresAstraux(); await game.system.rdd.calendrier.rebuildNombresAstraux();
} }
@ -195,6 +197,8 @@ export class AppAstrologie extends Application {
} }
refreshAstrologie() { refreshAstrologie() {
this.count = (this.count ?? 0)+1
console.log(`Refreshing ${this.count}`);
this.render(true) this.render(true)
} }

View File

@ -3,10 +3,8 @@ export class DialogChateauDormant extends Dialog {
static async create() { static async create() {
const date = game.system.rdd.calendrier.dateCourante(); const date = game.system.rdd.calendrier.dateCourante();
const actors = game.actors.filter(actor => actor.hasPlayerOwner && actor.isPersonnage());
const dialogData = { const dialogData = {
actors: actors, actors: game.actors.filter(actor => actor.isPersonnageJoueur()),
date: date, date: date,
motifStress: `Nuit du ${date}`, motifStress: `Nuit du ${date}`,
finChateauDormant: game.system.rdd.calendrier.getTimestampFinChateauDormant() finChateauDormant: game.system.rdd.calendrier.getTimestampFinChateauDormant()

View File

@ -21,7 +21,7 @@ export class DialogRepos extends Dialog {
} }
constructor(html, actor) { constructor(html, actor) {
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 400, height: 'fit-content', 'z-index': 99999 }; let options = { classes: ["dialog-repos"], width: 400, height: 'fit-content', 'z-index': 99999 };
let conf = { let conf = {
title: "Se reposer", title: "Se reposer",
content: html, content: html,

View File

@ -6,7 +6,7 @@ export class DialogStress extends Dialog {
motif: "Motif", motif: "Motif",
stress: 10, stress: 10,
immediat: false, immediat: false,
actors: game.actors.filter(actor => actor.hasPlayerOwner && actor.isPersonnage()) actors: game.actors.filter(actor => actor.isPersonnageJoueur())
.map(actor => ({ .map(actor => ({
id: actor.id, id: actor.id,
name: actor.name, name: actor.name,

View File

@ -61,7 +61,7 @@ export class RdDCalendrierEditor extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
updateData(calendrierData) { updateData(calendrierData) {
this.calendrierData = duplicate(calendrierData); this.calendrierData = foundry.utils.duplicate(calendrierData);
} }
} }

View File

@ -35,7 +35,7 @@ export class RdDCalendrier extends Application {
} }
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
title: "Calendrier", title: "Calendrier",
template: TEMPLATE_CALENDRIER, template: TEMPLATE_CALENDRIER,
classes: ["calendar"], classes: ["calendar"],
@ -51,7 +51,6 @@ export class RdDCalendrier extends Application {
this.timestamp = RdDTimestamp.getWorldTime(); this.timestamp = RdDTimestamp.getWorldTime();
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
RdDTimestamp.setWorldTime(this.timestamp); RdDTimestamp.setWorldTime(this.timestamp);
this.nombresAstraux = this.getNombresAstraux();
this.rebuildNombresAstraux(); // Ensure always up-to-date this.rebuildNombresAstraux(); // Ensure always up-to-date
} }
Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id)); Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id));
@ -108,7 +107,10 @@ export class RdDCalendrier extends Application {
this.timestamp = RdDTimestamp.getWorldTime(); this.timestamp = RdDTimestamp.getWorldTime();
this.positionAiguilles() this.positionAiguilles()
this.render(false); this.render(false);
Hooks.callAll(APP_ASTROLOGIE_REFRESH); Hooks.callAll(APP_ASTROLOGIE_REFRESH)
}
if (setting.key == SYSTEM_RDD + '.' + "liste-nombre-astral") {
Hooks.callAll(APP_ASTROLOGIE_REFRESH)
} }
} }
@ -120,7 +122,7 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
fillCalendrierData(formData = {}) { fillCalendrierData(formData = {}) {
mergeObject(formData, this.timestamp.toCalendrier()); foundry.utils.mergeObject(formData, this.timestamp.toCalendrier());
formData.isGM = game.user.isGM; formData.isGM = game.user.isGM;
formData.heures = RdDTimestamp.definitions() formData.heures = RdDTimestamp.definitions()
formData.horlogeAnalogique = this.horlogeAnalogique; formData.horlogeAnalogique = this.horlogeAnalogique;
@ -167,7 +169,11 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
getNombresAstraux() { getNombresAstraux() {
return game.settings.get(SYSTEM_RDD, "liste-nombre-astral") ?? []; return game.settings.get(SYSTEM_RDD, "liste-nombre-astral") ?? []
}
async setNombresAstraux(nombresAstraux) {
await game.settings.set(SYSTEM_RDD, "liste-nombre-astral", nombresAstraux)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -225,20 +231,15 @@ export class RdDCalendrier extends Application {
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: HIDE_DICE, rollMode: "selfroll" }); const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: HIDE_DICE, rollMode: "selfroll" });
return { return {
nombreAstral: nombreAstral, nombreAstral: nombreAstral,
valeursFausses: [], lectures: [],
index: indexDate index: indexDate
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
resetNombresAstraux() { async resetNombresAstraux() {
this.nombresAstraux = []; await Promise.all(game.actors.filter(it => it.type == "personnage").map(async it => await it.deleteNombresAstraux()))
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", []); await this.setNombresAstraux([])
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_reset_nombre_astral",
data: {}
});
} }
/** /**
@ -251,39 +252,30 @@ export class RdDCalendrier extends Application {
if (indexDate == undefined) { if (indexDate == undefined) {
indexDate = this.timestamp.indexDate; indexDate = this.timestamp.indexDate;
} }
this.nombresAstraux = this.getNombresAstraux(); const nombresAstraux = this.getNombresAstraux()
let astralData = this.nombresAstraux.find((nombreAstral, i) => nombreAstral.index == indexDate); let astralData = nombresAstraux.find(it => it.index == indexDate);
return astralData?.nombreAstral ?? 0; return astralData?.nombreAstral ?? 0;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rebuildNombresAstraux() { async rebuildNombresAstraux() {
if (Misc.isUniqueConnectedGM()) { if (Misc.isUniqueConnectedGM()) {
let newList = []; const nombresAstraux = this.getNombresAstraux()
let newNombresAstraux = [];
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) { for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
let dayIndex = this.timestamp.indexDate + i; let dayIndex = this.timestamp.indexDate + i;
let na = this.nombresAstraux.find(n => n.index == dayIndex); let na = nombresAstraux.find(it => it.index == dayIndex);
if (na) { if (na) {
newList[i] = na; newNombresAstraux[i] = na;
} else { } else {
newList[i] = await this.ajouterNombreAstral(dayIndex); newNombresAstraux[i] = await this.ajouterNombreAstral(dayIndex);
} }
} }
this.nombresAstraux = newList;
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", newList);
game.actors.filter(it => it.isPersonnage()).forEach(actor => actor.supprimerAnciensNombresAstraux()); game.actors.filter(it => it.isPersonnage()).forEach(actor => actor.supprimerAnciensNombresAstraux());
this.notifyChangeNombresAstraux(); await this.setNombresAstraux(newNombresAstraux);
} }
} }
notifyChangeNombresAstraux() {
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_refresh_nombre_astral",
data: {}
});
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async setNewTimestamp(newTimestamp) { async setNewTimestamp(newTimestamp) {
const oldTimestamp = this.timestamp; const oldTimestamp = this.timestamp;
@ -373,25 +365,22 @@ export class RdDCalendrier extends Application {
request.nbAstral = await RdDDice.rollTotal("1dhr" + request.nbAstral, { request.nbAstral = await RdDDice.rollTotal("1dhr" + request.nbAstral, {
rollMode: "selfroll", showDice: HIDE_DICE rollMode: "selfroll", showDice: HIDE_DICE
}); });
// Mise à jour des nombres astraux du joueur
this.addNbAstralIncorect(request.id, request.date, request.nbAstral);
}
if (Misc.getActiveUser(request.userId)?.isGM) {
RdDUtility.responseNombreAstral(request);
} else {
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_response_nombre_astral",
data: request
});
} }
// Mise à jour des nombres astraux du joueur
await this.addNbAstralJoueur(actor, request.date, request.nbAstral, request.isValid)
Hooks.callAll(APP_ASTROLOGIE_REFRESH)
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_app_astrologie_refresh", data: {} })
} }
} }
addNbAstralIncorect(actorId, date, nbAstral) { async addNbAstralJoueur(actor, date, nbAstral, isValid) {
const astralData = this.nombresAstraux.find((nombreAstral, i) => nombreAstral.index == date); const nombresAstraux = this.getNombresAstraux()
astralData.valeursFausses.push({ actorId: actorId, nombreAstral: nbAstral }); const astralData = nombresAstraux.find(it => it.index == date)
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.nombresAstraux); if (astralData) {
astralData.lectures.push({ actorId: actor.id, nombreAstral: nbAstral });
await this.setNombresAstraux(nombresAstraux);
await actor.ajouteNombreAstral(date, nbAstral, isValid);
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -202,7 +202,7 @@ export class RdDTimestamp {
} }
static setWorldTime(timestamp) { static setWorldTime(timestamp) {
game.settings.set(SYSTEM_RDD, WORLD_TIMESTAMP_SETTING, duplicate(timestamp)); game.settings.set(SYSTEM_RDD, WORLD_TIMESTAMP_SETTING, foundry.utils.duplicate(timestamp));
} }
/** construit un RdDTimestamp à partir de l'année/mois/jour/heure?/minute? */ /** construit un RdDTimestamp à partir de l'année/mois/jour/heure?/minute? */

View File

@ -117,7 +117,7 @@ function $loadFilters(parameters) {
export class FenetreRechercheTirage extends Application { export class FenetreRechercheTirage extends Application {
static get defaultOptions() { static get defaultOptions() {
return mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/tirage/fenetre-recherche-tirage.hbs", template: "systems/foundryvtt-reve-de-dragon/templates/tirage/fenetre-recherche-tirage.hbs",
title: `Recherches et tirages`, title: `Recherches et tirages`,
width: 600, width: 600,
@ -133,7 +133,7 @@ export class FenetreRechercheTirage extends Application {
const parameters = { const parameters = {
milieux: milieux, milieux: milieux,
filterMilieux: $filterMilieux(milieux), filterMilieux: $filterMilieux(milieux),
filterGroups: duplicate(FILTER_GROUPS).filter(it => it.group), filterGroups: foundry.utils.duplicate(FILTER_GROUPS).filter(it => it.group),
} }
const options = {} const options = {}
$loadFilters(parameters); $loadFilters(parameters);
@ -147,7 +147,7 @@ export class FenetreRechercheTirage extends Application {
} }
async getData() { async getData() {
return mergeObject(await super.getData(), this.parameters) return foundry.utils.mergeObject(await super.getData(), this.parameters)
} }
_canDragStart() { return true; } _canDragStart() { return true; }
@ -294,7 +294,7 @@ class FenetreRechercheConfiguration extends Dialog {
static async create() { static async create() {
const configuration = { const configuration = {
compendiums: game.packs.filter(it => it.metadata.type == 'Item').map(it => it.metadata) compendiums: game.packs.filter(it => it.metadata.type == 'Item').map(it => it.metadata)
.map(it => mergeObject({ selected: game.system.rdd.environnement.compendiums.includes(it.id) }, it)) .map(it => foundry.utils.mergeObject({ selected: game.system.rdd.environnement.compendiums.includes(it.id) }, it))
} }
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/tirage/fenetre-recherche-configuration.hbs", configuration); const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/tirage/fenetre-recherche-configuration.hbs", configuration);
new FenetreRechercheConfiguration(html).render(true); new FenetreRechercheConfiguration(html).render(true);

View File

@ -39,6 +39,8 @@ export class TMRRencontres {
const frequence = it => it.system.frequence[codeTerrain]; const frequence = it => it.system.frequence[codeTerrain];
const row = await this.table.getRandom(frequence, filtreMauvaise, forcedRoll); const row = await this.table.getRandom(frequence, filtreMauvaise, forcedRoll);
if (row) { if (row) {
console.log("DORM", row);
//row.document.system.computedForce = new Roll(row.document.system.formula).roll({async: false}).total;
await CompendiumTableHelpers.tableRowToChatMessage(row); await CompendiumTableHelpers.tableRowToChatMessage(row);
} }

View File

@ -18,8 +18,8 @@ export class Draconique {
static isTeteDragon(item) { return item.type == TYPES.tete; } static isTeteDragon(item) { return item.type == TYPES.tete; }
static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); } static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); }
static register(draconique) { static register(draconique, code = undefined) {
registeredEffects[draconique.code()] = draconique; registeredEffects[code ?? draconique.code()] = draconique;
if (draconique.img()) { if (draconique.img()) {
PixiTMR.register(draconique.code(), draconique.img()) PixiTMR.register(draconique.code(), draconique.img())
} }
@ -90,6 +90,15 @@ export class Draconique {
*/ */
token(pixiTMR, linkData, coordTMR, type = undefined) { token(pixiTMR, linkData, coordTMR, type = undefined) {
const tooltip = this.tooltip(linkData); const tooltip = this.tooltip(linkData);
return this._createToken(pixiTMR, linkData, coordTMR, type, tooltip);
}
tokens(pixiTMR, linkData, coordTMR, type = undefined) {
const tooltip = this.tooltip(linkData);
return [this._createToken(pixiTMR, linkData, coordTMR, type, tooltip)];
}
_createToken(pixiTMR, linkData, coordTMR, type, tooltip) {
const token = { const token = {
sprite: this.createSprite(pixiTMR), sprite: this.createSprite(pixiTMR),
coordTMR: coordTMR, coordTMR: coordTMR,

View File

@ -6,7 +6,7 @@ import { ReserveExtensible } from "./reserve-extensible.js";
import { DemiReve } from "./demi-reve.js"; import { DemiReve } from "./demi-reve.js";
import { TrouNoir } from "./trou-noir.js"; import { TrouNoir } from "./trou-noir.js";
import { Rencontre } from "./rencontre.js"; import { Rencontre } from "./rencontre.js";
import { SortReserve } from "./sort-reserve.js"; import { SortReserve, SortReserveHumide } from "./sort-reserve.js";
import { CarteTmr } from "./carte-tmr.js"; import { CarteTmr } from "./carte-tmr.js";
import { PontImpraticable } from "./pont-impraticable.js"; import { PontImpraticable } from "./pont-impraticable.js";
import { Draconique } from "./draconique.js"; import { Draconique } from "./draconique.js";
@ -26,6 +26,7 @@ export class EffetsDraconiques {
static demiReve = new DemiReve(); static demiReve = new DemiReve();
static rencontre = new Rencontre(); static rencontre = new Rencontre();
static sortReserve = new SortReserve(); static sortReserve = new SortReserve();
static sortReserveHumide = new SortReserveHumide();
static debordement = new Debordement(); static debordement = new Debordement();
static presentCites = new PresentCites(); static presentCites = new PresentCites();
static fermetureCites = new FermetureCites(); static fermetureCites = new FermetureCites();
@ -49,6 +50,7 @@ export class EffetsDraconiques {
Draconique.register(EffetsDraconiques.demiReve); Draconique.register(EffetsDraconiques.demiReve);
Draconique.register(EffetsDraconiques.rencontre); Draconique.register(EffetsDraconiques.rencontre);
Draconique.register(EffetsDraconiques.sortReserve); Draconique.register(EffetsDraconiques.sortReserve);
Draconique.register(EffetsDraconiques.sortReserveHumide);
Draconique.register(EffetsDraconiques.debordement); Draconique.register(EffetsDraconiques.debordement);
Draconique.register(EffetsDraconiques.fermetureCites); Draconique.register(EffetsDraconiques.fermetureCites);
Draconique.register(EffetsDraconiques.queteEaux); Draconique.register(EffetsDraconiques.queteEaux);

View File

@ -107,7 +107,7 @@ export class EffetsRencontre {
} }
static rdd_part_tete = async (dialog, context) => { static rdd_part_tete = async (dialog, context) => {
mergeObject(context, { foundry.utils.mergeObject(context, {
tete: context.rolled.isPart, tete: context.rolled.isPart,
poesie: await Poetique.getExtrait() poesie: await Poetique.getExtrait()
}) })
@ -118,7 +118,7 @@ export class EffetsRencontre {
} }
static rdd_echec_queue = async (dialog, context) => { static rdd_echec_queue = async (dialog, context) => {
mergeObject(context, { foundry.utils.mergeObject(context, {
queues: [await context.actor.ajouterQueue()], queues: [await context.actor.ajouterQueue()],
poesie: await Poetique.getExtrait() poesie: await Poetique.getExtrait()
}) })

View File

@ -1,4 +1,3 @@
import { SYSTEM_RDD } from "../constants.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { TMRConstants, tmrTokenZIndex } from "../tmr-constants.js"; import { TMRConstants, tmrTokenZIndex } from "../tmr-constants.js";
import { TMRUtility } from "../tmr-utility.js"; import { TMRUtility } from "../tmr-utility.js";
@ -14,12 +13,12 @@ export class PixiTMR {
static register(name, img) { static register(name, img) {
PixiTMR.textures[name] = img; PixiTMR.textures[name] = img;
} }
static async init() { static async init() {
await Promise.all( await Promise.all(
Object.values(PixiTMR.textures) Object.values(PixiTMR.textures)
.filter(img => img != undefined) .filter(img => img != undefined && !PIXI.utils.TextureCache[img])
.map(async img => PIXI.Sprite.from(await PIXI.Assets.load(img))) .map(async img => PIXI.Sprite.from(await PIXI.Assets.load(img))))
)
} }
constructor(tmrDialog, displaySize) { constructor(tmrDialog, displaySize) {
@ -58,7 +57,7 @@ export class PixiTMR {
this.sizes = new TMRConstants({ size: displaySize }) this.sizes = new TMRConstants({ size: displaySize })
const appSize = PixiTMR.computeTMRSize(this.sizes) const appSize = PixiTMR.computeTMRSize(this.sizes)
this.pixiApp.renderer.resize(appSize.width, appSize.height) this.pixiApp.renderer.resize(appSize.width, appSize.height)
this.tooltipStyle.fontSize = Math.max(this.sizes.size / 4, 16) this.tooltipStyle.fontSize = Math.max(this.sizes.size / 3, 16)
} }
get view() { get view() {
@ -106,8 +105,9 @@ export class PixiTMR {
sprite(code, options = {}) { sprite(code, options = {}) {
let img = PixiTMR.getImgFromCode(code) let img = PixiTMR.getImgFromCode(code)
const texture = PIXI.utils.TextureCache[img] let texture = PIXI.utils.TextureCache[img]
if (!texture) { if (!texture) {
// TODO: charger la texture
console.error("Texture manquante", code, PIXI.utils.TextureCache) console.error("Texture manquante", code, PIXI.utils.TextureCache)
return; return;
} }
@ -199,7 +199,7 @@ export class PixiTMR {
setTooltipPosition(event) { setTooltipPosition(event) {
const oddq = this.sizes.computeEventOddq(event); const oddq = this.sizes.computeEventOddq(event);
this.tooltip.x = oddq.x + (oddq.col > 7 ? -3 * this.sizes.full : this.sizes.quarter); this.tooltip.x = oddq.x + (oddq.col > 7 ? -2.5 * this.sizes.full : this.sizes.quarter);
this.tooltip.y = oddq.y + (oddq.row > 10 ? -this.sizes.size : 0); this.tooltip.y = oddq.y + (oddq.row > 10 ? -this.sizes.size : 0);
} }

View File

@ -49,7 +49,7 @@ export class PresentCites extends Draconique {
content: `La ${this.tmrLabel(casetmr)} vous offre un présent, faites votre choix`, content: `La ${this.tmrLabel(casetmr)} vous offre un présent, faites votre choix`,
buttons: buttons buttons: buttons
}); });
dialog.render(true); await dialog.render(true);
return dialog return dialog
} }

View File

@ -1,5 +1,7 @@
import { tmrTokenZIndex } from "../tmr-constants.js"; import { tmrTokenZIndex } from "../tmr-constants.js";
import { TMRUtility } from "../tmr-utility.js";
import { Draconique } from "./draconique.js"; import { Draconique } from "./draconique.js";
import { EffetsDraconiques } from "./effets-draconiques.js";
export class SortReserve extends Draconique { export class SortReserve extends Draconique {
@ -19,4 +21,19 @@ export class SortReserve extends Draconique {
taille: () => pixiTMR.sizes.third, taille: () => pixiTMR.sizes.third,
}); });
} }
tokens(pixiTMR, linkData, coordTMR, type = undefined) {
if (TMRUtility.getTMR(coordTMR()).type == 'fleuve') {
const tooltip = this.tooltip(linkData)
const fleuves = TMRUtility.getListTMR('fleuve')
return fleuves.map(f => EffetsDraconiques.sortReserveHumide._createToken(pixiTMR, linkData, () => f.coord, type?? this.code(), tooltip))
}
return super.tokens(pixiTMR, linkData, coordTMR, type)
}
}
export class SortReserveHumide extends SortReserve {
code() { return 'sortreservehumide' }
tooltip(sort) { return `${sort.name} en fleuve, r${sort.system.ptreve}` }
img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/sort-reserve-humide.svg' }
} }

View File

@ -0,0 +1,181 @@
import { TYPES } from "../item.js"
import { RdDItemCompetence } from "../item-competence.js"
import { ChatUtility } from "../chat-utility.js"
const CODES_COMPETENCES_VOYAGE = ['Extérieur', 'Forêt', 'Montagne', 'Marais', 'Glace', 'Equitation']
const TABLEAU_FATIGUE_MARCHE = [
{
code: "aise", label: "Aisé", description: "Route ou chemin",
survies: ['Extérieur', 'Equitation'],
vitesses: [{ vitesse: 4, fatigue: 1 }, { vitesse: 6, fatigue: 2 }, { vitesse: 8, fatigue: 3 }, { vitesse: 10, fatigue: 4 }, { vitesse: 12, fatigue: 6 }],
},
{
code: "malaise", label: "Malaisé", description: "Hors piste (herbes et buissons)",
survies: ['Extérieur', 'Equitation'],
vitesses: [{ vitesse: 4, fatigue: 2 }, { vitesse: 6, fatigue: 3 }, { vitesse: 8, fatigue: 4 }, { vitesse: 10, fatigue: 6 }],
},
{
code: "difficile", label: "Difficile", description: "Hors piste (collines, forêt)",
survies: ['Extérieur', 'Forêt', 'Glace', 'Equitation'],
vitesses: [{ vitesse: 4, fatigue: 3 }, { vitesse: 6, fatigue: 4 }, { vitesse: 8, fatigue: 6 }],
},
{
code: "tresdifficile", label: "Très difficile", description: "Hors piste (montagne, jungle, marais)",
survies: ['Forêt', 'Montagne', 'Marais', 'Glace'],
vitesses: [{ vitesse: 4, fatigue: 4 }, { vitesse: 6, fatigue: 6 }],
},
]
export class DialogFatigueVoyage extends Dialog {
static dialog = undefined
static async create() {
if (!game.user.isGM) {
return
}
if (!DialogFatigueVoyage.dialog) {
const parameters = {
tableauFatigueMarche: TABLEAU_FATIGUE_MARCHE,
playerActors: game.actors.filter(actor => actor.isPersonnageJoueur())
.map(actor => DialogFatigueVoyage.prepareActor(actor)),
nombreHeures: 1,
}
DialogFatigueVoyage.setModeDeplacement(parameters, undefined, undefined)
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/voyage/dialog-fatigue-voyage.hbs", parameters);
DialogFatigueVoyage.dialog = new DialogFatigueVoyage(html, parameters);
}
DialogFatigueVoyage.dialog.render(true);
}
static setModeDeplacement(parameters, code, vitesse) {
const ligneFatigueMarche = TABLEAU_FATIGUE_MARCHE.find(it => it.code == code) ?? TABLEAU_FATIGUE_MARCHE[0]
const rythme = ligneFatigueMarche.vitesses.find(it => it.vitesse == vitesse) ?? ligneFatigueMarche.vitesses[0]
parameters.typeTerrain = ligneFatigueMarche
parameters.vitesseDeplacement = rythme.vitesse
parameters.fatigueHoraire = rythme.fatigue
}
static prepareActor(actor) {
const competencesVoyage = {}
CODES_COMPETENCES_VOYAGE.forEach(codeSurvie =>
competencesVoyage[codeSurvie] = RdDItemCompetence.findCompetence(actor.itemTypes[TYPES.competence], codeSurvie, { onMessage: () => { } })
)
return {
actor: actor,
selected: true,
ajustementFatigue: 0,
competencesVoyage: competencesVoyage
}
}
constructor(html, parameters) {
const options = {
classes: ["dialog-fatigue-voyage"],
width: 600,
height: 'fit-content',
'max-height': 900,
'z-index': 99999
}
const conf = {
title: "Fatigue de voyage",
content: html,
buttons: {}
}
super(conf, options);
this.parameters = parameters
this.controls = {}
}
activateListeners(html) {
if (this.html == undefined) {
html.find('select[name="code-terrain"]').trigger("focus")
}
this.html = html;
super.activateListeners(html);
this.html.find('select[name="code-terrain"]').change(event => this.changeParameters())
this.html.find('select[name="vitesse-deplacement"]').change(event => this.changeParameters())
this.html.find('input[name="nombre-heures"]').change(event => this.changeParameters())
this.html.find('button[name="appliquer-fatigue"]').click(event => this.appliquerFatigue())
}
changeParameters() {
this.changeTerrain(this.html.find('select[name="code-terrain"]').val())
this.changeVitesse(this.html.find('select[name="vitesse-deplacement"]').val())
this.changeNombreHeures(this.html.find('input[name="nombre-heures"]').val())
this.setFatigue()
}
async changeTerrain(codeTerrain) {
if (this.parameters.typeTerrain.code != codeTerrain) {
const selectVitesseDeplacement = this.html.find('select[name="vitesse-deplacement"]')
const vitesse = selectVitesseDeplacement.val()
selectVitesseDeplacement.empty()
DialogFatigueVoyage.setModeDeplacement(this.parameters, codeTerrain, vitesse)
this.parameters.typeTerrain.vitesses.forEach(async rythme => {
selectVitesseDeplacement.append(await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs', rythme))
})
selectVitesseDeplacement.val(this.parameters.vitesseDeplacement).change()
}
}
async changeVitesse(vitesse) {
if (this.parameters.vitesseDeplacement != vitesse) {
DialogFatigueVoyage.setModeDeplacement(this.parameters, this.parameters.typeTerrain.code, vitesse)
}
}
async changeNombreHeures(nombreHeures) {
this.parameters.nombreHeures = parseInt(nombreHeures)
}
async setFatigue() {
this.html.find('input[name="base-fatigue"]').val(this.parameters.nombreHeures * this.parameters.fatigueHoraire)
}
async appliquerFatigue() {
const fatigueBase = parseInt(this.html.find('input[name="base-fatigue"]').val() ?? 0)
const actors = jQuery.map(
this.html.find('div.fatigue-actors-list li.list-item'),
it => this.$extractActor(this.html.find(it))
)
actors.filter(it => it.selected)
.forEach(async it => {
const perteFatigue = fatigueBase + it.ajustement
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(it.actor.name),
content: await renderTemplate(
'systems/foundryvtt-reve-de-dragon/templates/voyage/chat-fatigue_voyage.hbs', foundry.utils.mergeObject(it,
{
parameters: this.parameters,
fatigueBase: fatigueBase,
perteFatigue: perteFatigue,
isVoyage: fatigueBase == this.parameters.nombreHeures * this.parameters.fatigueHoraire
})
),
})
await it.actor.santeIncDec("fatigue", perteFatigue)
})
}
$extractActor(actorRow) {
const actor = game.actors.get(actorRow.data('actor-id'))
if (!actor) {
ui.notifications.warn(`Acteur ${it.actorId} introuvable`)
}
return {
actor: actor,
ajustement: parseInt(actorRow.find('input[name="ajustement-fatigue"]').val() ?? 0),
selected: actor && actorRow.find('input[name="selectionner-acteur"]').is(':checked')
}
}
async close() {
DialogFatigueVoyage.dialog = undefined
await super.close()
}
}

View File

@ -92,7 +92,10 @@
--background-custom-button-hover: linear-gradient(to bottom, rgb(128, 0, 0) 5%, rgb(62, 1, 1) 100%); --background-custom-button-hover: linear-gradient(to bottom, rgb(128, 0, 0) 5%, rgb(62, 1, 1) 100%);
--background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%); --background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%);
--background-tooltip: hsla(60, 12%, 85%, 0.95); --background-tooltip: hsla(60, 12%, 85%, 0.95);
--color-tooltip:hsla(282, 47%, 33%, 0.9);
--color-tooltip-faint:hsla(282, 47%, 66%, 0.5);
--background-error:hsla(16, 100%, 50%, 0.8); --background-error:hsla(16, 100%, 50%, 0.8);
--color-profile-border: hsla(0, 0%, 80%, 0.05);
} }
/*@import url("https://fonts.googleapis.com/css2?family=Martel:wght@400;800&family=Roboto:wght@300;400;500&display=swap");*/ /*@import url("https://fonts.googleapis.com/css2?family=Martel:wght@400;800&family=Roboto:wght@300;400;500&display=swap");*/
@ -195,11 +198,10 @@ i:is(.fas, .far, .fa-solid, .fa-regular, .fa-sharp ) {
flex: 0 0 110px; flex: 0 0 110px;
height: 110px; height: 110px;
width: 110px; width: 110px;
margin-right: 0.5rem; padding: 0.2rem;
object-fit: scale-down;
object-position: 50% 0;
margin: 0.1rem;
object-fit: contain; object-fit: contain;
background-color: var(--color-profile-border);
border: 1px solid var(--color-profile-border);
} }
.system-foundryvtt-reve-de-dragon .rdd-item-sheet-tarot img.profile-img { .system-foundryvtt-reve-de-dragon .rdd-item-sheet-tarot img.profile-img {
@ -433,6 +435,7 @@ table {border: 1px solid #7a7971;}
} }
.flex-shrink { .flex-shrink {
flex: 'flex-shrink' ; flex: 'flex-shrink' ;
flex-shrink: 2;
} }
:is(.flex-grow, .flex-grow-3) { :is(.flex-grow, .flex-grow-3) {
flex-grow: 3; flex-grow: 3;
@ -440,7 +443,19 @@ table {border: 1px solid #7a7971;}
.flex-grow-2 { .flex-grow-2 {
flex-grow: 2; flex-grow: 2;
} }
.flex-grow-1 {
flex-grow: 1;
}
.flex-grow-0-5 {
flex-grow: 0.5;
}
.voyage-liste-survies {
max-width: 12rem;
}
/* Styles limited to foundryvtt-reve-de-dragon sheets */ /* Styles limited to foundryvtt-reve-de-dragon sheets */
.texte-dans-liste {
text-align: left;
}
.equipement-nom { .equipement-nom {
flex-grow : 4; flex-grow : 4;
margin: 0; margin: 0;
@ -788,6 +803,10 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) {
.rdd-roll-dialog div.dialog-content input { .rdd-roll-dialog div.dialog-content input {
font-size: 1rem; font-size: 1rem;
} }
.rdd-roll-dialog div.dialog-content input[type="checkbox"]{
width: 1rem;
vertical-align: sub;
}
.rdd-roll-part { .rdd-roll-part {
align-items: center; align-items: center;
border-radius: 6px; padding: 3px; border-radius: 6px; padding: 3px;
@ -959,12 +978,6 @@ section.sheet-body {
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
} }
.sheet header.sheet-header :is(.profile-img, .profile-img-token) {
object-fit: scale-down;
object-position: 50% 0;
margin: 0.5rem 0 0.5rem 0.5rem;
padding: 0;
}
.sheet header.sheet-header h1 { .sheet header.sheet-header h1 {
flex: 3; flex: 3;
} }
@ -1170,7 +1183,7 @@ ul.chat-list li:nth-child(odd) {
border-radius: 0.25rem; border-radius: 0.25rem;
padding: 0.1rem; padding: 0.1rem;
flex: 1 1 1.5rem; flex: 1 1 1.5rem;
display: flex !important; display: flex;
align-items: center !important; align-items: center !important;
} }
@ -1311,10 +1324,7 @@ div.competence-column div.categorie-competence{
margin-right: 0.2rem; margin-right: 0.2rem;
margin-left: 0.2rem; margin-left: 0.2rem;
} }
.blessures-title { .item-label {
font-weight: bold;
}
.alchimie-title {
font-weight: bold; font-weight: bold;
} }
.pointsreve-value { .pointsreve-value {
@ -1363,43 +1373,37 @@ table.table-nombres-astraux tr:hover {
justify-content: flex-start; justify-content: flex-start;
flex-direction: column; flex-direction: column;
position: absolute; position: absolute;
top: 2.75rem; top: 4.6rem;
right: 4rem; right: 3.5rem;
} }
.token-hud-ext.soins { .token-hud-ext.soins {
justify-content: flex-start;
flex-direction: column; flex-direction: column;
position: absolute; position: absolute;
top: 13.2rem; top: 14.7rem;
left: -5rem; left: -6rem;
max-width: 8.5rem max-width: 8rem;
line-height: 1rem;
} }
.token-hud-ext.right { .token-hud-ext.right {
justify-content: flex-start;
flex-direction: column; flex-direction: column;
position: absolute; position: absolute;
top: 2.75rem; top: 4.6rem;
left: 4rem; left: 3.5rem;
} }
.control-icon.token-hud-icon { div.control-icon.token-hud-icon {
width: fit-content; width: 9rem;
height: fit-content; height: fit-content;
border-radius: 0.3rem;
min-width: 6rem; min-width: 6rem;
flex-basis: auto; flex-basis: auto;
padding: 0; padding: 0;
line-height: 1rem; line-height: 0.95rem;
margin: 0.2rem; margin: 0.2rem;
} }
.control-icon.token-hud-icon.right {
margin-left: 8px;
}
.rdd-hud-menu label { .rdd-hud-menu label {
font-size: 0.8rem; font-size: 0.8rem;
} }
#token-hud .status-effects.active{
z-index: 2;
}
/* ======================================== */ /* ======================================== */
.item-checkbox { .item-checkbox {
height: 25px; height: 25px;
@ -1941,6 +1945,23 @@ div.calendar-timestamp-edit select.calendar-signe-heure {
padding: 3px; padding: 3px;
} }
aside#tooltip {
background: var(--background-tooltip);
color: var(--color-text-dark-primary);
font-size: 1rem;
border-radius: 0.2rem;
padding: 0.4rem;
}
aside#tooltip span.reference {
color: var(--color-tooltip);
border: 1px solid var(--color-tooltip-faint);
}
aside#tooltip .toolclip p.faint {
color: var(--color-tooltip-faint);
}
.tooltip :is(.ttt-xp,.ttt-levelup) { .tooltip :is(.ttt-xp,.ttt-levelup) {
width: 250px; width: 250px;
background: var(--background-tooltip) !important; background: var(--background-tooltip) !important;

View File

@ -1,8 +1,8 @@
{ {
"id": "foundryvtt-reve-de-dragon", "id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon", "title": "Rêve de Dragon",
"version": "11.2.8", "version": "11.2.20",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.2.8.zip", "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.2.20.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json",
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
"compatibility": { "compatibility": {
@ -528,8 +528,10 @@
} }
], ],
"socket": true, "socket": true,
"gridDistance": 1, "grid": {
"gridUnits": "m", "distance": 1,
"units": "m"
},
"primaryTokenAttribute": "sante.vie", "primaryTokenAttribute": "sante.vie",
"secondaryTokenAttribute": "sante.endurance", "secondaryTokenAttribute": "sante.endurance",
"media": [ "media": [

View File

@ -525,15 +525,11 @@
}, },
"Item": { "Item": {
"types": [ "types": [
"competence", "competencecreature", "arme", "armure", "blessure", "casetmr", "chant", "competence", "competencecreature", "conteneur", "danse",
"recettealchimique", "musique", "chant", "danse", "jeu", "recettecuisine", "oeuvre", "empoignade", "extraitpoetique", "faune", "gemme", "herbe", "ingredient", "jeu", "livre", "maladie", "meditation",
"objet", "arme", "armure", "conteneur", "herbe", "plante", "ingredient", "faune", "livre", "potion", "munition", "monnaie", "munition", "musique", "nombreastral", "nourritureboisson", "objet", "oeuvre", "ombre", "plante", "possession",
"monnaie", "nourritureboisson", "gemme", "poison", "potion", "queue", "recettealchimique", "recettecuisine", "rencontre",
"service", "service" ,"signedraconique", "sort", "sortreserve", "souffle", "tarot", "tache", "tete" ],
"meditation", "rencontre", "queue", "ombre", "souffle", "tete", "casetmr", "signedraconique", "sort", "sortreserve",
"nombreastral", "tache", "blessure", "maladie", "poison", "possession",
"tarot", "extraitpoetique", "empoignade"
],
"templates": { "templates": {
"description": { "description": {
"description": "", "description": "",

View File

@ -70,9 +70,13 @@
{{#if options.vueDetaillee}} {{#if options.vueDetaillee}}
&nbsp;&nbsp; &nbsp;&nbsp;
{{#if @root.options.vueArchetype}} {{#if @root.options.vueArchetype}}
<a class="competence-archetype toggle-archetype chat-card-button-pushed"><i class="fa-solid fa-up-right-from-square"></i>Incarnation</a> <a class="competence-archetype toggle-archetype chat-card-button-pushed" data-tooltip="Retour à la vue détaillée des compétences">
<i class="fa-solid fa-up-right-from-square"></i>Incarnation
</a>
{{else}} {{else}}
<a class="competence-archetype toggle-archetype chat-card-button"><i class="fa-solid fa-people-line"></i>Archétype</a> <a class="competence-archetype toggle-archetype chat-card-button" data-tooltip="Gestion de l'archétype et de la réincarnation">
<i class="fa-solid fa-people-line"></i>Archétype
</a>
{{/if}} {{/if}}
{{/if}} {{/if}}
</span> </span>

View File

@ -12,19 +12,19 @@
<ul> <ul>
<li data-attribute="resistance" class="flexrow"> <li data-attribute="resistance" class="flexrow">
<span class="carac-label">Résistance</span> <span class="carac-label">Résistance</span>
<a class="resistance-moins"><i class="fas fa-minus-square"></i></a> <a class="resistance-moins"><i class="fa-solid fa-square-minus"></i></a>
<input type="text" name="system.etat.resistance.value" value="{{system.etat.resistance.value}}" data-dtype="Number" /> <input type="text" name="system.etat.resistance.value" value="{{system.etat.resistance.value}}" data-dtype="Number" />
/ /
<input type="text" name="system.etat.resistance.max" value="{{system.etat.resistance.max}}" data-dtype="Number" {{#unless @root.options.vueDetaillee}}disabled{{/unless}} /> <input type="text" name="system.etat.resistance.max" value="{{system.etat.resistance.max}}" data-dtype="Number" {{#unless @root.options.vueDetaillee}}disabled{{/unless}} />
<a class="resistance-plus"><i class="fas fa-plus-square"></i></a> <a class="resistance-plus"><i class="fa-solid fa-square-plus"></i></a>
</li> </li>
<li data-attribute="structure" class="flexrow"> <li data-attribute="structure" class="flexrow">
<span class="carac-label">Structure</span> <span class="carac-label">Structure</span>
<a class="structure-moins"><i class="fas fa-minus-square"></i></a> <a class="structure-moins"><i class="fa-solid fa-square-minus"></i></a>
<input type="text" name="system.etat.structure.value" value="{{system.etat.structure.value}}" data-dtype="Number" /> <input type="text" name="system.etat.structure.value" value="{{system.etat.structure.value}}" data-dtype="Number" />
/ /
<input type="text" name="system.etat.structure.max" value="{{system.etat.structure.max}}" data-dtype="Number" {{#unless @root.options.vueDetaillee}}disabled{{/unless}} /> <input type="text" name="system.etat.structure.max" value="{{system.etat.structure.max}}" data-dtype="Number" {{#unless @root.options.vueDetaillee}}disabled{{/unless}} />
<a class="structure-plus"><i class="fas fa-plus-square"></i></a> <a class="structure-plus"><i class="fa-solid fa-square-plus"></i></a>
</li> </li>
</ul> </ul>
</div> </div>

View File

@ -3,10 +3,12 @@
<ul class="item-list alterne-list"> <ul class="item-list alterne-list">
{{#each (trier recettesAlchimiques) as |recette id|}} {{#each (trier recettesAlchimiques) as |recette id|}}
<li class="item flexrow list-item" data-item-id="{{recette._id}}"><span class="competence-title recette-label item-edit"><a>{{recette.name}}</a></span> <li class="item flexrow list-item" data-item-id="{{recette._id}}"><span class="competence-title recette-label item-edit"><a>{{recette.name}}</a></span>
<div class="item-controls flex-shrink"> <div class="item-controls">
<a class="item-edit" data-tooltip="Edit Item"><i class="fas fa-edit"></i></a> <a class="item-edit" data-tooltip="Modifier"><i class="fas fa-edit"></i></a>
<a class="item-delete" data-tooltip="Delete Item"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
</div> &nbsp;
<a class="item-montrer" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
</div>
</li> </li>
{{/each}} {{/each}}
</ul> </ul>

View File

@ -2,7 +2,8 @@
<ul class="item-list"> <ul class="item-list">
{{#if @root.options.isGM}} {{#if @root.options.isGM}}
<li> <li>
<a class="nouvelle-incarnation chat-card-button"><i class="fa-solid fa-person-circle-plus"></i> Nouvelle incarnation</a> <a class="nouvelle-incarnation chat-card-button" data-tooltip="Création d'une nouvelle incarnation de l'archétype">
<i class="fa-solid fa-person-circle-plus"></i> Nouvelle incarnation</a>
</li> </li>
{{/if}} {{/if}}
<li><hr></li> <li><hr></li>

View File

@ -1,2 +1,7 @@
<h3>Astrologie</h3> <h3>Astrologie</h3>
<span class="astrologie-label"><a name="jet-astrologie">Astrologie : Nombres Astraux</a></span> <span class="astrologie-label chat-card-button">
<a name="jet-astrologie">
<i class="fa-solid fa-moon-over-sun"></i>
Astrologie: Nombres Astraux
</a>
</span>

View File

@ -36,6 +36,7 @@
<span class="item-controls"> <span class="item-controls">
<a class="item-edit" data-tooltip="Editer"><i class="fas fa-edit"></i></a> <a class="item-edit" data-tooltip="Editer"><i class="fas fa-edit"></i></a>
<a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
&nbsp;
<a class="item-montrer" data-tooltip="Montrer"><i class="fas fa-comment"></i></a> <a class="item-montrer" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
</span> </span>
</li> </li>

View File

@ -1,8 +1,14 @@
<h4>blessures</h4> <h4>Blessures</h4>
<div> <div>
<a class="chat-card-button creer-blessure-legere" data-tooltip="Ajouter une blessure légère"><i class="fas fa-plus-circle"></i> légère</a> <a class="chat-card-button creer-blessure-legere" data-tooltip="Ajouter une légère"><i class="fas fa-plus-circle"></i> légère</a>
<a class="chat-card-button creer-blessure-grave" data-tooltip="Ajouter une blessure grave"><i class="fas fa-plus-circle"></i> grave</a> <a class="chat-card-button creer-blessure-grave" data-tooltip="Ajouter une grave"><i class="fas fa-plus-circle"></i> grave</a>
<a class="chat-card-button creer-blessure-critique" data-tooltip="Ajouter une blessure critque"><i class="fas fa-plus-circle"></i> critique</a> <a class="chat-card-button creer-blessure-critique" data-tooltip="Ajouter une critique"><i class="fas fa-plus-circle"></i> critique</a>
</div>
<div>
<a class="chat-card-button subir-blessure-contusion" data-tooltip="Subir une contusion (avec perte d'Endurance)"><i class="fas fa-swords"></i> contusion</a>
<a class="chat-card-button subir-blessure-legere" data-tooltip="Subir une légère (avec perte d'Endurance)"><i class="fas fa-swords"></i> légère</a>
<a class="chat-card-button subir-blessure-grave" data-tooltip="Subir une grave (avec perte d'Endurance/Vie)"><i class="fas fa-swords"></i> grave</a>
<a class="chat-card-button subir-blessure-critique" data-tooltip="Subir une critique (avec perte d'Endurance/Vie)"><i class="fas fa-swords"></i> critique</a>
</div> </div>
<ul class="item-list alterne-list"> <ul class="item-list alterne-list">

View File

@ -12,9 +12,11 @@
<img class="sheet-competence-img" src="{{tache.img}}"/> <img class="sheet-competence-img" src="{{tache.img}}"/>
<span class="competence-title tache-label"><a>{{tache.name}} <span class="competence-title tache-label"><a>{{tache.name}}
({{tache.system.points_de_tache_courant}}/{{tache.system.points_de_tache}})</a></span> ({{tache.system.points_de_tache_courant}}/{{tache.system.points_de_tache}})</a></span>
<div class="item-controls flex-shrink"> <div class="item-controls">
<a class="item-edit" data-tooltip="Edit Item"><i class="fas fa-edit"></i></a> <a class="item-edit" data-tooltip="Modifier"><i class="fas fa-edit"></i></a>
<a class="item-delete" data-tooltip="Delete Item"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
&nbsp;
<a class="item-montrer" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
</div> </div>
</li> </li>
{{/if}} {{/if}}

View File

@ -64,8 +64,8 @@
</span> </span>
<span class="competence-value">{{emp.system.pointsemp}}</span> <span class="competence-value">{{emp.system.pointsemp}}</span>
<div class="item-controls"> <div class="item-controls">
<a class="item-edit" data-tooltip="Edit Item"><i class="fas fa-edit"></i></a> <a class="item-edit" data-tooltip="Modifier"><i class="fas fa-edit"></i></a>
<a class="item-delete" data-tooltip="Delete Item"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}

View File

@ -17,13 +17,13 @@
<span class="equipement-detail-buttons flexrow"> <span class="equipement-detail-buttons flexrow">
{{#unless (or (eq item.type 'service') (and (eq item.type 'conteneur') (not vide)))}} {{#unless (or (eq item.type 'service') (and (eq item.type 'conteneur') (not vide)))}}
{{#if options.isOwner}} {{#if options.isOwner}}
<a class="item-quantite-moins"><i class="fas fa-minus-square"></i></a> <a class="item-quantite-moins"><i class="fa-solid fa-square-minus"></i></a>
{{/if}} {{/if}}
<input {{#unless options.isOwner}}disabled{{/unless}} type="number" data-dtype="Number" <input {{#unless options.isOwner}}disabled{{/unless}} type="number" data-dtype="Number"
class="item-quantite number-x3" name="items[{{item._id}}].system.quantite" class="item-quantite number-x3" name="items[{{item._id}}].system.quantite"
value="{{item.system.quantite}}" /> value="{{item.system.quantite}}" />
{{#if options.isOwner}} {{#if options.isOwner}}
<a class="item-quantite-plus"><i class="fas fa-plus-square"></i></a> <a class="item-quantite-plus"><i class="fa-solid fa-square-plus"></i></a>
{{/if}} {{/if}}
{{/unless}} {{/unless}}
</span> </span>

View File

@ -23,8 +23,8 @@
/> />
{{#if @root.options.vueDetaillee}} {{#if @root.options.vueDetaillee}}
<div class="item-controls"> <div class="item-controls">
<a class="item-edit" data-tooltip="Edit Item"><i class="fas fa-edit"></i></a> <a class="item-edit" data-tooltip="Modifier"><i class="fas fa-edit"></i></a>
<a class="item-delete" data-tooltip="Delete Item"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
</div> </div>
{{/if}} {{/if}}
</li> </li>

View File

@ -6,8 +6,8 @@
<img class="sheet-competence-img" src="{{possession.img}}" data-tooltip="{{possession.name}}"/> <img class="sheet-competence-img" src="{{possession.img}}" data-tooltip="{{possession.name}}"/>
<span class="competence-label">{{possession.name}}</span> <span class="competence-label">{{possession.name}}</span>
<div class="item-controls"> <div class="item-controls">
<a class="item-edit" data-tooltip="Edit Item"><i class="fas fa-edit"></i></a> <a class="item-edit" data-tooltip="Modifier"><i class="fas fa-edit"></i></a>
<a class="item-delete" data-tooltip="Delete Item"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}

View File

@ -48,7 +48,9 @@
{{#if @root.options.isGM}} {{#if @root.options.isGM}}
<a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
{{/if}} {{/if}}
</div> &nbsp;
<a class="item-montrer" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
</div>
{{/if}} {{/if}}
</li> </li>
{{/unless}} {{/unless}}

View File

@ -8,7 +8,8 @@
<a>{{queue.name}}</a> <a>{{queue.name}}</a>
</span> </span>
<div class="item-controls"> <div class="item-controls">
<a class="item-delete" data-tooltip="Delete Item"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
<a class="item-montrer" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
{{#if queue.system.refoulement}} {{#if queue.system.refoulement}}
<a class="item-action">Refouler</a> <a class="item-action">Refouler</a>
{{/if}} {{/if}}

View File

@ -5,8 +5,9 @@
<li class="item flexrow" data-attribute={{key}} data-item-id="{{souffle._id}}" data-tooltip="Souffle: {{souffle.name}}"> <li class="item flexrow" data-attribute={{key}} data-item-id="{{souffle._id}}" data-tooltip="Souffle: {{souffle.name}}">
<img class="sheet-competence-img" src="{{souffle.img}}"/> <img class="sheet-competence-img" src="{{souffle.img}}"/>
<span class="item-edit flex-grow"><a>{{souffle.name}}</a></span> <span class="item-edit flex-grow"><a>{{souffle.name}}</a></span>
<div class="item-controls flex-shrink"> <div class="item-controls">
<a class="item-delete" data-tooltip="Delete Item"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
<a class="item-montrer" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}

View File

@ -5,8 +5,9 @@
<li class="item flexrow" data-attribute={{key}} data-item-id="{{tete._id}}" data-tooltip="Tête: {{tete.name}}"> <li class="item flexrow" data-attribute={{key}} data-item-id="{{tete._id}}" data-tooltip="Tête: {{tete.name}}">
<img class="sheet-competence-img" src="{{tete.img}}"/> <img class="sheet-competence-img" src="{{tete.img}}"/>
<span class="item-edit flex-grow"><a>{{tete.name}}</a></span> <span class="item-edit flex-grow"><a>{{tete.name}}</a></span>
<div class="item-controls flex-shrink"> <div class="item-controls">
<a class="item-delete" data-tooltip="Delete Item"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
<a class="item-montrer" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}

View File

@ -3,23 +3,23 @@
<li data-attribute="vie"> <li data-attribute="vie">
<label class="compteur"> <label class="compteur">
<a class="jet-vie" name="system.sante.vie.label" data-tooltip="Faire un jet de vie">Vie</a> <a class="jet-vie" name="system.sante.vie.label" data-tooltip="Faire un jet de vie">Vie</a>
<a class="vie-moins"><i class="fas fa-minus-square"></i></a> <a class="vie-moins"><i class="fa-solid fa-square-minus"></i></a>
<input class="resource-content" type="text" name="system.sante.vie.value" value="{{system.sante.vie.value}}" data-dtype="Number" /> <input class="resource-content" type="text" name="system.sante.vie.value" value="{{system.sante.vie.value}}" data-dtype="Number" />
/ {{#if @root.options.vueDetaillee}} / {{#if @root.options.vueDetaillee}}
<input class="resource-content" type="text" name="system.sante.vie.max" value="{{system.sante.vie.max}}" data-dtype="Number"/> <input class="resource-content" type="text" name="system.sante.vie.max" value="{{system.sante.vie.max}}" data-dtype="Number"/>
{{else}}{{system.sante.vie.max}}{{/if}} {{else}}{{system.sante.vie.max}}{{/if}}
<a class="vie-plus"><i class="fas fa-plus-square"></i></a> <a class="vie-plus"><i class="fa-solid fa-square-plus"></i></a>
</label> </label>
</li> </li>
<li data-attribute="endurance"> <li data-attribute="endurance">
<label class="compteur"> <label class="compteur">
<a class="jet-endurance" name="system.sante.endurance.label" data-tooltip="Faire un jet d'endurance pour ne pas être sonné">Endurance</a> <a class="jet-endurance" name="system.sante.endurance.label" data-tooltip="Faire un jet d'endurance pour ne pas être sonné">Endurance</a>
<a class="endurance-moins"><i class="fas fa-minus-square"></i></a> <a class="endurance-moins"><i class="fa-solid fa-square-minus"></i></a>
<input class="resource-content" type="text" name="system.sante.endurance.value" value="{{system.sante.endurance.value}}" data-dtype="Number"/> <input class="resource-content" type="text" name="system.sante.endurance.value" value="{{system.sante.endurance.value}}" data-dtype="Number"/>
/ {{#if @root.options.vueDetaillee}} / {{#if @root.options.vueDetaillee}}
<input class="resource-content" type="text" name="system.sante.endurance.max" value="{{system.sante.endurance.max}}" data-dtype="Number"/> <input class="resource-content" type="text" name="system.sante.endurance.max" value="{{system.sante.endurance.max}}" data-dtype="Number"/>
{{else}}{{system.sante.endurance.max}}{{/if}} {{else}}{{system.sante.endurance.max}}{{/if}}
<a class="endurance-plus"><i class="fas fa-plus-square"></i></a> <a class="endurance-plus"><i class="fa-solid fa-square-plus"></i></a>
</label> </label>
</li> </li>
</ul> </ul>

View File

@ -4,12 +4,12 @@
<li data-attribute="endurance"> <li data-attribute="endurance">
<label class="compteur"> <label class="compteur">
Endurance Endurance
<a class="endurance-moins"><i class="fas fa-minus-square"></i></a> <a class="endurance-moins"><i class="fa-solid fa-square-minus"></i></a>
<input class="resource-content" type="text" name="system.sante.endurance.value" value="{{system.sante.endurance.value}}" data-dtype="Number" /> <input class="resource-content" type="text" name="system.sante.endurance.value" value="{{system.sante.endurance.value}}" data-dtype="Number" />
/ {{#if @root.options.vueDetaillee}} / {{#if @root.options.vueDetaillee}}
<input class="resource-content" type="text" name="system.sante.endurance.max" value="{{system.sante.endurance.max}}" data-dtype="Number"/> <input class="resource-content" type="text" name="system.sante.endurance.max" value="{{system.sante.endurance.max}}" data-dtype="Number"/>
{{else}}{{system.sante.endurance.max}}{{/if}} {{else}}{{system.sante.endurance.max}}{{/if}}
<a class="endurance-plus"><i class="fas fa-plus-square"></i></a> <a class="endurance-plus"><i class="fa-solid fa-square-plus"></i></a>
</label> </label>
</li> </li>
</ul> </ul>

View File

@ -3,38 +3,38 @@
<li> <li>
<label class="compteur"> <label class="compteur">
<a class="jet-vie" data-tooltip="Faire un jet de vie">Vie</a> <a class="jet-vie" data-tooltip="Faire un jet de vie">Vie</a>
<a class="vie-moins"><i class="fas fa-minus-square"></i></a> <a class="vie-moins"><i class="fa-solid fa-square-minus"></i></a>
<input class="resource-content" type="text" name="system.sante.vie.value" value="{{system.sante.vie.value}}" data-dtype="Number"/> <input class="resource-content" type="text" name="system.sante.vie.value" value="{{system.sante.vie.value}}" data-dtype="Number"/>
<span>/ {{system.sante.vie.max}}</span> <span>/ {{system.sante.vie.max}}</span>
<a class="vie-plus"><i class="fas fa-plus-square"></i></a> <a class="vie-plus"><i class="fa-solid fa-square-plus"></i></a>
</label> </label>
</li> </li>
<li> <li>
<label class="compteur"> <label class="compteur">
<a class="jet-endurance" data-tooltip="Faire un jet d'endurance pour ne pas être sonné">Endurance</a> <a class="jet-endurance" data-tooltip="Faire un jet d'endurance pour ne pas être sonné">Endurance</a>
<a class="endurance-moins"><i class="fas fa-minus-square"></i></a> <a class="endurance-moins"><i class="fa-solid fa-square-minus"></i></a>
<input class="resource-content" type="text" name="system.sante.endurance.value" value="{{system.sante.endurance.value}}" data-dtype="Number"/> <input class="resource-content" type="text" name="system.sante.endurance.value" value="{{system.sante.endurance.value}}" data-dtype="Number"/>
<span>/ {{system.sante.endurance.max}}</span> <span>/ {{system.sante.endurance.max}}</span>
<a class="endurance-plus"><i class="fas fa-plus-square"></i></a> <a class="endurance-plus"><i class="fa-solid fa-square-plus"></i></a>
</label> </label>
</li> </li>
<li> <li>
<label class="appliquerFatigue compteur tooltip"> <label class="appliquerFatigue compteur tooltip">
<span class="tooltiptext ttt-fatigue">{{{calc.fatigue.html}}}</span> <span class="tooltiptext ttt-fatigue">{{{calc.fatigue.html}}}</span>
Fatigue ({{calc.fatigue.malus}}) Fatigue ({{calc.fatigue.malus}})
<a class="fatigue-moins"><i class="fas fa-minus-square"></i></a> <a class="fatigue-moins"><i class="fa-solid fa-square-minus"></i></a>
<input class="resource-content" type="text" name="system.sante.fatigue.value" value="{{system.sante.fatigue.value}}" data-dtype="Number" /> <input class="resource-content" type="text" name="system.sante.fatigue.value" value="{{system.sante.fatigue.value}}" data-dtype="Number" />
<span>/ {{system.sante.fatigue.max}}</span> <span>/ {{system.sante.fatigue.max}}</span>
<a class="fatigue-plus"><i class="fas fa-plus-square"></i></a> <a class="fatigue-plus"><i class="fa-solid fa-square-plus"></i></a>
</label> </label>
</li> </li>
<li> <li>
<label class="compteur"> <label class="compteur">
<span class="ptreve-actuel" data-tooltip="Faire un jet de Rêve actuel (ou jet de résistance)"><a>Rêve</a></span> <span class="ptreve-actuel" data-tooltip="Faire un jet de Rêve actuel (ou jet de résistance)"><a>Rêve</a></span>
<a class="ptreve-actuel-moins"><i class="fas fa-minus-square"></i></a> <a class="ptreve-actuel-moins"><i class="fa-solid fa-square-minus"></i></a>
<input class="resource-content" class="pointsreve-value" type="text" name="system.reve.reve.value" value="{{system.reve.reve.value}}" data-dtype="Number" /> <input class="resource-content" class="pointsreve-value" type="text" name="system.reve.reve.value" value="{{system.reve.reve.value}}" data-dtype="Number" />
<span>/ {{system.reve.seuil.value}}</span> <span>/ {{system.reve.seuil.value}}</span>
<a class="ptreve-actuel-plus"><i class="fas fa-plus-square"></i></a> <a class="ptreve-actuel-plus"><i class="fa-solid fa-square-plus"></i></a>
</label> </label>
</li> </li>
</ul> </ul>

View File

@ -1,7 +1,7 @@
<div> <div>
{{#if effects}} {{#if effects}}
{{#each effects as |effect key|}} {{#each effects as |effect key|}}
<span class="active-effect" data-effect="{{effect.flags.core.statusId}}"> <span class="active-effect" data-effect="{{effect.id}}">
<img class="button-effect-img {{#if @root.options.isGM}}delete-active-effect{{/if}}" src="{{effect.icon}}" data-tooltip="{{localize effect.name}}" width="24" height="24" /> <img class="button-effect-img {{#if @root.options.isGM}}delete-active-effect{{/if}}" src="{{effect.icon}}" data-tooltip="{{localize effect.name}}" width="24" height="24" />
</span> </span>
{{/each}} {{/each}}

View File

@ -6,8 +6,10 @@
<img class="sheet-competence-img" src="{{casetmr.img}}"/> <img class="sheet-competence-img" src="{{casetmr.img}}"/>
<span class="item-edit"><a>{{casetmr.name}}</a></span> <span class="item-edit"><a>{{casetmr.name}}</a></span>
<span>{{casetmr.system.coord}} - {{caseTmr-label casetmr.system.coord}}</span> <span>{{casetmr.system.coord}} - {{caseTmr-label casetmr.system.coord}}</span>
<div class="item-controls flex-shrink"> <div class="item-controls">
<a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
&nbsp;
<a class="item-montrer" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}

View File

@ -5,9 +5,11 @@
<li class="item flexrow" data-item-id="{{meditation._id}}" data-attribute="{{key}}" data-tooltip="Méditation: {{meditation.name}}"> <li class="item flexrow" data-item-id="{{meditation._id}}" data-attribute="{{key}}" data-tooltip="Méditation: {{meditation.name}}">
<img class="sheet-competence-img" src="{{meditation.img}}"/> <img class="sheet-competence-img" src="{{meditation.img}}"/>
<span class="meditation-label flex-grow"><a data-item-id="{{meditation._id}}">{{meditation.name}} - {{meditation.system.competence}}</a></span> <span class="meditation-label flex-grow"><a data-item-id="{{meditation._id}}">{{meditation.name}} - {{meditation.system.competence}}</a></span>
<div class="item-controls flex-shrink"> <div class="item-controls">
<a class="item-edit" data-tooltip="Editer"><i class="fas fa-edit"></i></a> <a class="item-edit" data-tooltip="Editer"><i class="fas fa-edit"></i></a>
<a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
&nbsp;
<a class="item-montrer" data-tooltip="Montrer"><i class="fas fa-comment"></i></a>
</div> </div>
</li> </li>
{{/each}} {{/each}}

View File

@ -10,7 +10,7 @@
{{#if rencontre.system.date}} {{#if rencontre.system.date}}
<span class="flex-shrink">{{upperFirst rencontre.system.heure}}, le {{rencontre.system.date}}</span> <span class="flex-shrink">{{upperFirst rencontre.system.heure}}, le {{rencontre.system.date}}</span>
{{/if}} {{/if}}
<div class="item-controls flex-shrink"> <div class="item-controls">
<a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>

View File

@ -6,7 +6,7 @@
<img class="sheet-competence-img" src="{{signe.img}}"/> <img class="sheet-competence-img" src="{{signe.img}}"/>
<span class="item-edit flex-grow"><a>{{signe.name}}</a></span> <span class="item-edit flex-grow"><a>{{signe.name}}</a></span>
<span class="flex-shrink">{{signe.system.difficulte}}</span> <span class="flex-shrink">{{signe.system.difficulte}}</span>
<div class="item-controls flex-shrink"> <div class="item-controls">
<a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a> <a class="item-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
</div> </div>
</li> </li>

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