Compare commits

...

36 Commits

Author SHA1 Message Date
0d62b60e38 Merge pull request 'v13.0.16 - La paix d'Illysis' (#782) from VincentVk/foundryvtt-reve-de-dragon:v13 into v13
All checks were successful
Release Creation / build (release) Successful in 3m38s
Reviewed-on: #782
2025-11-02 09:55:25 +01:00
9b91850731 Export de personnage en pdf
Première version d'export de personnage pdf
2025-11-01 01:28:44 +01:00
05c7a91f93 Correction d'un problème à l'ouverture
Pour un personnage saisis dans d'anciennes versions avec un sort
de coût entier, la feuille de personnage ne pouvait pas s'ouvrir
2025-11-01 00:44:26 +01:00
f83fdb3b8f Fix: fenêtre jets V2 hors combat
la fenêtre ne marchait pas hors d'un combat
2025-10-29 02:03:43 +01:00
020ff4b014 Merge pull request 'v13.0.15 - Les pièces d'Illysis' (#781) from VincentVk/foundryvtt-reve-de-dragon:v13 into v13
All checks were successful
Release Creation / build (release) Successful in 1m45s
Reviewed-on: #781
2025-10-28 18:43:25 +01:00
b3c7453823 Fix achat dans les commerces 2025-10-28 17:57:27 +01:00
18d003aa5d Fix colors of tabs and lists in interface
These colors where misbehaving in dark/light themes
2025-10-28 17:57:27 +01:00
0b90badb5e Merge pull request 'v13.0.14 - Le familier d'Illysis' (#779) from VincentVk/foundryvtt-reve-de-dragon:v13 into v13
All checks were successful
Release Creation / build (release) Successful in 2m39s
Reviewed-on: #779
2025-10-25 23:21:59 +02:00
290b5029d1 Correction couleurs sommaires 2025-10-24 22:20:29 +02:00
a7e4aea52d Fix: meditation V2 2025-10-24 01:22:20 +02:00
755d15509e Ajout du StatusEffect surencombré 2025-10-23 20:21:56 +02:00
02cea84ebb Empoignade V2 2025-10-23 12:01:52 +02:00
c47fc4f5b6 Fix scenes image locations 2025-10-22 22:40:07 +02:00
147e49f2cb Gestion des significatives 2025-10-21 01:40:14 +02:00
7f4f942d50 Amélioration des entités
- l'attaquant ne sait plus que c'est une entité de cauchemar (surprise!)
- l'encaissement indique une blessure dans le tchat... même si ce
  n'est que de l'endurance
- les blurettes suivent les règles des entités de cauchemar (p322)
2025-10-21 01:39:23 +02:00
8f4df1af56 Fix: ajustements surprises
Affichage de l'image de la surprise
2025-10-21 01:39:23 +02:00
77f2de2c5f Jet V2 pour les créatures 2025-10-21 01:39:16 +02:00
e5e271e424 Corrections majuscules/couleurs 2025-10-19 23:53:43 +02:00
43ecca8be1 Merge pull request 'v13.0.13 - L'épanouissement d'Illysis' (#777) from VincentVk/foundryvtt-reve-de-dragon:v13 into v13
All checks were successful
Release Creation / build (release) Successful in 2m5s
Reviewed-on: #777
2025-10-18 18:04:36 +02:00
e21f7e398a Création de tâches dans la fenêtre de jets 2025-10-18 00:52:14 +02:00
e16f89743a Affichage des ajustements V2 2025-10-18 00:52:14 +02:00
a6c593c100 Corrections premiers retours 2025-10-18 00:52:14 +02:00
cd8e190082 Merge pull request 'v13.0.12 - La méditation d'Illysis' (#776) from VincentVk/foundryvtt-reve-de-dragon:v13 into v13
All checks were successful
Release Creation / build (release) Successful in 1m49s
Reviewed-on: #776
2025-10-16 20:14:03 +02:00
f2106763c1 v13.0.12 2025-10-16 00:55:58 +02:00
5da5cb0314 Gestion des maladresses 2025-10-16 00:35:43 +02:00
6d7f66569a Lancer de sorts V2 2025-10-15 22:42:14 +02:00
3e8963b20b Impacts uniquement sur l'acteur 2025-10-15 22:42:14 +02:00
2cf5b06da8 Correction: rename bringToTop 2025-10-15 22:42:13 +02:00
68c01fc930 Montée TMR sur méditation
ajout d'un bouton pour aller dans les TMR lors d'une
méditation réussie
2025-10-15 22:42:13 +02:00
3bc1c4871b Biugfix: compétences de jeu
Les compétences de jeu spécifiques (doublon) ne remplacent plus
la compétence active si le jet n'est pas un jet de jeu
2025-10-15 00:26:01 +02:00
3d732e9a8a Suppression des signes draconiques
en cas de descente des TMR, suppression des signes
draconiques éphémères durant seulement 1 round
2025-10-15 00:24:35 +02:00
35f226af5c Correction du générateur aléatoire
- couleurs de cheveux/yeux
- les tailles entre 1m00 et 1m09 sont correctement affichées
- possibilité de positionner le sexe masculin/féminin en un clic
2025-10-14 17:44:39 +02:00
126a0701d8 Merge pull request 'v13.0.11 - Le gambit d'Illysis' (#775) from VincentVk/foundryvtt-reve-de-dragon:v13 into v13
All checks were successful
Release Creation / build (release) Successful in 2m2s
Reviewed-on: #775
2025-10-09 14:14:44 +02:00
edf920b340 Roll V2: cuisine 2025-10-08 16:36:14 +02:00
293af5ab83 Roll V2: les jeux 2025-10-08 16:35:58 +02:00
1bf9e330f4 Petites améliorations 2025-10-05 22:39:08 +02:00
198 changed files with 82158 additions and 1156 deletions

View File

@@ -25,4 +25,7 @@ Merci à eux !!
Toute la propriété intellectuelle leur appartient, ce système est une adaptation destinée à fonctionner sous FoundryVTT. Toute la propriété intellectuelle leur appartient, ce système est une adaptation destinée à fonctionner sous FoundryVTT.
L'ensemble du code est sous licence Creative Commons. L'ensemble du code est sous licence Creative Commons.
# Licences
- L'export pdf utilise la librairie [pdf-lib](https://pdf-lib.js.org/) sous licence [MIT](pdf-lib-LICENSE.md)

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,0)" style=""><path d="m329.5 29.12-8.1 11.4L359 67.16l8.1-11.44zm-88 5.04 24.2 45.36 1.8 1.29 14.8-40.36zm57.6 12.63-16.4 44.8 40.7 28.81 35.3-31.54c-.9-.58-1.9-1.19-2.8-1.84zM59.83 48.56l10.84 45.83 29.63 2.6 2.7-29.63zM470.9 75.41c-5.6 4.71-12.2 8.59-19.5 11.74 5 46.45-14.7 83.45-45.2 109.75-26.5 22.9-60.9 38.4-95 47.9-2.5 4.8-5 9.2-7.4 13.1 41.5 5.4 93.2-21.2 129.2-60 19.8-21.3 34.8-45.9 41.1-69.2 5.2-19.4 4.7-37.42-3.2-53.29zm-351.3 8.71-3 32.48-32.35-2.9 226.55 271 20-16.7 15.3-12.8zM434 93.09c-4.2 1-8.5 2-12.8 2.7-14.9 2.5-30.1 3.1-43.5.3l-41 36.61c4 7 5 15.7 4.5 24.5-.6 12.6-4.3 26.7-9.3 40.9-3 8.3-6.3 16.6-9.9 24.6 26.9-9.2 52.6-22.3 72.5-39.4 26.2-22.8 42.5-51.6 39.5-90.21zM274 107.4l-51.2 72.2 30.6 36.5 58.2-82.1zM173.8 248.8 34.53 445.2l37.53 26.6L204.3 285.3zm233 79.2L273.3 439.5l19.2 23.1L426 351zm-18.3 77.9-35.3 29.4 39.7 47.6 35.3-29.4z" fill="#fff" fill-opacity="1"></path></g></svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,0)" style=""><path d="M243.512 23.29c-27.105 18.337-53.533 32.92-82.274 45.337-2.843 17.364-3.948 34.497-4.05 51.584 28.913 15.41 56.096 32.85 83.33 49.634l7.045 4.344-3.432 7.482c-12.12 26.572-24.33 47.087-46.245 70.3l-5.184 5.512-6.46-3.904c-32.974-19.974-74.472-38.724-113.373-53.95l6.826-17.374c36.79 14.4 75.11 32.32 108.153 51.504 15.396-17.198 25.326-33.354 34.713-52.89-43.44-26.91-86.13-53.51-134.69-70.632-23.012 20.357-37.705 45.243-51.942 70.74 8.324 25.495 6.596 53.376-6.596 77.46 48.58-.593 97.994 2.23 150.666 10.26l5.658.837 1.787 5.44c8.85 26.46 11.79 54.41 8.325 83.588l-.987 8.432-8.466-.187c-40.508-.864-80.175-2.138-118.17.234 1.634 15.94-2.31 30.972-7.724 45.025 13.427 28.54 27.38 55.8 48.29 79.39 41.27-19.05 73.564-31.288 115.93-42.85-3.407-13.72-6.918-26.36-11.097-33.62-5.122-8.9-10.207-13.057-17.85-15.256-15.284-4.4-44.533 2.293-92.894 19.454l-6.243-17.594c48.907-17.354 79.702-26.894 104.283-19.82 9.133 2.628 16.884 8.004 23.066 15.46 14.487-7.627 28.415-16.79 42.053-26.996 12.34-45.92 37.29-81.42 66.626-112.107-7.226-13.52-13.208-27.204-20.563-40.613l-3.394-6.168 5-4.965c23.275-23.13 47.34-40.157 71.87-52.487l8.395 16.716c-20.952 10.53-41.503 25.913-61.795 45.152 12.41 23.91 22.263 45.5 39.457 64.826 37.488-27.124 74.943-51.39 116.84-74.938-13.96-30.473-31.345-58.357-56.286-79.462-32.2 13.38-62.527 17.39-92.61 12.29-14.223 13.25-30.094 22.23-48.756 23.337-29.017 1.722-60.74-15.74-99.174-57.672l6.858-6.295.017-.028.006.006 6.88-6.314c36.702 40.043 63.74 52.87 84.32 51.65 18.514-1.1 35.03-14.95 51.684-35.406-28.827-31.81-64.174-59.94-97.822-84.465zM39.324 277.884c-6.06.022-12.104.098-18.142.223 1.673 26.288 5.512 51.288 14.052 73.732 45.88-5.82 93.308-4.96 141.15-3.87 1.518-21.27-.253-41.69-6.058-61.212-45.528-6.565-88.59-9.03-131.002-8.873z" fill="#fff" fill-opacity="1"></path></g></svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

65
assets/actions/surenc.svg Normal file
View File

@@ -0,0 +1,65 @@
<?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 448 434"
version="1.1"
id="svg6"
sodipodi:docname="surenc.svg"
width="448"
height="434"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="3840"
inkscape:window-height="2054"
id="namedview8"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1.4355469"
inkscape:cx="224"
inkscape:cy="210"
inkscape:window-x="-11"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="svg6" />
<g
class=""
id="g4"
transform="translate(-32,-46)">
<path
d="m 256,46 c -45.074,0 -82,36.926 -82,82 0,25.812 12.123,48.936 30.938,64 H 128 L 32,480 H 480 L 384,192 H 307.062 C 325.877,176.936 338,153.812 338,128 338,82.926 301.074,46 256,46 Z m 0,36 c 25.618,0 46,20.382 46,46 0,25.618 -20.382,46 -46,46 -25.618,0 -46,-20.382 -46,-46 0,-25.618 20.382,-46 46,-46 z m -82.215,202.95 h 23.5 v 33.263 l 33.873,-33.264 h 27.283 l -43.883,43.15 48.4,47.974 H 233.54 l -36.255,-35.888 v 35.888 h -23.5 z m 119.934,21.24 c 4.76,0 8.952,0.934 12.573,2.806 3.62,1.872 6.938,4.82 9.95,8.85 v -10.13 h 21.972 v 61.462 c 0,10.986 -3.48,19.368 -10.438,25.146 -6.917,5.82 -16.968,8.727 -30.152,8.727 -4.272,0 -8.4,-0.325 -12.39,-0.976 a 77.367,77.367 0 0 1 -12.024,-2.99 v -17.03 c 3.826,2.198 7.57,3.826 11.23,4.884 3.664,1.098 7.347,1.648 11.05,1.648 7.162,0 12.41,-1.566 15.746,-4.7 3.337,-3.132 5.006,-8.035 5.006,-14.708 v -4.7 c -3.01,3.986 -6.328,6.916 -9.95,8.788 -3.62,1.87 -7.813,2.808 -12.573,2.808 -8.343,0 -15.238,-3.275 -20.69,-9.826 -5.453,-6.592 -8.18,-14.974 -8.18,-25.146 0,-10.214 2.727,-18.576 8.18,-25.086 5.452,-6.55 12.347,-9.827 20.69,-9.827 z m 8.118,15.746 c -4.517,0 -8.038,1.67 -10.56,5.005 -2.523,3.338 -3.784,8.058 -3.784,14.162 0,6.266 1.22,11.026 3.662,14.28 2.442,3.215 6.003,4.823 10.682,4.823 4.557,0 8.096,-1.67 10.62,-5.006 2.522,-3.337 3.784,-8.036 3.784,-14.098 0,-6.104 -1.262,-10.824 -3.785,-14.16 -2.523,-3.337 -6.062,-5.006 -10.62,-5.006 z"
fill="#ffffff"
fill-opacity="1"
id="path2" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

1
assets/ui/maladresse.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,0)" style=""><path d="M221.313 16a23.682 23.695 0 0 0-23.688 23.688v106.406a23.682 23.695 0 0 0 2.156 9.72 23.682 23.695 0 0 0 3.157 13.81l41.75 71.626-79 55.438 6.094-48.625a23.682 23.695 0 0 0-8.186-20.97l-66.28-81.937a23.682 23.695 0 0 0-33.314-3.5l-9.188 7.438a23.682 23.695 0 0 0-3.53 33.344l59.78 73.906-11.25 89.937a23.682 23.695 0 0 0 12.47 23.876l37.468 53.47a23.695 23.682 1.57 0 0 2.344 2.812 23.682 23.695 0 0 0 13.594 20.062L262 491.53a23.682 23.695 0 0 0 9.97 2.22 23.682 23.695 0 0 0 23.53-2.063l87.156-60.937a23.682 23.695 0 0 0 5.844-33l-6.78-9.688a23.682 23.695 0 0 0-32.97-5.875l-72.406 50.657-59.063-27.625 120.595-84.626a23.695 23.682 1.57 0 0 5.53-5.5 23.682 23.695 0 0 0 14.626-13.594l37.22-91.53 87.813-44.845a23.694 23.682 1.18 0 0 10.312-31.875L488 122.687a23.694 23.682 1.18 0 0-31.875-10.343l-94.688 48.375a23.694 23.682 1.18 0 0-9.843 9.436 23.682 23.695 0 0 0-8.344 10.47l-27.375 67.31-5.22-7.436a23.682 23.695 0 0 0-3-8.844l-50.81-87.094V39.688A23.682 23.695 0 0 0 233.154 16h-11.843zM77.75 376A59.994 60 0 0 0 16 436a59.994 60 0 1 0 120 0 59.994 60 0 0 0-58.25-60z" fill="#fff" fill-opacity="1"></path></g></svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@@ -1,4 +1,73 @@
# 13.0 # 13.0
## 13.0.16 - La paix d'Illysis
- Export de personnages sous forme de feuille de personnage pdf
- Correction d'un problème à l'ouverture de personnages saisis dans d'anciennes versions
- Fenêtre de jet v2
- on peut faire des jets en dehors des combats
## 13.0.15 - Les pièces d'Illysis
- On peut de nouveau acheter dans les commerces
- Corrections V13
- Les textes sur fond "parchemin" ne sont plus affichés en blanc
## 13.0.14 - Le familier d'Illysis
- Les réussites particulières en demi-surprise sont de simples réussites
- Les images des scènes par défaut sont corrigées
- Ajout d'une image de status "sur-encombré"
- Correction V13
- couleur lisible dans les sommaires des journaux et des compendiums
- Amélioration des entités:
- l'attaquant ne sait plus que c'est une entité de cauchemar (surprise!)
- l'encaissement indique une blessure dans le tchat... même si ce n'est que de l'endurance
- les blurettes suivent les règles des entités de cauchemar (p322)
- Nouvelle fenêtre de jets de dés
- attaque/défense des créatures
- les attaques/parades avec une arme trop lourde se font en demi-surprise
- les demandes de défense disparaîssent une fois prises en compte
- empoignade
- l'empoignade est possible avec une initiative d'empoignade, ou en cours d'empoignade
- seule la dague, le pugilat et la dague sont possibles en cours d'empoignade
- jet de Dextérité/Dague pour utiliser la dague en cours d'empoignade (p136)
- attaquer avec une arme un empoigneur donne un +4 si pas d'empoignade (p134)
- la différence de taille donne un bonus/malus en cours d'empoignade (p135)
- les dommages de l'empoignade ajoutent/enlèvent un point d'empoignade
- le statut d'empoignade est affiché sur les tokens
- les défenses contre une empoignade sont corrigées
## 13.0.13 - L'épanouissement d'Illysis
- Fix d'erreur au chargement de templates RollDialog
- Nouvelle fenêtre de jets de dés
- Fix: affichage des points de tâche
- Fix: affichage des ajustements cohérent
- L'ouverture depuis les caractéristiques permet plusieurs types de jets
- On peut créer ou modifier les tâches dans la fenêtre de jets de tâches
- attaque/défense
- les maladresses sont affichées dans le résultat du jet
- le message au défenseur s'affiche correctement
- la difficulté d'attaque s'applique à la défense
- on peut choisir les particulières en rapidité
## 13.0.12 - La méditation d'Illysis
- les signes draconiques éphémères de 1 round sont supprimés à la descente des TMRs
- Générateur de description
- correction des termes pour les couleurs des yeux/cheveux
- ajout de boutons pour forcer le sexe masculin/féminin
- Nouvelle fenêtre de jets de dés
- les méditations proposent un bouton pour monter dans les TMRs
- fenêtre de lancer de sorts
- Correction: les compétences de jeux ne remplacent plus les compétences en dehors des jets de jeu
- gestion des maladresses d'attaque et défense
## 13.0.11 - Le gambit d'Illysis
- Nouvelle fenêtre de jets de dés
- jeux
- cuisine et préparation de nourriture
## 13.0.10 - Les papilles d'Illysis ## 13.0.10 - Les papilles d'Illysis

View File

@@ -160,7 +160,7 @@ select,
min-height: 100px; min-height: 100px;
background: var(--rdd-bg-input-alt); background: var(--rdd-bg-input-alt);
padding: 5px; padding: 5px;
border-radius: 3px; border-radius: 0.2rem;
color: var(--rdd-color-text-primary); color: var(--rdd-color-text-primary);
} }
.system-foundryvtt-reve-de-dragon .monnaie-content .window-content { .system-foundryvtt-reve-de-dragon .monnaie-content .window-content {
@@ -177,7 +177,7 @@ select,
background: var(--fieldset-background); background: var(--fieldset-background);
color: var(--rdd-color-text-primary); color: var(--rdd-color-text-primary);
margin-bottom: 4px; margin-bottom: 4px;
border-radius: 6px; border-radius: 0.5rem;
border-color: var(--rdd-color-text-primary); border-color: var(--rdd-color-text-primary);
border-width: 2px; border-width: 2px;
} }
@@ -207,7 +207,7 @@ select,
border: 1px solid var(--rdd-color-border-input); border: 1px solid var(--rdd-color-border-input);
color: var(--rdd-color-text-input); color: var(--rdd-color-text-input);
padding: 2px 2px; padding: 2px 2px;
border-radius: 3px; border-radius: 0.2rem;
} }
.system-foundryvtt-reve-de-dragon .monnaie-content .form-group input[type="checkbox"] { .system-foundryvtt-reve-de-dragon .monnaie-content .form-group input[type="checkbox"] {
flex: 0 0 20px; flex: 0 0 20px;
@@ -251,7 +251,7 @@ select,
min-height: 100px; min-height: 100px;
background: var(--rdd-bg-input-alt); background: var(--rdd-bg-input-alt);
padding: 5px; padding: 5px;
border-radius: 3px; border-radius: 0.2rem;
color: var(--rdd-color-text-primary); color: var(--rdd-color-text-primary);
} }
.system-foundryvtt-reve-de-dragon .munition-content .window-content { .system-foundryvtt-reve-de-dragon .munition-content .window-content {
@@ -268,7 +268,7 @@ select,
background: var(--fieldset-background); background: var(--fieldset-background);
color: var(--rdd-color-text-primary); color: var(--rdd-color-text-primary);
margin-bottom: 4px; margin-bottom: 4px;
border-radius: 6px; border-radius: 0.5rem;
border-color: var(--rdd-color-text-primary); border-color: var(--rdd-color-text-primary);
border-width: 2px; border-width: 2px;
} }
@@ -298,7 +298,7 @@ select,
border: 1px solid var(--rdd-color-border-input); border: 1px solid var(--rdd-color-border-input);
color: var(--rdd-color-text-input); color: var(--rdd-color-text-input);
padding: 2px 2px; padding: 2px 2px;
border-radius: 3px; border-radius: 0.2rem;
} }
.system-foundryvtt-reve-de-dragon .munition-content .form-group input[type="checkbox"] { .system-foundryvtt-reve-de-dragon .munition-content .form-group input[type="checkbox"] {
flex: 0 0 20px; flex: 0 0 20px;
@@ -342,7 +342,7 @@ select,
min-height: 100px; min-height: 100px;
background: var(--rdd-bg-input-alt); background: var(--rdd-bg-input-alt);
padding: 5px; padding: 5px;
border-radius: 3px; border-radius: 0.2rem;
color: var(--rdd-color-text-primary); color: var(--rdd-color-text-primary);
} }
.system-foundryvtt-reve-de-dragon .tarot-content .window-content { .system-foundryvtt-reve-de-dragon .tarot-content .window-content {
@@ -359,7 +359,7 @@ select,
background: var(--fieldset-background); background: var(--fieldset-background);
color: var(--rdd-color-text-primary); color: var(--rdd-color-text-primary);
margin-bottom: 4px; margin-bottom: 4px;
border-radius: 6px; border-radius: 0.5rem;
border-color: var(--rdd-color-text-primary); border-color: var(--rdd-color-text-primary);
border-width: 2px; border-width: 2px;
} }
@@ -389,7 +389,7 @@ select,
border: 1px solid var(--rdd-color-border-input); border: 1px solid var(--rdd-color-border-input);
color: var(--rdd-color-text-input); color: var(--rdd-color-text-input);
padding: 2px 2px; padding: 2px 2px;
border-radius: 3px; border-radius: 0.2rem;
} }
.system-foundryvtt-reve-de-dragon .tarot-content .form-group input[type="checkbox"] { .system-foundryvtt-reve-de-dragon .tarot-content .form-group input[type="checkbox"] {
flex: 0 0 20px; flex: 0 0 20px;
@@ -530,7 +530,7 @@ select,
margin: 0.1rem 0; margin: 0.1rem 0;
} }
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section subline .warning { .system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section subline .warning {
border-radius: 6px; border-radius: 0.5rem;
background: var(--gradient-warning); background: var(--gradient-warning);
} }
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-img { .system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-img {
@@ -560,6 +560,7 @@ select,
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-detail subline div.poesie-extrait { .system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-detail subline div.poesie-extrait {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: normal;
} }
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-detail subline span.status-surprise { .system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-detail subline span.status-surprise {
display: flex; display: flex;
@@ -576,8 +577,12 @@ select,
display: flow; display: flow;
width: 2.5rem; width: 2.5rem;
text-align: right; text-align: right;
margin: 0 0.2rem 0 0.5rem; margin: 0 0.2rem;
padding: 0 0.2rem; padding: 0 0.2rem;
border: 1px solid ;
border-radius: 0.2rem;
height: 1.5rem;
background: hsla(0, 0%, 0%, 0.2);
} }
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action { .system-foundryvtt-reve-de-dragon .roll-dialog roll-action {
flex-basis: content; flex-basis: content;
@@ -632,24 +637,29 @@ select,
margin: 0 0.1rem; margin: 0 0.1rem;
} }
.system-foundryvtt-reve-de-dragon .roll-dialog roll-carac select[name="select-carac"] { .system-foundryvtt-reve-de-dragon .roll-dialog roll-carac select[name="select-carac"] {
max-width: 6rem; min-width: 6.5rem;
max-width: 8rem;
} }
.system-foundryvtt-reve-de-dragon .roll-dialog roll-comp select[name="select-comp"] { .system-foundryvtt-reve-de-dragon .roll-dialog roll-comp select[name="select-comp"] {
min-width: 8rem; min-width: 8rem;
max-width: 11rem; max-width: 10rem;
margin-left: 1rem; margin-left: 1.5rem;
} }
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="coeur"] select[name="coeur"] { .system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="coeur"] select[name="coeur"] {
max-width: 4rem; max-width: 4rem;
} }
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section img {
max-width: 1rem;
max-height: 1rem;
gap: 0;
margin: 0;
padding: 0;
filter: invert(0.8);
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="tricher"] img { .system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="tricher"] img {
/* image de d100 */ /* image de d100 */
max-width: 2.5rem; max-width: 2.5rem;
max-height: 2.5rem; max-height: 2.5rem;
gap: 0;
margin: 0;
padding: 0;
filter: invert(0.8);
} }
.system-foundryvtt-reve-de-dragon .roll-dialog roll-buttons { .system-foundryvtt-reve-de-dragon .roll-dialog roll-buttons {
display: flex; display: flex;
@@ -701,6 +711,10 @@ select,
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-details div,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-details div {
display: block;
}
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions, .system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-actions,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-actions { .system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-actions {
grid-area: actions; grid-area: actions;
@@ -751,7 +765,10 @@ select,
.system-foundryvtt-reve-de-dragon .window-header { .system-foundryvtt-reve-de-dragon .window-header {
background: rgba(0, 0, 0, 0.75); background: rgba(0, 0, 0, 0.75);
} }
.system-foundryvtt-reve-de-dragon .application .window-content, .system-foundryvtt-reve-de-dragon .application .window-content {
margin: 0;
padding: 0.2rem;
}
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content { .system-foundryvtt-reve-de-dragon .window-app.sheet .window-content {
margin: 0.2rem; margin: 0.2rem;
padding: 0; padding: 0;
@@ -842,7 +859,7 @@ select,
max-width: 1.4rem; max-width: 1.4rem;
max-height: 1.4rem; max-height: 1.4rem;
border: 1px; border: 1px;
background: center / contain no-repeat url('../../assets/ui/icone_parchement_vierge.webp'); background: center / contain no-repeat url('../../icons/templates/icone_parchement_vierge.webp');
} }
.system-foundryvtt-reve-de-dragon .sheet-header .header-compteurs { .system-foundryvtt-reve-de-dragon .sheet-header .header-compteurs {
width: calc(60% - 110px - 1rem); width: calc(60% - 110px - 1rem);
@@ -918,6 +935,12 @@ select,
.system-foundryvtt-reve-de-dragon a:hover { .system-foundryvtt-reve-de-dragon a:hover {
text-shadow: 1px 0px 0px #ff6600; text-shadow: 1px 0px 0px #ff6600;
} }
.system-foundryvtt-reve-de-dragon .tabs .item.active img,
.system-foundryvtt-reve-de-dragon .blessures-list li ul li:first-child:hover img,
.system-foundryvtt-reve-de-dragon i.moral-radio-checkmark-off:hover img,
.system-foundryvtt-reve-de-dragon a:hover img {
filter: drop-shadow(1px 0px 0px #ff6600);
}
.system-foundryvtt-reve-de-dragon .rollable:hover, .system-foundryvtt-reve-de-dragon .rollable:hover,
.system-foundryvtt-reve-de-dragon .rollable:focus { .system-foundryvtt-reve-de-dragon .rollable:focus {
color: #000; color: #000;
@@ -1355,6 +1378,9 @@ select,
margin: 0.1rem 0; margin: 0.1rem 0;
align-items: center; align-items: center;
} }
.system-foundryvtt-reve-de-dragon .prosemirror menu {
background-color: var(--color-background-chat-message);
}
.system-foundryvtt-reve-de-dragon .app.sheet .editor.prosemirror { .system-foundryvtt-reve-de-dragon .app.sheet .editor.prosemirror {
height: fit-content; height: fit-content;
min-height: 5rem; min-height: 5rem;
@@ -1442,12 +1468,27 @@ select,
.system-foundryvtt-reve-de-dragon .competence-list .item-controls.hidden-controls { .system-foundryvtt-reve-de-dragon .competence-list .item-controls.hidden-controls {
display: none !important; display: none !important;
} }
.system-foundryvtt-reve-de-dragon .item-actions-controls a.actionItem i:is(.fas, .fa, .fa-solid, .fa-regular), .system-foundryvtt-reve-de-dragon .item-actions-controls,
.system-foundryvtt-reve-de-dragon .item-controls {
vertical-align: super;
}
.system-foundryvtt-reve-de-dragon .item-actions-controls img,
.system-foundryvtt-reve-de-dragon .item-controls img {
display: inline;
max-width: 1rem;
max-height: 1rem;
margin: 0 0.1rem;
border: none;
filter: invert(0.8);
}
.system-foundryvtt-reve-de-dragon .item-actions-controls i:is(.fas, .fa, .fa-solid, .fa-regular),
.system-foundryvtt-reve-de-dragon .item-controls i:is(.fas, .fa, .fa-solid, .fa-regular) { .system-foundryvtt-reve-de-dragon .item-controls i:is(.fas, .fa, .fa-solid, .fa-regular) {
font-size: 0.8em; font-size: 0.8em;
color: var(--color-controls-light); color: var(--color-controls-light);
} }
.system-foundryvtt-reve-de-dragon .item-actions-controls a.actionItem i:is(.fas, .fa, .fa-solid, .fa-regular):hover, .system-foundryvtt-reve-de-dragon .item-actions-controls img:hover,
.system-foundryvtt-reve-de-dragon .item-controls img:hover,
.system-foundryvtt-reve-de-dragon .item-actions-controls i:is(.fas, .far, .fa-solid, .fa-regular):hover,
.system-foundryvtt-reve-de-dragon .item-controls i:is(.fas, .far, .fa-solid, .fa-regular):hover { .system-foundryvtt-reve-de-dragon .item-controls i:is(.fas, .far, .fa-solid, .fa-regular):hover {
opacity: 0.6; opacity: 0.6;
} }
@@ -1463,38 +1504,38 @@ select,
} }
.system-foundryvtt-reve-de-dragon .rdd-roll-part { .system-foundryvtt-reve-de-dragon .rdd-roll-part {
align-items: center; align-items: center;
border-radius: 6px; border-radius: 0.5rem;
padding: 3px; padding: 3px;
background: var(--gradient-gold); background: var(--gradient-gold);
} }
.system-foundryvtt-reve-de-dragon .rdd-roll-sign { .system-foundryvtt-reve-de-dragon .rdd-roll-sign {
border-radius: 6px; border-radius: 0.5rem;
padding: 3px; padding: 3px;
background: var(--gradient-silver); background: var(--gradient-silver);
} }
.system-foundryvtt-reve-de-dragon .rdd-roll-norm { .system-foundryvtt-reve-de-dragon .rdd-roll-norm {
border-radius: 6px; border-radius: 0.5rem;
padding: 3px; padding: 3px;
background: var(--gradient-green); background: var(--gradient-green);
} }
.system-foundryvtt-reve-de-dragon .rdd-roll-notSign, .system-foundryvtt-reve-de-dragon .rdd-roll-notSign,
.system-foundryvtt-reve-de-dragon .rdd-roll-echec { .system-foundryvtt-reve-de-dragon .rdd-roll-echec {
border-radius: 6px; border-radius: 0.5rem;
padding: 3px; padding: 3px;
background: var(--gradient-red); background: var(--gradient-red);
} }
.system-foundryvtt-reve-de-dragon .rdd-roll-epart { .system-foundryvtt-reve-de-dragon .rdd-roll-epart {
border-radius: 6px; border-radius: 0.5rem;
padding: 3px; padding: 3px;
background: var(--gradient-violet); background: var(--gradient-violet);
} }
.system-foundryvtt-reve-de-dragon .rdd-roll-etotal { .system-foundryvtt-reve-de-dragon .rdd-roll-etotal {
border-radius: 6px; border-radius: 0.5rem;
padding: 3px; padding: 3px;
background: var(--gradient-purple-black); background: var(--gradient-purple-black);
} }
.system-foundryvtt-reve-de-dragon .rdd-diviseur { .system-foundryvtt-reve-de-dragon .rdd-diviseur {
border-radius: 6px; border-radius: 0.5rem;
padding: 3px; padding: 3px;
background: var(--gradient-red); background: var(--gradient-red);
} }
@@ -1521,12 +1562,8 @@ select,
font-size: 0.8rem; font-size: 0.8rem;
font-style: italic; font-style: italic;
color: rgba(82, 17, 131, 0.9); color: rgba(82, 17, 131, 0.9);
overflow: hidden; overflow-y: scroll;
} width: 100%;
.system-foundryvtt-reve-de-dragon .poesie-extrait:hover {
max-height: unset;
overflow: visible;
opacity: 1;
} }
.system-foundryvtt-reve-de-dragon .poesie-reference { .system-foundryvtt-reve-de-dragon .poesie-reference {
font-size: 0.7rem; font-size: 0.7rem;
@@ -1535,22 +1572,70 @@ select,
.system-foundryvtt-reve-de-dragon .type-compendium { .system-foundryvtt-reve-de-dragon .type-compendium {
font-size: 0.6rem; font-size: 0.6rem;
} }
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-header { .system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body,
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top; .system-foundryvtt-reve-de-dragon .application .window-content,
color: #ffffff; .system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar {
background: url(../assets/ui/bg_left.webp) no-repeat left top;
color: var(--rdd-color-text-primary);
} }
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-header :is( .system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body label,
input[type="text"], .system-foundryvtt-reve-de-dragon .application .window-content label,
input[type="number"], .system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar label,
input[type="password"], .system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body .hint,
input[type="datetime-local"], .system-foundryvtt-reve-de-dragon .application .window-content .hint,
input[type="date"], .system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar .hint,
input[type="time"]) { .system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body .permissions-list,
color: rgba(255, 255, 255, 0.75); .system-foundryvtt-reve-de-dragon .application .window-content .permissions-list,
background: rgba(255, 255, 255, 0.1); .system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar .permissions-list,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs,
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs button,
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs button,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs button,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs button .count,
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs button .count,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs button .count,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body button,
.system-foundryvtt-reve-de-dragon .application .window-content button,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar button {
color: var(--rdd-color-text-primary);
}
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body a,
.system-foundryvtt-reve-de-dragon .application .window-content a,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar a {
color: var(--color-dark-3);
}
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body a.filter.active,
.system-foundryvtt-reve-de-dragon .application .window-content a.filter.active,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar a.filter.active {
color: var(--color-dark-1);
}
.system-foundryvtt-reve-de-dragon .window-app .window-content {
background: url(../assets/ui/bg_left.webp) no-repeat left top;
color: var(--rdd-color-text-primary);
}
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header {
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
}
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header label,
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header .hint,
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header .permissions-list,
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header nav.tabs,
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header nav.tabs button,
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header nav.tabs button .count,
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header div,
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header button {
color: rgba(255, 255, 255, 0.9);
}
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header input {
color: rgba(255, 255, 255, 0.9);
border: 0 none; border: 0 none;
margin-bottom: 0.2rem; margin-bottom: 0.2rem;
} }
.system-foundryvtt-reve-de-dragon .window-app .window-content .sheet-header input[type="checkbox"] {
color: rgba(255, 255, 255, 0.75);
}
.system-foundryvtt-reve-de-dragon input[type="number"] { .system-foundryvtt-reve-de-dragon input[type="number"] {
text-align: right; text-align: right;
padding-right: 0.5rem; padding-right: 0.5rem;
@@ -1591,8 +1676,11 @@ select,
width: calc(100% - 2px); width: calc(100% - 2px);
height: var(--form-field-height); height: var(--form-field-height);
margin: 0; margin: 0;
color: var(--color-text-dark-primary); color: var(--rdd-color-text-primary);
border-radius: 3px; border-radius: 0.2rem;
}
.system-foundryvtt-reve-de-dragon form.app-personnage-aleatoire h2 {
min-width: 30rem;
} }
.system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.theme-astral { .system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.theme-astral {
width: 14rem; width: 14rem;
@@ -1614,8 +1702,9 @@ select,
height: 2rem; height: 2rem;
} }
.system-foundryvtt-reve-de-dragon .window-app .window-content, .system-foundryvtt-reve-de-dragon .window-app .window-content,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body { .system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body,
background: #f5f5f0 url(../assets/ui/bg_left.webp) no-repeat left top; .system-foundryvtt-reve-de-dragon .application .window-content {
background: url(../assets/ui/bg_left.webp) no-repeat left top;
} }
.system-foundryvtt-reve-de-dragon section.sheet-body { .system-foundryvtt-reve-de-dragon section.sheet-body {
padding: 0.25rem 0.5rem; padding: 0.25rem 0.5rem;
@@ -1643,7 +1732,7 @@ select,
background: hsla(280, 50%, 50%, 0.1); background: hsla(280, 50%, 50%, 0.1);
padding: 1px 4px; padding: 1px 4px;
border: 1px solid var(--color-border-dark-tertiary); border: 1px solid var(--color-border-dark-tertiary);
border-radius: 2px; border-radius: 0.2rem;
white-space: nowrap; white-space: nowrap;
word-break: break-all; word-break: break-all;
} }
@@ -1653,7 +1742,7 @@ select,
font-weight: 560; font-weight: 560;
padding: 0.1rem 0.3rem; padding: 0.1rem 0.3rem;
border: 1px solid var(--color-border-dark-tertiary); border: 1px solid var(--color-border-dark-tertiary);
border-radius: 0.25rem; border-radius: 0.2rem;
white-space: nowrap; white-space: nowrap;
word-break: break-all; word-break: break-all;
display: ruby; display: ruby;
@@ -1773,7 +1862,7 @@ select,
.system-foundryvtt-reve-de-dragon .xp-level-up { .system-foundryvtt-reve-de-dragon .xp-level-up {
margin: 0.1rem; margin: 0.1rem;
box-shadow: inset 0px 0px 1px #00000096; box-shadow: inset 0px 0px 1px #00000096;
border-radius: 0.25rem; border-radius: 0.2rem;
padding: 0.1rem; padding: 0.1rem;
flex: 1 1 5rem; flex: 1 1 5rem;
background: var(--gradient-gold) !important; background: var(--gradient-gold) !important;
@@ -1804,7 +1893,7 @@ select,
.system-foundryvtt-reve-de-dragon .list-item { .system-foundryvtt-reve-de-dragon .list-item {
margin: 0.1rem; margin: 0.1rem;
box-shadow: inset 0px 0px 1px #00000096; box-shadow: inset 0px 0px 1px #00000096;
border-radius: 0.25rem; border-radius: 0.2rem;
padding: 0.1rem; padding: 0.1rem;
flex: 1 1 1.5rem; flex: 1 1 1.5rem;
display: flex; display: flex;
@@ -2117,6 +2206,9 @@ select,
font-size: 0.7rem; font-size: 0.7rem;
flex-grow: 3; flex-grow: 3;
} }
.system-foundryvtt-reve-de-dragon .chat-message header.message-header .message-metadata {
flex-grow: 3.5;
}
.system-foundryvtt-reve-de-dragon .chat-message hr { .system-foundryvtt-reve-de-dragon .chat-message hr {
margin: 0.2rem 0; margin: 0.2rem 0;
} }
@@ -2287,7 +2379,7 @@ select,
pointer-events: all; pointer-events: all;
} }
.system-foundryvtt-reve-de-dragon div.horloge-roue div.horloge-cercle { .system-foundryvtt-reve-de-dragon div.horloge-roue div.horloge-cercle {
background: hsl(60, 20%, 95%) url(../assets/ui/bg_left.webp) no-repeat left top; background: hsla(60, 20%, 90%, 0.8);
top: 2%; top: 2%;
left: 2%; left: 2%;
width: 96%; width: 96%;
@@ -2337,7 +2429,7 @@ select,
font-size: 0.8rem; font-size: 0.8rem;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
border-radius: 0.3rem; border-radius: 0.2rem;
} }
.system-foundryvtt-reve-de-dragon div.horloge-roue div img { .system-foundryvtt-reve-de-dragon div.horloge-roue div img {
border: none; border: none;
@@ -2664,13 +2756,20 @@ select,
.system-foundryvtt-reve-de-dragon :is(.tooltip, .tooltip-overflow) .ttt-ajustements { .system-foundryvtt-reve-de-dragon :is(.tooltip, .tooltip-overflow) .ttt-ajustements {
width: 10rem; width: 10rem;
background: var(--background-tooltip); background: var(--background-tooltip);
border-radius: 6px; border-radius: 0.5rem;
font-size: 0.9rem; font-size: 0.9rem;
padding: 3px 0; padding: 3px 0;
} }
.system-foundryvtt-reve-de-dragon :is(.tooltip, .tooltip-overflow) .ttt-ajustements div:nth-child(odd) { .system-foundryvtt-reve-de-dragon :is(.tooltip, .tooltip-overflow) .ttt-ajustements div:nth-child(odd) {
background: var(--background-tooltip-alt); background: var(--background-tooltip-alt);
} }
.system-foundryvtt-reve-de-dragon :is(.tooltip, .tooltip-overflow) .ttt-ajustements div img {
display: inline;
margin: 0;
max-width: 1rem;
max-height: 1rem;
filter: invert(0.8);
}
.system-foundryvtt-reve-de-dragon aside#tooltip { .system-foundryvtt-reve-de-dragon aside#tooltip {
max-width: 15rem; max-width: 15rem;
background: var(--background-tooltip); background: var(--background-tooltip);
@@ -2732,11 +2831,9 @@ select,
} }
.system-foundryvtt-reve-de-dragon .chat-card-button:hover { .system-foundryvtt-reve-de-dragon .chat-card-button:hover {
background: var(--background-custom-button-hover); background: var(--background-custom-button-hover);
background-color: red;
} }
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed:hover { .system-foundryvtt-reve-de-dragon .chat-card-button-pushed:hover {
background: var(--background-custom-button-hover); background: var(--background-custom-button-hover);
background-color: red;
} }
.system-foundryvtt-reve-de-dragon .chat-card-button:active, .system-foundryvtt-reve-de-dragon .chat-card-button:active,
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed:active { .system-foundryvtt-reve-de-dragon .chat-card-button-pushed:active {

1
icons/cuisine/gibier.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.8 KiB

1
icons/cuisine/herbe.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 5.6 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.6 KiB

1
icons/cuisine/plante.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.8 KiB

1
icons/cuisine/ragout.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.2 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -1,6 +1,6 @@
{ {
"TYPES": { "TYPES": {
"Actor": { "Actor": {
"personnage": "Personnage", "personnage": "Personnage",
"creature": "Créature", "creature": "Créature",
"entite": "Entité de cauchemar", "entite": "Entité de cauchemar",
@@ -67,6 +67,7 @@
"StatusComma": "Comma", "StatusComma": "Comma",
"StatusDead": "Mort", "StatusDead": "Mort",
"StatusDemiReve": "Demi-rêve", "StatusDemiReve": "Demi-rêve",
"StatusSurEnc": "Sur-encombrement",
"StatusForceWeak": "Force insuffisante" "StatusForceWeak": "Force insuffisante"
} }
} }

View File

@@ -12,7 +12,10 @@
background: rgba(0,0,0,0.75); background: rgba(0,0,0,0.75);
} }
.application .window-content, .application .window-content {
margin: 0;
padding: 0.2rem;
}
.window-app.sheet .window-content { .window-app.sheet .window-content {
margin: 0.2rem; margin: 0.2rem;
padding: 0; padding: 0;
@@ -115,7 +118,7 @@
max-width: 1.4rem; max-width: 1.4rem;
max-height: 1.4rem; max-height: 1.4rem;
border: 1px; border: 1px;
background: center / contain no-repeat url('../../assets/ui/icone_parchement_vierge.webp'); background: center / contain no-repeat url('../../icons/templates/icone_parchement_vierge.webp');
} }
.sheet-header .header-compteurs { .sheet-header .header-compteurs {
@@ -200,6 +203,9 @@
i.moral-radio-checkmark-off:hover, i.moral-radio-checkmark-off:hover,
a:hover { a:hover {
text-shadow: 1px 0px 0px #ff6600; text-shadow: 1px 0px 0px #ff6600;
img {
filter: drop-shadow(1px 0px 0px #ff6600);
}
} }
.rollable:hover, .rollable:focus { .rollable:hover, .rollable:focus {
@@ -650,9 +656,15 @@
margin: 0.1rem 0; margin: 0.1rem 0;
align-items: center; align-items: center;
} }
.prosemirror {
menu{
background-color: var(--color-background-chat-message);
}
}
.app.sheet .editor.prosemirror { .app.sheet .editor.prosemirror {
height: fit-content; height: fit-content;
min-height: 5rem; min-height: 5rem;
} }
.app.sheet .editor.prosemirror .editor-container { .app.sheet .editor.prosemirror .editor-container {
min-height: 5rem; min-height: 5rem;
@@ -741,11 +753,11 @@
.foundryvtt-reve-de-dragon .item-list .item img { .foundryvtt-reve-de-dragon .item-list .item img {
display: inline; display: inline;
} }
.foundryvtt-reve-de-dragon .item-list .item-name { .foundryvtt-reve-de-dragon .item-list .item-name {
margin: 0; margin: 0;
} }
.competence-list .item-controls, .competence-list .item-controls,
.competence-list .item-actions-controls { .competence-list .item-actions-controls {
display: contents !important; display: contents !important;
@@ -754,15 +766,30 @@
.competence-list .item-controls.hidden-controls { .competence-list .item-controls.hidden-controls {
display: none !important; display: none !important;
} }
.item-actions-controls,
.item-controls {
vertical-align: super;
// a {
// }
.item-actions-controls a.actionItem i:is(.fas, .fa, .fa-solid, .fa-regular), img {
.item-controls i:is(.fas, .fa, .fa-solid, .fa-regular) { display: inline;
font-size: 0.8em; max-width: 1rem;
color: var(--color-controls-light); max-height: 1rem;
} margin: 0 0.1rem;
.item-actions-controls a.actionItem i:is(.fas, .fa, .fa-solid, .fa-regular):hover, border: none;
.item-controls i:is(.fas, .far, .fa-solid, .fa-regular):hover { filter: invert(0.8);
opacity: 0.6; }
i:is(.fas, .fa, .fa-solid, .fa-regular) {
font-size: 0.8em;
color: var(--color-controls-light);
}
img:hover,
i:is(.fas, .far, .fa-solid, .fa-regular):hover {
opacity: 0.6;
}
} }
.rdd-roll-dialog .description-sort { .rdd-roll-dialog .description-sort {
@@ -777,31 +804,31 @@
} }
.rdd-roll-part { .rdd-roll-part {
align-items: center; align-items: center;
border-radius: 6px; padding: 3px; border-radius: 0.5rem; padding: 3px;
background: var(--gradient-gold); background: var(--gradient-gold);
} }
.rdd-roll-sign{ .rdd-roll-sign{
border-radius: 6px; padding: 3px; border-radius: 0.5rem; padding: 3px;
background: var(--gradient-silver); background: var(--gradient-silver);
} }
.rdd-roll-norm{ .rdd-roll-norm{
border-radius: 6px; padding: 3px; border-radius: 0.5rem; padding: 3px;
background: var(--gradient-green); background: var(--gradient-green);
} }
.rdd-roll-notSign, .rdd-roll-echec{ .rdd-roll-notSign, .rdd-roll-echec{
border-radius: 6px; padding: 3px; border-radius: 0.5rem; padding: 3px;
background: var(--gradient-red); background: var(--gradient-red);
} }
.rdd-roll-epart{ .rdd-roll-epart{
border-radius: 6px; padding: 3px; border-radius: 0.5rem; padding: 3px;
background: var(--gradient-violet); background: var(--gradient-violet);
} }
.rdd-roll-etotal{ .rdd-roll-etotal{
border-radius: 6px; padding: 3px; border-radius: 0.5rem; padding: 3px;
background: var(--gradient-purple-black); background: var(--gradient-purple-black);
} }
.rdd-diviseur{ .rdd-diviseur{
border-radius: 6px; padding: 3px; border-radius: 0.5rem; padding: 3px;
background: var(--gradient-red); background: var(--gradient-red);
} }
@@ -832,15 +859,10 @@
font-size: 0.8rem; font-size: 0.8rem;
font-style: italic; font-style: italic;
color: rgba(82, 17, 131, 0.9); color: rgba(82, 17, 131, 0.9);
overflow: hidden; overflow-y: scroll;
width: 100%;
} }
.poesie-extrait:hover {
max-height: unset;
overflow: visible;
opacity: 1;
}
.poesie-reference { .poesie-reference {
font-size: 0.7rem; font-size: 0.7rem;
text-align: right; text-align: right;
@@ -849,26 +871,60 @@
.type-compendium { .type-compendium {
font-size: 0.6rem; font-size: 0.6rem;
} }
.window-app.sheet .window-content .sheet-body,
.application .window-content,
.journal-entry .journal-sidebar {
background: url(../assets/ui/bg_left.webp) no-repeat left top;
color: var(--rdd-color-text-primary);
label ,
.hint ,
.permissions-list ,
nav.tabs,
nav.tabs button,
nav.tabs button .count,
button {
color: var(--rdd-color-text-primary);
}
a {
color: var(--color-dark-3);
}
a.filter.active {
color: var(--color-dark-1);
}
}
/* ======================================== */ /* ======================================== */
/* Sheet */ /* Sheet */
.window-app.sheet .window-content .sheet-header{ .window-app .window-content{
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top; background: url(../assets/ui/bg_left.webp) no-repeat left top;
color: rgba(255, 255, 255, 1); color: var(--rdd-color-text-primary);
}
.sheet-header {
background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
label ,
.hint ,
.permissions-list ,
nav.tabs,
nav.tabs button,
nav.tabs button .count,
div,
button {
color: rgba(255, 255, 255, 0.9);
}
input {
//color: rgba(255, 255, 255, 0);
color: rgba(255, 255, 255, 0.9);
border: 0 none;
margin-bottom: 0.2rem;
}
input[type="checkbox"] {
// background-color: hsla(268, 41%, 56%, 0.9);
color: rgba(255, 255, 255, 0.75);
}
}
}
.window-app.sheet .window-content .sheet-header :is(
input[type="text"],
input[type="number"],
input[type="password"],
input[type="datetime-local"],
input[type="date"],
input[type="time"]) {
color: rgba(255, 255, 255, 0.75);
background: rgba(255, 255, 255, 0.1);
border: 0 none;
margin-bottom: 0.2rem;
}
input[type="number"] { input[type="number"] {
text-align: right; text-align: right;
@@ -912,8 +968,13 @@
width: calc(100% - 2px); width: calc(100% - 2px);
height: var(--form-field-height); height: var(--form-field-height);
margin: 0; margin: 0;
color: var(--color-text-dark-primary); color: var(--rdd-color-text-primary);
border-radius: 3px; border-radius: 0.2rem;
}
form.app-personnage-aleatoire {
h2 {
min-width: 30rem,
}
} }
.app-calendar-astrologie{ .app-calendar-astrologie{
div.theme-astral{ div.theme-astral{
@@ -937,8 +998,10 @@
} }
} }
.window-app .window-content, .window-app.sheet .window-content .sheet-body{ .window-app .window-content,
background: rgb(245,245,240) url(../assets/ui/bg_left.webp) no-repeat left top; .window-app.sheet .window-content .sheet-body,
.application .window-content {
background: url(../assets/ui/bg_left.webp) no-repeat left top;
} }
section.sheet-body { section.sheet-body {
@@ -970,7 +1033,7 @@
background: hsla(280, 50%, 50%, 0.1); background: hsla(280, 50%, 50%, 0.1);
padding: 1px 4px; padding: 1px 4px;
border: 1px solid var(--color-border-dark-tertiary); border: 1px solid var(--color-border-dark-tertiary);
border-radius: 2px; border-radius: 0.2rem;
white-space: nowrap; white-space: nowrap;
word-break: break-all; word-break: break-all;
} }
@@ -981,7 +1044,7 @@
font-weight: 560; font-weight: 560;
padding: 0.1rem 0.3rem; padding: 0.1rem 0.3rem;
border: 1px solid var(--color-border-dark-tertiary); border: 1px solid var(--color-border-dark-tertiary);
border-radius: 0.25rem; border-radius: 0.2rem;
white-space: nowrap; white-space: nowrap;
word-break: break-all; word-break: break-all;
display: ruby; display: ruby;
@@ -1111,7 +1174,7 @@
.xp-level-up { .xp-level-up {
margin: 0.1rem; margin: 0.1rem;
box-shadow: inset 0px 0px 1px #00000096; box-shadow: inset 0px 0px 1px #00000096;
border-radius: 0.25rem; border-radius: 0.2rem;
padding: 0.1rem; padding: 0.1rem;
flex: 1 1 5rem; flex: 1 1 5rem;
background: var(--gradient-gold) !important; background: var(--gradient-gold) !important;
@@ -1142,7 +1205,7 @@
.list-item { .list-item {
margin: 0.1rem; margin: 0.1rem;
box-shadow: inset 0px 0px 1px #00000096; box-shadow: inset 0px 0px 1px #00000096;
border-radius: 0.25rem; border-radius: 0.2rem;
padding: 0.1rem; padding: 0.1rem;
flex: 1 1 1.5rem; flex: 1 1 1.5rem;
display: flex; display: flex;
@@ -1483,10 +1546,15 @@
.message-content { .message-content {
text-align: justify; text-align: justify;
} }
header.message-header .heure-rdd { header.message-header{
font-size: 0.7rem; .heure-rdd {
flex-grow: 3; font-size: 0.7rem;
} flex-grow: 3;
}
.message-metadata {
flex-grow: 3.5;
}
}
hr { hr {
margin: 0.2rem 0; margin: 0.2rem 0;
} }
@@ -1654,7 +1722,7 @@
} }
div.horloge-roue div.horloge-cercle { div.horloge-roue div.horloge-cercle {
background: hsl(60, 20%, 95%) url(../assets/ui/bg_left.webp) no-repeat left top; background: hsla(60, 20%, 90%, 0.8);
top: 2%; left: 2%; width: 96%; height: 96%; border-radius: 50%; top: 2%; left: 2%; width: 96%; height: 96%; border-radius: 50%;
} }
@@ -1685,7 +1753,7 @@
font-size: 0.8rem; font-size: 0.8rem;
text-align: center; text-align: center;
vertical-align: middle; vertical-align: middle;
border-radius: 0.3rem; border-radius: 0.2rem;
} }
div.horloge-roue div img { div.horloge-roue div img {
@@ -1921,12 +1989,19 @@
.ttt-ajustements { .ttt-ajustements {
width: 10rem; width: 10rem;
background: var(--background-tooltip); background: var(--background-tooltip);
border-radius: 6px; border-radius: 0.5rem;
font-size: 0.9rem; font-size: 0.9rem;
padding: 3px 0; padding: 3px 0;
div:nth-child(odd) { div:nth-child(odd) {
background: var(--background-tooltip-alt); background: var(--background-tooltip-alt);
} }
div img {
display: inline;
margin: 0;
max-width: 1rem;
max-height: 1rem;
filter: invert(0.8);
}
} }
} }
@@ -1998,12 +2073,10 @@
.chat-card-button:hover { .chat-card-button:hover {
background: var(--background-custom-button-hover); background: var(--background-custom-button-hover);
background-color: red;
} }
.chat-card-button-pushed:hover { .chat-card-button-pushed:hover {
background: var(--background-custom-button-hover); background: var(--background-custom-button-hover);
background-color: red;
} }
.chat-card-button:active, .chat-card-button-pushed:active { .chat-card-button:active, .chat-card-button-pushed:active {

View File

@@ -37,6 +37,9 @@
text-align: justify; text-align: justify;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
div {
display: block;
}
} }
div.chat-actions { div.chat-actions {
grid-area: actions; grid-area: actions;

View File

@@ -90,7 +90,7 @@
flex-direction: row; flex-direction: row;
margin: 0.1rem 0; margin: 0.1rem 0;
.warning { .warning {
border-radius: 6px; border-radius: 0.5rem;
background: var(--gradient-warning); background: var(--gradient-warning);
} }
} }
@@ -121,6 +121,7 @@
div.poesie-extrait{ div.poesie-extrait{
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: normal;
} }
span.status-surprise{ span.status-surprise{
display: flex; display: flex;
@@ -141,8 +142,13 @@
display: flow; display: flow;
width: 2.5rem; width: 2.5rem;
text-align: right; text-align: right;
margin: 0 0.2rem 0 0.5rem; margin: 0 0.2rem;
padding: 0 0.2rem; padding: 0 0.2rem;
border: 1px solid ;
border-radius: 0.2rem ;
background: hsla(0, 0%, 0%, 0.2);
height: 1.5rem;
background: hsla(0, 0%, 0%, 0.2);
} }
roll-action { roll-action {
@@ -205,28 +211,32 @@
} }
roll-carac select[name="select-carac"] { roll-carac select[name="select-carac"] {
max-width: 6rem; min-width: 6.5rem;
max-width: 8rem;
} }
roll-comp select[name="select-comp"] { roll-comp select[name="select-comp"] {
min-width: 8rem; min-width: 8rem;
max-width: 11rem; max-width: 10rem;
margin-left: 1rem; margin-left: 1.5rem;
} }
roll-conditions roll-section[name="coeur"] select[name="coeur"] { roll-conditions roll-section[name="coeur"] select[name="coeur"] {
max-width: 4rem; max-width: 4rem;
} }
roll-conditions roll-section[name="tricher"] img { roll-conditions roll-section img {
/* image de d100 */ max-width: 1rem;
max-width: 2.5rem; max-height: 1rem;
max-height: 2.5rem;
gap: 0; gap: 0;
margin: 0; margin: 0;
padding: 0; padding: 0;
filter: invert(0.8); filter: invert(0.8);
} }
roll-conditions roll-section[name="tricher"] img {
/* image de d100 */
max-width: 2.5rem;
max-height: 2.5rem;
}
roll-buttons { roll-buttons {
display: flex; display: flex;

View File

@@ -8,7 +8,7 @@
min-height: 100px; // Hauteur minimale pour la description min-height: 100px; // Hauteur minimale pour la description
background: var(--rdd-bg-input-alt); // Une couleur de fond alternative background: var(--rdd-bg-input-alt); // Une couleur de fond alternative
padding: 5px; padding: 5px;
border-radius: 3px; border-radius: 0.2rem;
color: var(--rdd-color-text-primary); color: var(--rdd-color-text-primary);
} }
@@ -28,7 +28,7 @@
background: var(--fieldset-background); background: var(--fieldset-background);
color: var(--rdd-color-text-primary); color: var(--rdd-color-text-primary);
margin-bottom: 4px; margin-bottom: 4px;
border-radius: 6px; border-radius: 0.5rem;
border-color: var(--rdd-color-text-primary); border-color: var(--rdd-color-text-primary);
border-width: 2px; border-width: 2px;
} }
@@ -64,7 +64,7 @@
--rdd-color-text-input --rdd-color-text-input
); // Assurez-vous que cette variable existe ); // Assurez-vous que cette variable existe
padding: 2px 2px; // Augmentation du padding vertical padding: 2px 2px; // Augmentation du padding vertical
border-radius: 3px; border-radius: 0.2rem;
} }
input[type="checkbox"] { input[type="checkbox"] {

View File

@@ -342,7 +342,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async createEmptyTache() { async createEmptyTache() {
await this.actor.createItem('tache', 'Nouvelle tache'); await this.actor.createItem(ITEM_TYPES.tache, 'Nouvelle tache')
} }
_getActionCombat(event) { _getActionCombat(event) {
@@ -375,14 +375,6 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
return position; return position;
} }
/* -------------------------------------------- */
/** @override */
_updateObject(event, formData) {
// Update the Actor
return this.actor.update(formData);
}
async splitItem(item) { async splitItem(item) {
const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split)); const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split));
dialog.render(true); dialog.render(true);

View File

@@ -47,9 +47,12 @@ import { RdDRollResult } from "./rdd-roll-result.js";
import { RdDInitiative } from "./initiative.mjs"; import { RdDInitiative } from "./initiative.mjs";
import RollDialog from "./roll/roll-dialog.mjs"; import RollDialog from "./roll/roll-dialog.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2, ROLL_DIALOG_V2_TEST } from "./settings/options-avancees.js"; import { OptionsAvancees, ROLL_DIALOG_V2, ROLL_DIALOG_V2_TEST } from "./settings/options-avancees.js";
import { ROLL_TYPE_MEDITATION } from "./roll/roll-constants.mjs"; import { ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_SORT } from "./roll/roll-constants.mjs";
import { PART_TACHE } from "./roll/roll-part-tache.mjs"; import { PART_TACHE } from "./roll/roll-part-tache.mjs";
import { PART_COMP } from "./roll/roll-part-comp.mjs"; import { PART_COMP } from "./roll/roll-part-comp.mjs";
import { PART_OEUVRE } from "./roll/roll-part-oeuvre.mjs";
import { PART_CUISINE } from "./roll/roll-part-cuisine.mjs";
import { PART_SORT } from "./roll/roll-part-sort.mjs";
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre'] export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
@@ -163,10 +166,10 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
getDemiReve() { return this.system.reve.tmrpos.coord } getDemiReve() { return this.system.reve.tmrpos.coord }
getDraconicList() { return this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == 'draconic') } getDraconics() { return this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == 'draconic') }
getBestDraconic() { return foundry.utils.duplicate([...this.getDraconicList(), PAS_DE_DRACONIC].sort(Misc.descending(it => it.system.niveau)).find(it => true)) } getBestDraconic() { return foundry.utils.duplicate([...this.getDraconics(), PAS_DE_DRACONIC].sort(Misc.descending(it => it.system.niveau)).find(it => true)) }
getDraconicOuPossession() { getDraconicOuPossession() {
return [...this.getDraconicList().filter(it => it.system.niveau >= 0), POSSESSION_SANS_DRACONIC] return [...this.getDraconics().filter(it => it.system.niveau >= 0), POSSESSION_SANS_DRACONIC]
.sort(Misc.descending(it => it.system.niveau)) .sort(Misc.descending(it => it.system.niveau))
.find(it => true) .find(it => true)
} }
@@ -182,13 +185,13 @@ export class RdDActor extends RdDBaseActorSang {
const actions = [] const actions = []
const uniques = [] const uniques = []
const addAttaque = (arme, main = undefined, action = 'attaque') => { const addAttaque = (arme, main = undefined) => {
const dommagesArme = RdDItemArme.valeurMain(arme.system.dommages, main) const dommages = RdDItemArme.valeurMain(arme.system.dommages, main)
const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main) const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
const ecaillesEfficacite = arme.system.magique ? arme.system.ecaille_efficacite : 0; const ecaillesEfficacite = arme.system.magique ? arme.system.ecaille_efficacite : 0;
const comp = this.getCompetence(RdDActor.$getCompetenceAction(arme, main)) const comp = this.getCompetence(arme.getCompetenceAction(main))
const unique = [comp.id, arme.name, dommagesArme, forceRequise, ecaillesEfficacite].join('|'); const unique = [comp.id, arme.name, dommages, forceRequise, ecaillesEfficacite].join('|');
if (uniques.includes(unique)) { if (uniques.includes(unique)) {
return return
} }
@@ -209,24 +212,20 @@ export class RdDActor extends RdDBaseActorSang {
main: main, main: main,
carac: { key: caracCode, value: caracValue }, carac: { key: caracCode, value: caracValue },
equipe: arme.system.equipe, equipe: arme.system.equipe,
dommagesArme: dommagesArme, dommages: dommages,
forceRequise: forceRequise, forceRequise: forceRequise,
initiative: RdDInitiative.getRollInitiative(caracValue, niveau, ajustement) initiative: RdDInitiative.getRollInitiative(caracValue, niveau, ajustement)
}) })
} }
addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS)
this.itemTypes[ITEM_TYPES.arme] this.itemTypes[ITEM_TYPES.arme]
.filter(it => it.isAttaque()) .filter(it => it.isAttaque())
.sort(Misc.ascending(it => it.name)) .sort(Misc.ascending(it => it.name))
.forEach(arme => { .forEach(arme => arme.getTypeAttaques().forEach(t => addAttaque(arme, t)))
if (arme.system.unemain && arme.system.competence && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.UNE_MAIN) }
if (arme.system.deuxmains && arme.system.competence && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.DEUX_MAINS) }
if (arme.system.lancer && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.LANCER) }
if (arme.system.tir) { addAttaque(arme, ATTAQUE_TYPE.TIR) }
})
addAttaque(RdDItemArme.pugilat(this), ATTAQUE_TYPE.CORPS_A_CORPS) addAttaque(RdDItemArme.pugilat(this), ATTAQUE_TYPE.CORPS_A_CORPS)
addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS, 'empoignade')
return actions return actions
} }
@@ -242,16 +241,6 @@ export class RdDActor extends RdDBaseActorSang {
} }
} }
static $getCompetenceAction(arme, main) {
switch (main) {
case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains()
case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains()
case ATTAQUE_TYPE.LANCER: return arme.system.lancer
case ATTAQUE_TYPE.TIR: return arme.system.tir
default: return arme.system.competence
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async $perteReveEnchantementsChateauDormants() { async $perteReveEnchantementsChateauDormants() {
const toUpdate = this.items.filter(it => [ITEM_TYPES.potion, ITEM_TYPES.gemme].includes(it.type)) const toUpdate = this.items.filter(it => [ITEM_TYPES.potion, ITEM_TYPES.gemme].includes(it.type))
@@ -703,11 +692,12 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async combattreReveDeDragon(force) { async combattreReveDeDragon(force) {
const rencontre = await game.system.rdd.rencontresTMR.getReveDeDragon(force);
let rollData = { let rollData = {
actor: this, actor: this,
competence: this.getDraconicOuPossession(), competence: this.getDraconicOuPossession(),
canClose: false, canClose: false,
rencontre: await game.system.rdd.rencontresTMR.getReveDeDragon(force), rencontre: rencontre,
tmr: true, tmr: true,
use: { libre: false, conditions: false }, use: { libre: false, conditions: false },
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.getReveActuel() } } forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.getReveActuel() } }
@@ -738,12 +728,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async sortMisEnReserve(sort, draconic, coord, ptreve) { async sortMisEnReserve(sort, draconic, coord, ptreve) {
await this.createEmbeddedDocuments("Item", [{ await this.createEmbeddedDocuments("Item", [RdDItemSort.prepareSortEnReserve(sort, draconic, ptreve, coord)],
type: ITEM_TYPES.sortreserve,
name: sort.name,
img: sort.img,
system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' }
}],
{ renderSheet: false }); { renderSheet: false });
this.tmrApp.updateTokens(); this.tmrApp.updateTokens();
} }
@@ -757,20 +742,18 @@ export class RdDActor extends RdDBaseActorSang {
let updates = {}; let updates = {};
if (caracName == LIST_CARAC_PERSONNAGE.reve.code) { if (caracName == LIST_CARAC_PERSONNAGE.reve.code) {
if (to > Misc.toInt(this.system.reve.seuil.value)) { if (to > Misc.toInt(this.system.reve.seuil.value)) {
updates[`system.reve.seuil.value`] = to; // SFA : Direct and packed changes updates[`system.reve.seuil.value`] = to
//this.setPointsDeSeuil(to);
} }
} }
if (caracName == LIST_CARAC_PERSONNAGE.chance.code) { if (caracName == LIST_CARAC_PERSONNAGE.chance.code) {
if (to > Misc.toInt(this.system.compteurs.chance.value)) { if (to > Misc.toInt(this.system.compteurs.chance.value)) {
updates[`system.compteurs.chance.value`] = to; // SFA : Direct and packed changes updates[`system.compteurs.chance.value`] = to
//this.setPointsDeChance(to);
} }
} }
let selectedCarac = this.findCaracByName(caracName); let selectedCarac = this.findCaracByName(caracName);
const from = selectedCarac.value const from = selectedCarac.value
updates[`system.carac.${caracName}.value`] = to; updates[`system.carac.${caracName}.value`] = to;
await this.update(updates); await this.update(updates, { noHook: true });
await ExperienceLog.add(this, XP_TOPIC.CARAC, from, to, caracName); await ExperienceLog.add(this, XP_TOPIC.CARAC, from, to, caracName);
} }
@@ -1688,7 +1671,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
computeDraconicAndSortIndex(sortList) { computeDraconicAndSortIndex(sortList) {
let draconicList = this.getDraconicList(); let draconicList = this.getDraconics();
for (let sort of sortList) { for (let sort of sortList) {
let draconicsSort = RdDItemSort.getDraconicsSort(draconicList, sort).map(it => it.name); let draconicsSort = RdDItemSort.getDraconicsSort(draconicList, sort).map(it => it.name);
for (let index = 0; index < draconicList.length && sort.system.listIndex == undefined; index++) { for (let index = 0; index < draconicList.length && sort.system.listIndex == undefined; index++) {
@@ -1709,15 +1692,18 @@ export class RdDActor extends RdDBaseActorSang {
ui.notifications.error("Une queue ou un souffle vous empèche de lancer de sort!") ui.notifications.error("Une queue ou un souffle vous empèche de lancer de sort!")
return return
} }
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
return await this.rollUnSortV2();
}
// 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 = foundry.utils.duplicate(this.itemTypes[ITEM_TYPES.sort].filter(it => RdDItemSort.isSortOnCoord(it, coord))) let sorts = foundry.utils.duplicate(this.itemTypes[ITEM_TYPES.sort].filter(it => RdDItemSort.isSortOnCoord(it, 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 = foundry.utils.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',
@@ -1740,6 +1726,27 @@ export class RdDActor extends RdDBaseActorSang {
this.tmrApp?.setTMRPendingAction(dialog); this.tmrApp?.setTMRPendingAction(dialog);
} }
async rollUnSortV2() {
const rollData = {
ids: { actorId: this.id },
type: { allowed: [ROLL_TYPE_SORT], current: ROLL_TYPE_SORT }
};
const dialog = await RollDialog.create(rollData, {
callbacks: [roll => {
this.tmrApp?.restoreTMRAfterAction();
if (roll.closeTMR) {
this.tmrApp?.close();
this.tmrApp = undefined;
}
}],
onRollDone: RollDialog.onRollDoneClose,
onClose: () => {
this.tmrApp?.restoreTMRAfterAction();
}
});
this.tmrApp?.setTMRPendingAction(dialog);
}
/* -------------------------------------------- */ /* -------------------------------------------- */
isMauvaiseRencontre() { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective' isMauvaiseRencontre() { // Gestion queue/souffle 'Mauvaise Rencontre en Perpective'
let addMsg = ""; let addMsg = "";
@@ -1811,11 +1818,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
else { else {
console.log('lancement de sort', rollData.selectedSort) console.log('lancement de sort', rollData.selectedSort)
const precedents = rollData.selectedSort.system.lancements ?? [] const lancements = RdDItemSort.prepareSortAddLancement(rollData.selectedSort, rollData.selectedSort.system.ptreve_reel)
const lancements = [...precedents, {
timestamp: game.system.rdd.calendrier.getTimestamp(),
reve: rollData.selectedSort.system.ptreve_reel
}]
await this.updateEmbeddedDocuments('Item', await this.updateEmbeddedDocuments('Item',
[{ _id: rollData.selectedSort._id, 'system.lancements': lancements }] [{ _id: rollData.selectedSort._id, 'system.lancements': lancements }]
) )
@@ -1933,12 +1936,13 @@ export class RdDActor extends RdDBaseActorSang {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { allowed: [PART_COMP], current: PART_COMP }, type: { allowed: [PART_COMP], current: PART_COMP },
selected: { selected: {
carac: {key: caracName }, carac: { key: caracName },
comp: { key: compName, forced: options.forced } comp: { key: compName, forced: options.forced },
diff: { value: diff ?? 0 }
} }
} }
RollDialog.create(rollData, options) RollDialog.create(rollData, foundry.utils.mergeObject(options, { onRollDone: RollDialog.onRollDoneClose }))
return return
} }
@@ -1970,7 +1974,7 @@ export class RdDActor extends RdDBaseActorSang {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
selected: { tache: { key: tache.id, forced: options.forced} }, selected: { tache: { key: tache.id, forced: options.forced } },
type: { allowed: [PART_TACHE], current: PART_TACHE } type: { allowed: [PART_TACHE], current: PART_TACHE }
} }
RollDialog.create(rollData, options) RollDialog.create(rollData, options)
@@ -2025,9 +2029,19 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollJeu(id) { async rollJeu(id) {
const oeuvre = this.getJeu(id); const jeu = this.getJeu(id);
const listCarac = oeuvre.system.caraccomp.toLowerCase().split(/[.,:\/-]/).map(it => it.trim()); if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
selected: { jeu: { key: jeu.id } },
type: { allowed: [ROLL_TYPE_JEU], current: ROLL_TYPE_JEU }
}
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return
}
const listCarac = jeu.system.caraccomp.toLowerCase().split(/[.,:\/-]/).map(it => it.trim());
const carac = listCarac.length > 0 ? listCarac[0] : 'chance' const carac = listCarac.length > 0 ? listCarac[0] : 'chance'
const artData = { const artData = {
art: 'jeu', verbe: 'Jeu', art: 'jeu', verbe: 'Jeu',
@@ -2037,8 +2051,8 @@ export class RdDActor extends RdDBaseActorSang {
}; };
listCarac.forEach(c => artData.forceCarac[c] = this.system.carac[c]); listCarac.forEach(c => artData.forceCarac[c] = this.system.carac[c]);
artData.competence.system.niveauReel = artData.competence.system.niveau; artData.competence.system.niveauReel = artData.competence.system.niveau;
artData.competence.system.niveau = Math.max(artData.competence.system.niveau, oeuvre.system.base); artData.competence.system.niveau = Math.max(artData.competence.system.niveau, jeu.system.base);
await this._rollArtV1(artData, carac, oeuvre); await this._rollArtV1(artData, carac, jeu);
} }
@@ -2052,7 +2066,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { meditation: { key: id } }, selected: { meditation: { key: id } },
type: { allowed: [ROLL_TYPE_MEDITATION], current: ROLL_TYPE_MEDITATION } type: { allowed: [ROLL_TYPE_MEDITATION], current: ROLL_TYPE_MEDITATION }
} }
await RollDialog.create(rollData) await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return return
} }
@@ -2095,7 +2109,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
_getSignesDraconiques(coord) { _getSignesDraconiques(coord) {
const type = TMRUtility.getTMRType(coord); const type = TMRUtility.getTMRType(coord);
return this.itemTypes["signedraconique"].filter(it => it.system.typesTMR.includes(type)); return this.itemTypes[ITEM_TYPES.signedraconique].filter(it => it.system.typesTMR.includes(type));
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -2107,18 +2121,19 @@ export class RdDActor extends RdDBaseActorSang {
async rollLireSigneDraconique(coord) { async rollLireSigneDraconique(coord) {
if (!this.isHautRevant()) { if (!this.isHautRevant()) {
ui.notifications.info("Seul un haut rêvant peut lire un signe draconique!"); ui.notifications.info("Seul un haut rêvant peut lire un signe draconique!");
return; return
} }
let signes = this._getSignesDraconiques(coord); let signes = this._getSignesDraconiques(coord)
if (signes.length == 0) { if (signes.length == 0) {
ui.notifications.info(`Aucun signe draconiques en ${coord} !`); ui.notifications.info(`Aucun signe draconiques en ${coord} !`)
return; return
} }
let draconicList = this.getDraconicList()
let draconicList = this.getDraconics()
.map(draconic => { .map(draconic => {
let draconicLecture = foundry.utils.duplicate(draconic); let draconicLecture = foundry.utils.duplicate(draconic)
draconicLecture.system.defaut_carac = "intellect"; draconicLecture.system.defaut_carac = "intellect"
return draconicLecture; return draconicLecture
}); });
const intellect = this.system.carac.intellect; const intellect = this.system.carac.intellect;
@@ -2392,14 +2407,15 @@ export class RdDActor extends RdDBaseActorSang {
if (this.tmrApp) { if (this.tmrApp) {
ui.notifications.warn("Vous êtes déja dans les TMR....") ui.notifications.warn("Vous êtes déja dans les TMR....")
this.tmrApp.forceTMRDisplay() this.tmrApp.forceTMRDisplay()
return return false
} }
if (mode != 'visu' && this.isDemiReve()) { if (mode != 'visu' && this.isDemiReve()) {
ui.notifications.warn("Les personnage est déjà dans les Terres Médianes, elles s'affichent en visualisation") ui.notifications.warn("Le personnage est déjà dans les Terres Médianes, elles s'affichent en visualisation")
mode = "visu"; // bascule le mode en visu automatiquement mode = "visu"; // bascule le mode en visu automatiquement
} }
if (mode == 'visu') { if (mode == 'visu') {
await this._doDisplayTMR(mode) await this._doDisplayTMR(mode)
return false
} }
else { else {
const rencontre = this.getRencontreTMREnAttente(); const rencontre = this.getRencontreTMREnAttente();
@@ -2412,6 +2428,7 @@ export class RdDActor extends RdDBaseActorSang {
buttonLabel: 'Monter dans les TMR', buttonLabel: 'Monter dans les TMR',
onAction: async () => await this._doDisplayTMR(mode) onAction: async () => await this._doDisplayTMR(mode)
}) })
return true
} }
} }
@@ -2434,7 +2451,7 @@ export class RdDActor extends RdDBaseActorSang {
let tmrFormData = { let tmrFormData = {
mode: mode, mode: mode,
fatigue: RdDUtility.calculFatigueHtml(fatigue, endurance), fatigue: RdDUtility.calculFatigueHtml(fatigue, endurance),
draconic: this.getDraconicList(), draconic: this.getDraconics(),
sort: this.itemTypes['sort'], sort: this.itemTypes['sort'],
signes: this.itemTypes['signedraconique'], signes: this.itemTypes['signedraconique'],
caracReve: parseInt(this.system.carac.reve.value), caracReve: parseInt(this.system.carac.reve.value),
@@ -2449,6 +2466,29 @@ export class RdDActor extends RdDBaseActorSang {
await this.tmrApp.onDeplacement() await this.tmrApp.onDeplacement()
} }
async quitterTMR(message, viewOnly, cumulFatigue) {
if (this.tmrApp) {
this.tmrApp = undefined
const appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue");
await this.santeIncDec(
appliquerFatigue ? "fatigue" : "endurance",
(appliquerFatigue ? 1 : -1) * cumulFatigue)
if (!viewOnly) {
await this.supprimerSignesDraconiques(it => it.system.ephemere && it.system.duree == '1 round', { render: false })
await this.setEffect(STATUSES.StatusDemiReve, false)
ChatUtility.tellToUserAndGM(message)
}
}
}
async supprimerSignesDraconiques(filter = it => true, options = { render: true }) {
const signes = this.itemTypes[ITEM_TYPES.signedraconique].filter(filter)
if (signes.length > 0) {
this.deleteEmbeddedDocuments("Item", signes.map(item => item.id), options)
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollSoins(blesse, blessureId) { async rollSoins(blesse, blessureId) {
const blessure = blesse.blessuresASoigner().find(it => it.id == blessureId); const blessure = blesse.blessuresASoigner().find(it => it.id == blessureId);
@@ -2552,7 +2592,7 @@ export class RdDActor extends RdDBaseActorSang {
if (item?.isEquipable()) { if (item?.isEquipable()) {
const isEquipe = !item.system.equipe; const isEquipe = !item.system.equipe;
await item.update({ "system.equipe": isEquipe }); await item.update({ "system.equipe": isEquipe });
this.computeEncTotal(); this.computeEncTotal()
if (isEquipe) if (isEquipe)
this.verifierForceMin(item); this.verifierForceMin(item);
} }
@@ -2943,6 +2983,7 @@ export class RdDActor extends RdDBaseActorSang {
if (updatedEndurance && options.diff) { if (updatedEndurance && options.diff) {
await this.setEffect(STATUSES.StatusUnconscious, updatedEndurance.value == 0) await this.setEffect(STATUSES.StatusUnconscious, updatedEndurance.value == 0)
} }
await super.onUpdateActor(update, options, actorId)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -2985,9 +3026,12 @@ export class RdDActor extends RdDBaseActorSang {
break break
case ITEM_TYPES.empoignade: case ITEM_TYPES.empoignade:
await RdDEmpoignade.deleteLinkedEmpoignade(this.id, item) await RdDEmpoignade.deleteLinkedEmpoignade(this.id, item)
// TODO: check remaining emp.
await this.setEffect(STATUSES.StatusGrappled, false)
await this.setEffect(STATUSES.StatusGrappling, false)
break break
} }
super.onDeleteItem(item, options, id) await super.onDeleteItem(item, options, id)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -3098,17 +3142,9 @@ export class RdDActor extends RdDBaseActorSang {
async _rollArtV2(oeuvreId) { async _rollArtV2(oeuvreId) {
const oeuvre = this.items.get(oeuvreId) const oeuvre = this.items.get(oeuvreId)
const rollData = { const rollData = {
title: `Interpretation de ${oeuvre.name} par ${this.name}`, ids: { actorId: this.id },
type: { selected: { oeuvre: { key: oeuvre.id } },
allowed: ["oeuvre"], type: { allowed: [PART_OEUVRE], current: PART_OEUVRE, },
current: "oeuvre",
},
selected: {
oeuvre: { key: oeuvre.id },
},
ids: {
actorId: this.id
}
} }
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose }) await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
} }
@@ -3206,14 +3242,26 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollRecetteCuisine(id) { async rollRecetteCuisine(id) {
const oeuvre = this.getRecetteCuisine(id); const recette = this.getRecetteCuisine(id);
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
type: { allowed: [PART_CUISINE], current: PART_CUISINE },
selected: {
cuisine: { key: recette.id }
}
}
RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return
}
const artData = { const artData = {
verbe: 'Cuisiner', verbe: 'Cuisiner',
compName: 'cuisine', compName: 'cuisine',
proportions: 1, proportions: 1,
ajouterEquipement: false ajouterEquipement: false
}; };
await this._rollArtV1(artData, 'odoratgout', oeuvre, r => this._resultRecetteCuisine(r)); await this._rollArtV1(artData, 'odoratgout', recette, r => this._resultRecetteCuisine(r));
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -3246,6 +3294,18 @@ export class RdDActor extends RdDBaseActorSang {
} }
async preparerNourriture(item) { async preparerNourriture(item) {
if (item.getUtilisationCuisine() == 'brut' && OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
type: { allowed: [PART_CUISINE], current: PART_CUISINE },
selected: {
cuisine: { key: item.id }
}
}
RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return
}
if (item.getUtilisationCuisine() == 'brut') { if (item.getUtilisationCuisine() == 'brut') {
const nourriture = { const nourriture = {
name: 'Plat de ' + item.name, name: 'Plat de ' + item.name,
@@ -3256,7 +3316,7 @@ export class RdDActor extends RdDBaseActorSang {
exotisme: item.system.exotisme, exotisme: item.system.exotisme,
ingredients: item.name ingredients: item.name
} }
}; }
const artData = { const artData = {
verbe: 'Préparer', verbe: 'Préparer',
compName: 'cuisine', compName: 'cuisine',

View File

@@ -56,13 +56,15 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet {
if (this.options.vueDetaillee) { if (this.options.vueDetaillee) {
// On carac change // On carac change
this.html.find('.carac-value').change(async event => { this.html.find('.carac-value').change(async event => {
let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", "") if (event.currentTarget.name.includes("carac.")) {
await this.actor.updateCarac(caracName, parseInt(event.target.value)) let caracName = event.currentTarget.name.replace("carac.", "")
}); await this.actor.updateCarac(caracName, parseInt(event.currentTarget.value))
}
})
// On competence change // On competence change
this.html.find('.competence-value').change(async event => { this.html.find('.competence-value').change(async event => {
let compName = event.currentTarget.attributes.compname.value let compName = event.currentTarget.attributes.compname.value
await this.actor.updateCompetence(compName, parseInt(event.target.value)) await this.actor.updateCompetence(compName, parseInt(event.currentTarget.value))
}); });
} }
} }

View File

@@ -1,4 +1,4 @@
import { ENTITE_INCARNE, renderTemplate, SHOW_DICE, SYSTEM_RDD } from "../constants.js"; import { renderTemplate, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDResolutionTable } from "../rdd-resolution-table.js"; import { RdDResolutionTable } from "../rdd-resolution-table.js";
@@ -89,7 +89,6 @@ export class RdDBaseActorReve extends RdDBaseActor {
getSConst() { return 0 } getSConst() { return 0 }
/* -------------------------------------------- */ /* -------------------------------------------- */
isSurenc() { return false }
computeMalusSurEncombrement() { return 0 } computeMalusSurEncombrement() { return 0 }
ajustementAstrologique() { return 0 } ajustementAstrologique() { return 0 }
@@ -126,6 +125,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
async remiseANeuf() { } async remiseANeuf() { }
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { } async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
computeResumeBlessure() { }
countBlessures(filter = it => !it.isContusion()) { return 0 }
async santeIncDec(name, inc, isCritique = false) { } async santeIncDec(name, inc, isCritique = false) { }
async finDeRound(options = { terminer: false }) { async finDeRound(options = { terminer: false }) {
@@ -176,10 +177,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
getCompetences(name = undefined, options = { onMessage: message => { } }) { getCompetences(name = undefined, options = { onMessage: message => { } }) {
const all = [...this.itemTypes[ITEM_TYPES.competence], ...this.itemTypes[ITEM_TYPES.competencecreature]]
if (name == undefined) { if (name == undefined) {
return this.itemTypes[ITEM_TYPES.competence] return all
} }
return RdDItemCompetence.findCompetences(this.itemTypes[ITEM_TYPES.competence], name, options) return RdDItemCompetence.findCompetences(all, name, options)
} }
getCompetenceCorpsACorps(options = { onMessage: message => { } }) { getCompetenceCorpsACorps(options = { onMessage: message => { } }) {
@@ -203,6 +205,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
getPossession(possessionId) { getPossession(possessionId) {
return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId); return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId);
} }
getEmpoignades() { getEmpoignades() {
return this.itemTypes[ITEM_TYPES.empoignade]; return this.itemTypes[ITEM_TYPES.empoignade];
} }
@@ -226,53 +229,13 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
} }
/* -------------------------------------------- */
isEffectAllowed(effectId) { return false }
getEffects(filter = e => true, forceRequise = undefined) {
const effects = this.getEmbeddedCollection("ActiveEffect")
const selected = effects.filter(filter)
if (forceRequise && this.isForceInsuffisante(forceRequise)) {
selected.push(StatusEffects.prepareActiveEffect(STATUSES.StatusForceWeak))
}
return selected
}
getEffectByStatus(statusId) {
return this.getEffects().find(it => it.statuses.has(statusId));
}
async setEffect(statusId, status) {
if (this.isEffectAllowed(statusId)) {
const effect = this.getEffectByStatus(statusId);
if (!status && effect) {
await this.deleteEmbeddedDocuments('ActiveEffect', [effect.id]);
}
if (status && !effect) {
await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.prepareActiveEffect(statusId)]);
}
}
}
async removeEffect(id) {
this.removeEffects(it => it.id == id)
}
async removeEffects(filter = e => true) {
if (game.user.isGM) {
const effectsToRemove = this.getEffects(filter);
const ids = effectsToRemove.map(it => it.id);
await this.deleteEmbeddedDocuments('ActiveEffect', ids);
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
isDemiReve() { isDemiReve() {
return this.getEffectByStatus(STATUSES.StatusDemiReve) != undefined return this.getEffectsByStatus(STATUSES.StatusDemiReve).length > 0
} }
getSurprise(isCombat = undefined) { getSurprise(isCombat = undefined, forceRequise = undefined) {
return StatusEffects.getSurprise(this.getEffects(), isCombat) return StatusEffects.getSurprise(this.getEffects(e => true, isCombat, forceRequise), isCombat)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -309,6 +272,22 @@ export class RdDBaseActorReve extends RdDBaseActor {
async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) { async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) {
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const competence = this.getCompetence(compName);
const rollData = {
ids: { actorId: this.id },
type: { allowed: DEFAULT_ROLL_TYPES, current: PART_COMP },
selected: {
carac: { key: caracName },
comp: { key: competence.name },
diff: { value: diff }
}
}
RollDialog.create(rollData, options)
return
}
const competence = this.getCompetence(compName); const competence = this.getCompetence(compName);
await this.openRollDialog({ await this.openRollDialog({
name: 'jet-competence', name: 'jet-competence',
@@ -387,7 +366,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { allowed: [PART_COMP], current: PART_COMP }, type: { allowed: DEFAULT_ROLL_TYPES, current: PART_COMP },
selected: { selected: {
carac: { key: caracName }, carac: { key: caracName },
comp: options.resistance ? { key: undefined, forced: true } : undefined comp: options.resistance ? { key: undefined, forced: true } : undefined
@@ -423,32 +402,22 @@ export class RdDBaseActorReve extends RdDBaseActor {
await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-general.hbs'); await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-general.hbs');
} }
/* -------------------------------------------- */
async rollCompetenceV2(rollData) {
rollData.ids = rollData?.ids ?? {}
rollData.type = rollData.type ?? { allowed: DEFAULT_ROLL_TYPES }
rollData.ids.actorId = this.id
await RollDialog.create(rollData)
}
async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) { async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) {
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
const competence = this.getCompetence(idOrName); const competence = this.getCompetence(idOrName);
if (competence.type != ITEM_TYPES.competencecreature && OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = { const rollData = {
ids: { actorId: this.id },
type: { allowed: options.arme ? ATTAQUE_ROLL_TYPES : DEFAULT_ROLL_TYPES },
selected: { selected: {
carac: competence.type == ITEM_TYPES.competencecreature ? { key: competence.name } : undefined,
comp: { key: competence.name }, comp: { key: competence.name },
diff: { type: DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 } diff: { type: options.arme ? DIFF.ATTAQUE : DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 },
attaque: options.arme ? { arme: { key: options.arme.id } } : undefined
} }
} }
if (options.arme) { return await RollDialog.create(rollData)
rollData.selected.attaque = { arme: { id: options.arme.id }, comp: { id: competence.id } }
rollData.type = { allowed: ATTAQUE_ROLL_TYPES }
}
await this.rollCompetenceV2(rollData)
return
} }
let rollData = { let rollData = {
@@ -512,19 +481,13 @@ export class RdDBaseActorReve extends RdDBaseActor {
title: 'Ne pas utiliser les automatisation de combat', title: 'Ne pas utiliser les automatisation de combat',
buttonLabel: "Pas d'automatisation", buttonLabel: "Pas d'automatisation",
onAction: async () => { onAction: async () => {
this.rollCompetenceV2({ const rollData = {
ids: { ids: { actorId: this.id, actorTokenId: token?.id, },
actorId: this.id,
actorTokenId: token?.id,
},
selected: {
conditions: { value: 0 }
},
type: { type: {
allowed: [ROLL_TYPE_COMP, ROLL_TYPE_ATTAQUE, ROLL_TYPE_OEUVRE, ROLL_TYPE_TACHE, ROLL_TYPE_JEU], allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE
current: ROLL_TYPE_COMP
} }
}) };
return await RollDialog.create(rollData)
} }
}) })
} }
@@ -669,7 +632,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
async accorder(entite, when = 'avant-encaissement') { async accorder(entite, when = 'avant-encaissement') {
if (when != game.settings.get(SYSTEM_RDD, "accorder-entite-cauchemar") if (when != game.settings.get(SYSTEM_RDD, "accorder-entite-cauchemar")
|| entite == undefined || entite == undefined
|| !entite.isEntite([ENTITE_INCARNE]) || !entite.isEntiteIncarnee()
|| entite.isEntiteAccordee(this)) { || entite.isEntiteAccordee(this)) {
return true return true
} }

View File

@@ -116,6 +116,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
blessure: blessure blessure: blessure
}); });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async santeIncDec(name, inc, isCritique = false) { async santeIncDec(name, inc, isCritique = false) {
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) { if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
@@ -179,6 +180,28 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return Math.max(0, Math.min(maxEndVie, maxEndGraves, maxEndCritiques)); return Math.max(0, Math.min(maxEndVie, maxEndGraves, maxEndCritiques));
} }
async onCreateItem(item, options, id) {
switch (item.type) {
case ITEM_TYPES.blessure:
await this.changeBleedingState()
break
}
await super.onCreateItem(item, options, id)
}
async onUpdateItem(item, options, id) {
switch (item.type) {
case ITEM_TYPES.blessure:
await this.changeBleedingState()
break
}
await super.onUpdateItem(item, options, id)
}
async changeBleedingState() {
const bleeding = this.itemTypes[ITEM_TYPES.blessure].find(it => it.isBleeding())
await this.setEffect(STATUSES.StatusBleeding, bleeding ? true : false)
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async ajouterBlessure(encaissement, attackerToken = undefined) { async ajouterBlessure(encaissement, attackerToken = undefined) {
@@ -292,7 +315,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
} }
isSonne() { isSonne() {
return this.getEffectByStatus(STATUSES.StatusStunned) return this.getEffectsByStatus(STATUSES.StatusStunned).length > 0
} }
isEffectAllowed(effectId) { return true } isEffectAllowed(effectId) { return true }

View File

@@ -49,15 +49,14 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
formData.calc = { formData.calc = {
fortune: Monnaie.toSolsDeniers(this.actor.getFortune()), fortune: Monnaie.toSolsDeniers(this.actor.getFortune()),
prixTotalEquipement: this.actor.computePrixTotalEquipement(), prixTotalEquipement: this.actor.computePrixTotalEquipement(),
encTotal: await this.actor.computeEncTotal(), encTotal: this.actor.getEncTotal(),
} }
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires); this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires); this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires);
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs); formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
formData.competences.filter(it => it.type == ITEM_TYPES.competencecreature) formData.competences.filter(it => it.type == ITEM_TYPES.competencecreature)
.forEach(it => it.isdommages = it.isDommages() .forEach(it => it.isdommages = it.isDommages())
)
return formData; return formData;
} }
@@ -230,14 +229,6 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
return position; return position;
} }
/* -------------------------------------------- */
/** @override */
_updateObject(event, formData) {
// Update the Actor
return this.actor.update(formData);
}
async splitItem(item) { async splitItem(item) {
const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split)); const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split));
dialog.render(true); dialog.render(true);

View File

@@ -10,7 +10,7 @@ import { RdDConfirm } from "../rdd-confirm.js";
import { RdDUtility } from "../rdd-utility.js"; import { RdDUtility } from "../rdd-utility.js";
import { SystemCompendiums } from "../settings/system-compendiums.js"; import { SystemCompendiums } from "../settings/system-compendiums.js";
import { RdDItem } from "../item.js"; import { RdDItem } from "../item.js";
import { STATUSES } from "../settings/status-effects.js"; import { StatusEffects, STATUSES } from "../settings/status-effects.js";
export class RdDBaseActor extends Actor { export class RdDBaseActor extends Actor {
@@ -215,9 +215,11 @@ export class RdDBaseActor extends Actor {
return game.users.players.find(player => player.active && player.character?.id == this.id); return game.users.players.find(player => player.active && player.character?.id == this.id);
} }
isCreatureEntite() { return this.isCreature() || this.isEntite() } isCreatureOuEntite() { return this.isCreature() || this.isEntite() }
isCreature() { return false } isCreature() { return false }
isEntite(typeentite = []) { return false } isEntite() { return false }
isEntiteIncarnee() { return false }
isEntiteNonIncarnee() { return false }
isHautRevant() { return false } isHautRevant() { return false }
isVehicule() { return false } isVehicule() { return false }
isPersonnage() { return false } isPersonnage() { return false }
@@ -241,41 +243,76 @@ export class RdDBaseActor extends Actor {
getMonnaie(id) { return this.findItemLike(id, 'monnaie'); } getMonnaie(id) { return this.findItemLike(id, 'monnaie'); }
getEncombrementMax() { return 0 } getEncombrementMax() { return 0 }
isSurenc() { return false }
/* -------------------------------------------- */
isEffectAllowed(effectId) { return false }
getEffects(filter = e => true, forceRequise = undefined) {
const effects = this.getEmbeddedCollection("ActiveEffect")
const selected = effects.filter(filter)
if (forceRequise && this.isForceInsuffisante(forceRequise)) {
selected.push(StatusEffects.prepareActiveEffect(STATUSES.StatusForceWeak))
}
return selected
}
getEffectsByStatus(effectId) {
return this.getEffects().filter(it => it.statuses.has(effectId))
}
async setEffect(effectId, status) {
if (this.isEffectAllowed(effectId)) {
const effects = this.getEffectsByStatus(effectId)
if (!status && effects.length > 0) {
await this.deleteEmbeddedDocuments('ActiveEffect', effects.map(it => it.id), { render: true })
}
if (status && effects.length == 0) {
await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.prepareActiveEffect(effectId)], { render: true })
}
}
}
async removeEffect(id) {
this.removeEffects(it => it.id == id)
}
async removeEffects(filter = e => true) {
if (game.user.isGM) {
const effectsToRemove = this.getEffects(filter);
const ids = effectsToRemove.map(it => it.id);
await this.deleteEmbeddedDocuments('ActiveEffect', ids);
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async updateCarac(caracName, to) { async updateCarac(caracName, to) {
} }
async onUpdateActor(change, options, actorId) {
const updatedCarac = change?.system?.carac
if (updatedCarac && (updatedCarac.force || updatedCarac.reve || updatedCarac.taille)) {
console.log(' onUpdateActor', change, options, actorId)
await this.setEffect(STATUSES.StatusSurEnc, this.isSurenc())
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async onPreUpdateItem(item, change, options, id) { } async onPreUpdateItem(item, change, options, id) { }
async onCreateItem(item, options, id) { async onCreateItem(item, options, id) {
switch (item.type) {
case ITEM_TYPES.blessure:
await this.changeBleedingState()
break
}
} }
async onUpdateItem(item, options, id) { async onUpdateItem(item, options, id) {
switch (item.type) {
case ITEM_TYPES.blessure:
await this.changeBleedingState()
break
}
} }
async changeBleedingState() {
const bleeding = this.itemTypes[ITEM_TYPES.blessure].find(it => it.isBleeding())
await this.setEffect(STATUSES.StatusBleeding, bleeding ? true : false)
}
async onUpdateActor(update, options, actorId) { }
async onDeleteItem(item, options, id) { async onDeleteItem(item, options, id) {
if (item.isInventaire()) { if (item.isInventaire()) {
await this._removeItemFromConteneur(item) await this._removeItemFromConteneur(item)
} }
} }
async _removeItemFromConteneur(item) { async _removeItemFromConteneur(item) {
const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id)) const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id))
.map(conteneur => { .map(conteneur => {
@@ -524,16 +561,22 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async computeEncTotal() { async computeEncTotal() {
if (!this.pack) { if (this.pack) {
this.encTotal = 0
}
else {
const wasSurenc = this.isSurenc()
this.encTotal = this.items.filter(it => RdDItem.getItemTypesInventaire().includes(it.type)) this.encTotal = this.items.filter(it => RdDItem.getItemTypesInventaire().includes(it.type))
.map(it => it.getEncTotal()).reduce(Misc.sum(), 0) .map(it => it.getEncTotal()).reduce(Misc.sum(), 0)
return this.encTotal; const isSurenc = this.isSurenc()
if (isSurenc != wasSurenc) {
await this.setEffect(STATUSES.StatusSurEnc, isSurenc)
}
} }
return 0;
} }
getEncTotal() { getEncTotal() {
return Math.floor(this.encTotal ?? 0); return Math.floor(this.encTotal ?? 0)
} }
async createItem(type, name = undefined) { async createItem(type, name = undefined) {
@@ -584,7 +627,7 @@ export class RdDBaseActor extends Actor {
} }
} }
} }
await this.computeEncTotal(); await this.computeEncTotal()
return result; return result;
} }

View File

@@ -43,7 +43,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
this.html.find('.resonance-add').click(async event => this.html.find('.resonance-add').click(async event =>
await DialogSelect.select({ await DialogSelect.select({
label: "Choisir un acteur à accorder", label: "Choisir un acteur à accorder",
list: game.actors.filter(it => it.isPersonnage() && it.prototypeToken.actorLink) list: game.actors.filter(it => true)
}, },
it => this.resonanceAdd(it.id)) it => this.resonanceAdd(it.id))
) )

View File

@@ -1,5 +1,6 @@
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js"; import { ENTITE_BLURETTE, ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
import { ITEM_TYPES } from "../constants.js"; import { ITEM_TYPES } from "../constants.js";
import { RdDItemBlessure } from "../item/blessure.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDCarac } from "../rdd-carac.js"; import { RdDCarac } from "../rdd-carac.js";
import { RdDEncaisser } from "../rdd-roll-encaisser.js"; import { RdDEncaisser } from "../rdd-roll-encaisser.js";
@@ -16,11 +17,10 @@ export class RdDEntite extends RdDBaseActorReve {
return item.type == ITEM_TYPES.competencecreature return item.type == ITEM_TYPES.competencecreature
} }
isEntite(typeentite = []) { isEntite() { return true }
return (typeentite.length == 0 || typeentite.includes(this.system.definition.typeentite)); isEntiteNonIncarnee() { return this.system.definition.typeentite == ENTITE_NONINCARNE }
} isEntiteIncarnee() { return [ENTITE_INCARNE, ENTITE_BLURETTE].includes(this.system.definition.typeentite) }
isEntiteBlurette() { return this.system.definition.typeentite !== ENTITE_BLURETTE }
isNonIncarnee() { return this.isEntite([ENTITE_NONINCARNE]) }
getReveActuel() { getReveActuel() {
return Misc.toInt(this.system.carac.reve?.value) return Misc.toInt(this.system.carac.reve?.value)
@@ -49,20 +49,20 @@ export class RdDEntite extends RdDBaseActorReve {
} }
async remiseANeuf() { async remiseANeuf() {
await this.removeEffects(e => true); if (!this.isEntiteNonIncarnee()) {
if (!this.isNonIncarnee()) {
await this.update({ await this.update({
'system.sante.endurance.value': this.system.sante.endurance.max 'system.sante.endurance.value': this.system.sante.endurance.max
}); });
} }
await this.removeEffects(e => true)
} }
isDead() { isDead() {
return this.isNonIncarnee() ? false : this.system.sante.endurance.value <= 0 return this.isEntiteNonIncarnee() ? false : this.system.sante.endurance.value <= 0
} }
async santeIncDec(name, inc, isCritique = false) { async santeIncDec(name, inc, isCritique = false) {
if (name == 'endurance' && !this.isNonIncarnee()) { if (name == 'endurance' && !this.isEntiteNonIncarnee()) {
const oldValue = this.system.sante.endurance.value; const oldValue = this.system.sante.endurance.value;
const endurance = Math.max(0, const endurance = Math.max(0,
Math.min(oldValue + inc, Math.min(oldValue + inc,
@@ -78,7 +78,7 @@ export class RdDEntite extends RdDBaseActorReve {
} }
async encaisser() { async encaisser() {
if (this.isNonIncarnee()) { if (this.isEntiteNonIncarnee()) {
return return
} }
await RdDEncaisser.encaisser(this) await RdDEncaisser.encaisser(this)
@@ -89,15 +89,19 @@ export class RdDEntite extends RdDBaseActorReve {
} }
async onAppliquerJetEncaissement(encaissement, attackerToken) { async onAppliquerJetEncaissement(encaissement, attackerToken) {
if (this.isEntiteNonIncarnee()) {
return
}
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance); const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance);
foundry.utils.mergeObject(encaissement, { foundry.utils.mergeObject(encaissement, {
resteEndurance: perteEndurance.newValue, resteEndurance: perteEndurance.newValue,
endurance: perteEndurance.perte endurance: perteEndurance.perte,
}); blessure: RdDItemBlessure.prepareBlessure(encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken)
})
} }
isEntiteAccordee(attacker) { isEntiteAccordee(attacker) {
if (this.isEntite([ENTITE_INCARNE])) { if (this.isEntiteIncarnee()) {
let resonnance = this.system.sante.resonnance let resonnance = this.system.sante.resonnance
return (resonnance.actors.find(it => it == attacker.id)) return (resonnance.actors.find(it => it == attacker.id))
} }
@@ -106,7 +110,7 @@ export class RdDEntite extends RdDBaseActorReve {
/* -------------------------------------------- */ /* -------------------------------------------- */
async setEntiteReveAccordee(actor) { async setEntiteReveAccordee(actor) {
if (this.isEntite([ENTITE_INCARNE])) { if (this.isEntiteIncarnee()) {
if (this.system.sante.resonnance.actors.find(it => it == actor.id)) { if (this.system.sante.resonnance.actors.find(it => it == actor.id)) {
// déjà accordé // déjà accordé
return return

View File

@@ -29,7 +29,7 @@ export class ExperienceLog {
}; };
console.log('ExperienceLog.add', newXpLog) console.log('ExperienceLog.add', newXpLog)
const newExperienceLog = (actor.system.experiencelog ?? []).concat([newXpLog]); const newExperienceLog = (actor.system.experiencelog ?? []).concat([newXpLog]);
await actor.update({ [`system.experiencelog`]: newExperienceLog }); await actor.update({ [`system.experiencelog`]: newExperienceLog }, { noHook: true });
} }
static labelTopic(topic) { static labelTopic(topic) {

View File

@@ -0,0 +1,288 @@
import { ACTOR_TYPES, ITEM_TYPES } from "../../constants.js"
import { Grammar } from "../../grammar.js"
import { RdDItemArme } from "../../item/arme.js"
import { CATEGORIES_COMPETENCE_COMBAT } from "../../item/base-items.js"
import { Misc } from "../../misc.js"
import { RdDTimestamp } from "../../time/rdd-timestamp.js"
import { PDFDocument } from "./pdf-lib/pdf-lib.esm.js"
const copyProperty = (actor, path) => foundry.utils.getProperty(actor, path)
// const findItem = (actor, itemType, itemName) => actor.itemTypes[itemType].find(it => Grammar.equalsInsensitive(formCompName(it.name), formCompName(itemName)))
// const findItemPos = (actor, itemType, pos) => actor.itemTypes[itemType].length <= pos ? actor.itemTypes[itemType][pos] : length
// const findProperty = (it, path) => it ? foundry.utils.getProperty(it, path) : undefined
// const findItemProperty = (actor, itemType, itemName, path) => findProperty(findItem(actor, itemType, itemName), path)
// const findItemPosProperty = (actor, itemType, pos, path) => findProperty(findItemPos(actor, itemType, pos), path)
// const findArmeProperty = (actor, pos, path) => findProperty(findItemPos(actor, ITEM_TYPES.arme, pos), path)
// const findSortProperty = (actor, pos, path) => findProperty(findItemPos(actor, ITEM_TYPES.sort, pos), path)
// const itemFormPath = (type, pos, property) => `${type}s.${pos}.${property}`
const ACTOR_TO_FORM_MAPPING = [
{ path: 'name' },
{ path: 'system.carac.taille.value' },
{ path: 'system.carac.apparence.value' },
{ path: 'system.carac.apparence.xp' },
{ path: 'system.carac.constitution.value' },
{ path: 'system.carac.constitution.xp' },
{ path: 'system.carac.force.value' },
{ path: 'system.carac.force.value' },
{ path: 'system.carac.force.xp' },
{ path: 'system.carac.agilite.value' },
{ path: 'system.carac.agilite.xp' },
{ path: 'system.carac.dexterite.value' },
{ path: 'system.carac.dexterite.xp' },
{ path: 'system.carac.vue.value' },
{ path: 'system.carac.vue.xp' },
{ path: 'system.carac.ouie.value' },
{ path: 'system.carac.ouie.xp' },
{ path: 'system.carac.odoratgout.value' },
{ path: 'system.carac.odoratgout.xp' },
{ path: 'system.carac.volonte.value' },
{ path: 'system.carac.volonte.xp' },
{ path: 'system.carac.empathie.value' },
{ path: 'system.carac.empathie.xp' },
{ path: 'system.carac.intellect.value' },
{ path: 'system.carac.intellect.xp' },
{ path: 'system.carac.reve.value' },
{ path: 'system.carac.reve.xp' },
{ path: 'system.carac.chance.value' },
{ path: 'system.carac.chance.xp' },
{ path: 'system.age' },
{ path: 'system.sexe' },
{ path: 'system.taille' },
{ path: 'system.poids' },
{ path: 'system.cheveux' },
{ path: 'system.yeux' },
{ path: 'system.beaute' },
{ path: 'system.main' },
{ path: 'system.heure' },
{ path: 'computed.hn.heure', getter: actor => (RdDTimestamp.definition(actor.system.heure)?.heure ?? 0) + 1 },
{ path: 'computed.hn.label', getter: actor => RdDTimestamp.definition(actor.system.heure)?.avecArticle },
{ path: 'system.carac.melee.value' },
{ path: 'system.carac.tir.value' },
{ path: 'system.carac.lancer.value' },
{ path: 'system.carac.derobee.value' },
{ path: 'system.sante.vie.value' },
{ path: 'system.sante.endurance.value' },
{ path: 'system.attributs.sust.value' },
{ path: 'system.attributs.sconst.value' },
{ path: 'system.attributs.encombrement.value' },
{ path: 'system.attributs.plusdom.value', getter: actor => Misc.toSignedString(actor.system.attributs.plusdom.value) },
// , getter: actor => actor.get
]
export default class ExportPdf {
static init() {
Hooks.on("getActorContextOptions", (actorDirectory, menus) => { ExportPdf.onActorDirectoryMenu(actorDirectory, menus) })
}
static onActorDirectoryMenu(actorDirectory, menus) {
menus.push({
name: 'Export PDF',
icon: '<i class="fa-regular fa-file-pdf"></i>',
condition: target => actorDirectory.id == 'actors' && ExportPdf.$isActorPersonnage(this.$getActor(target)),
callback: async target => await ExportPdf.exportActor(target)
})
}
static $getActor(target) {
const entryId = $(target).closest(".directory-item")?.data("entryId")
return game.actors.get(entryId)
}
static $isActorPersonnage(actor) {
return actor?.type == ACTOR_TYPES.personnage
}
static async exportActor(target) {
const actor = ExportPdf.$getActor(target)
if (!ExportPdf.$isActorPersonnage(actor)) {
ui.notifications.error("Pas de personnage sélectionné")
return
}
const templatePdf = '/systems/foundryvtt-reve-de-dragon/assets/feuille-personnage.pdf';
const pdfBytes = await fetch(templatePdf).then(res => res.arrayBuffer())
const pdfDoc = await PDFDocument.load(pdfBytes)
const exporter = new ExportPdf(actor, pdfDoc)
exporter.generateFeuillePersonnage()
}
constructor(actor, pdfDoc) {
this.pdfDoc = pdfDoc
this.form = this.pdfDoc.getForm()
this.actor = actor
this.allComps = this.actor.itemTypes[ITEM_TYPES.competence]
this.comps = this.allComps
.filter(it => !it.isNiveauBase())
.sort(Misc.ascending(it => it.name))
this.compsNonArmes = this.comps.filter(it => !ExportPdf.isCompCombat(it))
this.compsArmes = this.comps.filter(it => ExportPdf.isCompCombat(it))
this.addedComps = new Set([])
}
static isCompCombat(comp) {
return CATEGORIES_COMPETENCE_COMBAT.includes(comp.system.categorie) && !Grammar.includesLowerCaseNoAccent(comp.name, "corps à corps") && !Grammar.includesLowerCaseNoAccent(comp.name, "esquive")
}
async generateFeuillePersonnage() {
this.$exportActorFields()
this.$exportCompetences()
this.$exportArchetype()
this.$exportArmes()
this.$exportSorts()
const pdfBytes = await this.pdfDoc.save();
const filename = `rdd-${this.actor.name.slugify()}.pdf`;
foundry.utils.saveDataToFile(pdfBytes, "application/pdf", filename);
}
$exportActorFields() {
ACTOR_TO_FORM_MAPPING.forEach(async (mapping) => {
const path = mapping.path
const value = mapping.getter ? mapping.getter(this.actor) : copyProperty(this.actor, path)
this.$setFormValue(path, value)
})
}
$exportCompetences() {
this.compsNonArmes
.filter(it => !this.addedComps.has(it.id))
.forEach(comp => {
const formCompName = Grammar.toLowerCaseNoAccent(comp.name.replaceAll(/(\s|-|\')/g, '_'))
this.$setFormCompetence(formCompName, comp)
})
const musique = this.compsNonArmes.filter(it => Grammar.includesLowerCaseNoAccent(it.name, 'musique'))
.sort(Misc.descending(it => it.system.niveau))
.filter(it => !this.addedComps.has(it.id))
.find(it => true)
if (musique) {
this.$setFormCompetence('musique', musique)
}
}
$exportArchetype() {
this.allComps.sort(Misc.ascending(it => it.system.niveau_archetype))
.forEach(comp => {
let formCompName = Grammar.toLowerCaseNoAccent(comp.name.replaceAll(/(\s|-|\')/g, '_'))
if (formCompName.includes('musique')) {
formCompName = 'musique'
}
this.$setFormValue(`competences.${formCompName}.niveau_archetype`, comp.system.niveau_archetype)
})
}
$setFormCompetenceArchetype(formCompName, comp, baseFormName = 'competences') {
}
$exportArmes() {
const uniques = new Set([])
const armes = this.actor.itemTypes[ITEM_TYPES.arme].map(arme => arme.getTypeAttaques()
.map(main => {
const compName = arme.getCompetenceAction(main)
const dommages = RdDItemArme.valeurMain(arme.system.dommages, main)
const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
const comp = this.compsArmes.find(it => Grammar.equalsInsensitive(it.name, compName)) ?? this.actor.findItemLike(compName, ITEM_TYPES.competence)
const unique = [comp.id, arme.name, dommages, forceRequise].join('|');
if (uniques.has(unique)) {
return undefined
}
uniques.add(unique)
return { arme: arme, comp: comp, main: main }
}))
.reduce((a, b) => a.concat(b))
.filter(it => it != undefined && !it.comp.isNiveauBase())
.sort(Misc.descending(it => it.comp.niveau))
for (let pos = 0; pos < armes.length; pos++) {
const it = armes[pos]
this.$setFormArmeCompetence(pos, it.comp, it.arme, it.main, it.main)
}
// TODO: list comps without weapons
// TODO: list other comps not in the standard list -- use an instance of ExportPdf to hold state/built list
const otherComps = this.comps.filter(it => !this.addedComps.has(it.id))
for (let pos = 0; pos < otherComps.length; pos++) {
const comp = otherComps[pos]
this.$setFormCompetence(pos, comp, 'competences')
this.$setFormValue(`competences.${pos}.name`, comp.name)
}
}
$setFormCompetence(formCompName, comp, baseFormName = 'competences') {
if (this.form.getFieldMaybe(`${baseFormName}.${formCompName}.niveau`)) {
this.addedComps.add(comp.id)
}
if (comp.system.niveau != comp.system.base) {
this.$setFormValue(`${baseFormName}.${formCompName}.niveau`, comp.system.niveau)
}
if (comp.system.xp > 0) {
this.$setFormValue(`${baseFormName}.${formCompName}.xp`, comp.system.xp)
}
if (comp.system.xp_sort > 0) {
this.$setFormValue(`${baseFormName}.${formCompName}.xp_sort`, comp.system.xp_sort)
}
if (CATEGORIES_COMPETENCE_COMBAT.includes(comp.system.categorie)) {
this.$setFormValue(`${baseFormName}.${formCompName}.init`, comp.getBaseInit())
}
}
$setFormArmeCompetence(pos, comp, arme, main) {
this.$setFormCompetence(pos, comp, 'armes')
this.$setFormValue(`armes.${pos}.name`, arme.name)
this.$setFormValue(`armes.${pos}.main`, main)
this.$setFormValue(`armes.${pos}.plusdom`, RdDItemArme.valeurMain(arme.system.dommages, main))
}
$exportSorts() {
const sorts = this.actor.itemTypes[ITEM_TYPES.sort].sort(Misc.ascending(s => ExportPdf.$orderDraconic(s) + s.name))
for (let pos = 0; pos < sorts.length; pos++) {
const sort = sorts[pos]
this.$setFormSort(pos, sort)
}
}
$setFormSort(pos, sort) {
this.$setFormValue(`sorts.${pos}.name`, sort.name)
this.$setFormValue(`sorts.${pos}.voie`, sort.system.draconic)
this.$setFormValue(`sorts.${pos}.tmr`, sort.system.caseTMRSpeciale ?? sort.system.caseTMR)
this.$setFormValue(`sorts.${pos}.diff`, sort.system.difficulte)
this.$setFormValue(`sorts.${pos}.reve`, sort.system.ptreve)
this.$setFormValue(`sorts.${pos}.bonuscase`, sort.system.bonuscase)
}
static $orderDraconic(s) {
switch (s.system.draconic.substring(0, 1)) {
case 'O': return 1
case 'H': return 2
case 'N': return 3
case 'T': return 4
}
return 5
}
$setFormValue(path, value) {
const hasField = this.form.getFieldMaybe(path)
if (hasField && value != undefined) {
const field = this.form.getTextField(path)
field.setText(value.toString())
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -2,7 +2,7 @@ import { Grammar } from "../../grammar.js"
import { EMPOIGNADE, RdDItemArme } from "../../item/arme.js" import { EMPOIGNADE, RdDItemArme } from "../../item/arme.js"
import { RdDItemCompetence } from "../../item-competence.js" import { RdDItemCompetence } from "../../item-competence.js"
import { RdDItemSort } from "../../item-sort.js" import { RdDItemSort } from "../../item-sort.js"
import { ITEM_TYPES } from "../../constants.js" import { ITEM_TYPES, RDD_CONFIG } from "../../constants.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 { RdDBonus } from "../../rdd-bonus.js" import { RdDBonus } from "../../rdd-bonus.js"
@@ -160,7 +160,7 @@ export class Mapping {
return undefined return undefined
} }
const categorie = Mapping.complementCategorie(arme, maniement) const categorie = Mapping.complementCategorie(arme, maniement)
const dommages = Mapping.dommagesArme(actor, arme, maniement) const dommages = Mapping.dommages(actor, arme, maniement)
return { return {
name: arme.name + categorie, name: arme.name + categorie,
niveau: Misc.toSignedString(competence.system.niveau), niveau: Misc.toSignedString(competence.system.niveau),
@@ -170,12 +170,13 @@ export class Mapping {
arme: arme arme: arme
} }
} }
static dommagesArme(actor, arme, maniement) {
static dommages(actor, arme, maniement) {
const dmgArme = RdDItemArme.dommagesReels(arme, maniement) const dmgArme = RdDItemArme.dommagesReels(arme, maniement)
const dommages = Misc.toSignedString(dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme)) const dommages = Misc.toSignedString(dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme))
switch (arme.system.mortalite) { switch (arme.system.mortalite) {
case 'non-mortel': return `(${dommages})` case RDD_CONFIG.encaissement.nonmortel: return `(${dommages})`
case EMPOIGNADE: return '-' case RDD_CONFIG.encaissement.empoignade: return '-'
} }
return dommages return dommages
} }

View File

@@ -20,14 +20,15 @@ const PATHS = [
const RANDOM_VALUES = { const RANDOM_VALUES = {
'system.sexe': { 'masculin': 1, 'féminin': 1 }, 'system.sexe': { 'masculin': 1, 'féminin': 1 },
'system.main': { 'droitier': 51, 'gaucher': 15, 'ambidextre': 6 }, 'system.main': { 'droitier': 51, 'gaucher': 15, 'ambidextre': 6 },
'system.cheveux': { 'noirs': 2, 'bruns': 5, 'châtains clair': 5, 'blonds': 4, 'blonds très clair': 1, 'roux carotte': 1, 'roux cuivré': 3 }, 'system.cheveux': { 'noirs': 2, 'bruns': 5, 'châtains': 3, 'châtain clair': 5, 'blonds': 4, 'blond platine': 1, 'roux carotte': 1, 'roux cuivré': 3, 'chauve': 1 },
'system.yeux': { 'noirs': 2, 'noisettes': 3, 'bruns vert': 4, 'verts': 3, 'bleus clair': 3, 'bleus gris': 2, 'gris': 1, 'mauves': 1, 'indigos': 1 }, 'system.yeux': { 'noirs': 2, 'noisette': 3, 'brun-vert': 4, 'verts': 3, 'bleu clair': 3, 'bleu gris': 2, 'gris': 1, 'mauves': 1, 'indigos': 1 },
} }
export class AppPersonnageAleatoire extends FormApplication { export class AppPersonnageAleatoire extends FormApplication {
static preloadHandlebars() { static preloadHandlebars() {
foundry.applications.handlebars.loadTemplates([ foundry.applications.handlebars.loadTemplates([
'systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/random/sexe-aleatoire.hbs',
]) ])
} }
@@ -49,14 +50,14 @@ export class AppPersonnageAleatoire extends FormApplication {
this.current = foundry.utils.duplicate(actor) this.current = foundry.utils.duplicate(actor)
this.checked = { this.checked = {
'name': false, 'name': false,
'system.sexe': true, 'system.sexe': (this.actor.system.sexe ?? '') == '',
'system.age': true, 'system.age': this.actor.system.age == 0,
'system.taille': true, 'system.taille': (this.actor.system.taille ?? '') == '',
'system.poids': true, 'system.poids': (this.actor.system.poids ?? '') == '',
'system.main': true, 'system.main': (this.actor.system.main ?? '') == '',
'system.heure': true, 'system.heure': (this.actor.system.heure ?? '') == '',
'system.cheveux': true, 'system.cheveux': (this.actor.system.cheveux ?? '') == '',
'system.yeux': true 'system.yeux': (this.actor.system.yeux ?? '') == '',
} }
} }
@@ -76,6 +77,8 @@ export class AppPersonnageAleatoire extends FormApplication {
this.html.find("button.button-apply").click(async event => await this.onApply()) this.html.find("button.button-apply").click(async event => await this.onApply())
this.html.find("input.current-value").change(async event => await this.onChange(event)) this.html.find("input.current-value").change(async event => await this.onChange(event))
this.html.find("div.random-field[data-path='system.heure'] select.current-value").change(async event => await this.onChange(event)) this.html.find("div.random-field[data-path='system.heure'] select.current-value").change(async event => await this.onChange(event))
this.html.find('a[data-action="sexe-masculin"]').click(async event => await this.onSexe('masculin'))
this.html.find('a[data-action="sexe-feminin"]').click(async event => await this.onSexe('féminin'))
this.html.find("a.random").click(async event => await this.onRandom(event)) this.html.find("a.random").click(async event => await this.onRandom(event))
this.html.find("a.reset").click(async event => await this.onReset(event)) this.html.find("a.reset").click(async event => await this.onReset(event))
this.html.find("a.randomize-selected").click(async event => await this.onRandomizeSelected()) this.html.find("a.randomize-selected").click(async event => await this.onRandomizeSelected())
@@ -96,6 +99,10 @@ export class AppPersonnageAleatoire extends FormApplication {
const fields = this.html.find(selector).parents("div.random-field:first") const fields = this.html.find(selector).parents("div.random-field:first")
return fields[0].attributes['data-path'].value return fields[0].attributes['data-path'].value
} }
async onSexe(sexe) {
this.current['system.sexe'] = sexe
this.render()
}
async onChange(event) { async onChange(event) {
const path = this.getPath(event.currentTarget) const path = this.getPath(event.currentTarget)
@@ -180,8 +187,9 @@ export class AppPersonnageAleatoire extends FormApplication {
const variation = Math.floor((caracTaille.poidsMax - caracTaille.poidsMin + base / 5) / 2) const variation = Math.floor((caracTaille.poidsMax - caracTaille.poidsMin + base / 5) / 2)
const total = await RdDDice.rollTotal(`2d${variation} + ${base}`) const total = await RdDDice.rollTotal(`2d${variation} + ${base}`)
const cm = total % 100 const cm = total % 100
const dm = cm < 10 ? '0' : ''
const m = (total - cm) / 100 const m = (total - cm) / 100
return `${m}m${cm}` return `${m}m${dm}${cm}`
} }

View File

@@ -106,6 +106,25 @@ export class ChatUtility {
return await ChatMessage.create(messageData) return await ChatMessage.create(messageData)
} }
static tellToUser(message) {
ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id] });
}
static tellToGM(message) {
ChatMessage.create({
user: game.user.id,
content: message,
whisper: ChatUtility.getGMs()
});
}
static tellToUserAndGM(message) {
ChatMessage.create({
user: game.user.id,
content: message,
whisper: ChatUtility.getUserAndGMs()
})
}
static getOwners(document) { static getOwners(document) {
return document ? game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) : [game.user] return document ? game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) : [game.user]
} }
@@ -191,7 +210,7 @@ export class ChatUtility {
const timestamp = new RdDTimestamp(rddTimestamp); const timestamp = new RdDTimestamp(rddTimestamp);
const timestampData = timestamp.toCalendrier(); const timestampData = timestamp.toCalendrier();
const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData); const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData);
$(html).find('header.message-header .message-sender').after(dateHeure) $(html).find('header.message-header .message-timestamp').after(dateHeure)
} }
} }

View File

@@ -13,53 +13,65 @@ export const renderTemplate = foundry.applications.handlebars.renderTemplate
export const RDD_CONFIG = { export const RDD_CONFIG = {
niveauEthylisme: [ niveauEthylisme: [
{ value: "1", label: "Aucun" }, { value: '1', label: 'Aucun' },
{ value: "0", label: "Eméché (0)" }, { value: '0', label: 'Eméché (0)' },
{ value: "-1", label: "Gris (-1)" }, { value: '-1', label: 'Gris (-1)' },
{ value: "-2", label: "Pinté (-2)" }, { value: '-2', label: 'Pinté (-2)' },
{ value: "-3", label: "Pas Frais (-3)" }, { value: '-3', label: 'Pas Frais (-3)' },
{ value: "-4", label: "Ivre (-4)" }, { value: '-4', label: 'Ivre (-4)' },
{ value: "-5", label: "Bu (-5)" }, { value: '-5', label: 'Bu (-5)' },
{ value: "-6", label: "Complètement fait (-6)" }, { value: '-6', label: 'Complètement fait (-6)' },
{ value: "-7", label: "Ivre mort (-7)" } { value: '-7', label: 'Ivre mort (-7)' }
], ],
categorieEntite: { categorieEntite: {
"cauchemar": "Cauchemar", 'cauchemar': 'Cauchemar',
"reve": "Rêve" 'reve': 'Rêve'
}, },
typeEntite: { typeEntite: {
"incarne": "Incarnée", [ENTITE_INCARNE]: 'Incarnée',
"nonincarne": "Non Incarnée", [ENTITE_NONINCARNE]: 'Non Incarnée',
"blurette": "Blurette" [ENTITE_BLURETTE]: 'Blurette'
}, },
heuresRdD: [ heuresRdD: [
{ value: "vaisseau", label: "Vaisseau", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd01.webp" }, { value: 'vaisseau', label: 'Vaisseau', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd01.webp' },
{ value: "sirene", label: "Sirène", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd02.webp" }, { value: 'sirene', label: 'Sirène', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd02.webp' },
{ value: "faucon", label: "Faucon", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd03.webp" }, { value: 'faucon', label: 'Faucon', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd03.webp' },
{ value: "couronne", label: "Couronne", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd04.webp" }, { value: 'couronne', label: 'Couronne', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd04.webp' },
{ value: "dragon", label: "Dragon", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd05.webp" }, { value: 'dragon', label: 'Dragon', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd05.webp' },
{ value: "epees", label: "Epées", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd06.webp" }, { value: 'epees', label: 'Epées', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd06.webp' },
{ value: "lyre", label: "Lyre", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd07.webp" }, { value: 'lyre', label: 'Lyre', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd07.webp' },
{ value: "serpent", label: "Serpent", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd08.webp" }, { value: 'serpent', label: 'Serpent', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd08.webp' },
{ value: "poissonacrobate", label: "Poisson Acrobate", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd09.webp" }, { value: 'poissonacrobate', label: 'Poisson Acrobate', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd09.webp' },
{ value: "araignee", label: "Araignée", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd10.webp" }, { value: 'araignee', label: 'Araignée', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd10.webp' },
{ value: "roseau", label: "Roseau", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd11.webp" }, { value: 'roseau', label: 'Roseau', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd11.webp' },
{ value: "chateaudormant", label: "Chateau Dormant", img: "systems/foundryvtt-reve-de-dragon/icons/heures/hd12.webp" } { value: 'chateaudormant', label: 'Chateau Dormant', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd12.webp' }
], ],
raretes: [ raretes: [
{ value: "Commune", label: "Commune" }, { value: 'Commune', label: 'Commune' },
{ value: "Frequente", label: "Fréquente" }, { value: 'Frequente', label: 'Fréquente' },
{ value: "Rare", label: "Rare" }, { value: 'Rare', label: 'Rare' },
{ value: "Rarissime", label: "Rarissime" } { value: 'Rarissime', label: 'Rarissime' }
], ],
particuliere: { particuliere: {
force: { key: 'force', descr: 'en force', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-force.svg'}, force: { key: 'force', descr: 'en force', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-force.svg' },
finesse: { key: 'finesse', descr: 'en finesse', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-finesse.svg'}, finesse: { key: 'finesse', descr: 'en finesse', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-finesse.svg' },
rapidite: { key: 'finesse', descr: 'en rapidité', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-rapidite.svg'}, rapidite: { key: 'rapidite', descr: 'en rapidité', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-rapidite.svg' },
},
icons: {
armesDisparates: 'systems/foundryvtt-reve-de-dragon/assets/actions/armes-disparates.svg',
demiReve: 'systems/foundryvtt-reve-de-dragon/assets/actions/sort.svg',
empoignade: 'systems/foundryvtt-reve-de-dragon/assets/actions/empoignade.svg',
forceWeak: 'systems/foundryvtt-reve-de-dragon/assets/actions/weak.svg',
surenc: 'systems/foundryvtt-reve-de-dragon/assets/actions/surenc.svg',
},
encaissement: {
mortel: 'mortel',
nonmortel: 'non-mortel',
entiteincarnee: 'entiteincarnee',
empoignade: 'empoignade'
} }
} }
export const ACTOR_TYPES = { export const ACTOR_TYPES = {
personnage: 'personnage', personnage: 'personnage',
creature: 'creature', creature: 'creature',

View File

@@ -20,11 +20,11 @@ export class RdDInitiative {
return "1d6" + (base >= 0 ? "+" : "") + base return "1d6" + (base >= 0 ? "+" : "") + base
} }
static ajustementInitiative(caracValue, niveau, bonus) { static ajustementInitiative(caracValue, niveau, bonus = 0) {
return niveau + Math.floor(caracValue / 2) + bonus return niveau + Math.floor(caracValue / 2) + bonus
} }
static formule(phase, carac, niveau, bonusMalus) { static formule(phase, carac, niveau, bonusMalus = 0) {
const ajustement = RdDInitiative.ajustementInitiative(carac, niveau, bonusMalus) const ajustement = RdDInitiative.ajustementInitiative(carac, niveau, bonusMalus)
return { phase, ajustement } return { phase, ajustement }
} }
@@ -58,6 +58,7 @@ export class RdDInitiative {
return { return {
roll: roll, roll: roll,
value: value, value: value,
rang: formule.phase.rang,
init: formule.phase.rang + value / 100, init: formule.phase.rang + value / 100,
label: formule.phase.label label: formule.phase.label
} }

View File

@@ -1,7 +1,8 @@
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { RdDInitiative } from "./initiative.mjs";
import { RdDItem } from "./item.js"; import { RdDItem } from "./item.js";
import { CATEGORIES_COMPETENCES, SANS_COMPETENCE } from "./item/base-items.js"; import { CATEGORIES_COMPETENCE_COMBAT, CATEGORIES_COMPETENCES, SANS_COMPETENCE } from "./item/base-items.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
const competenceTroncs = [["Esquive", "Dague", "Corps à corps"], const competenceTroncs = [["Esquive", "Dague", "Corps à corps"],
@@ -46,6 +47,30 @@ export class RdDItemCompetence extends RdDItem {
static get defaultIcon() { return "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp" } static get defaultIcon() { return "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp" }
isNiveauBase() {
return this.system.niveau == this.system.base && this.system.xp == 0
}
getBaseInit() {
const carac = this.getInitCarac()
if (carac == undefined) {
return undefined
}
return RdDInitiative.ajustementInitiative(carac.value, this.system.niveau)
}
getInitCarac() {
if (!this.actor) {
return undefined
}
switch (this.system.categorie) {
case CATEGORIES_COMPETENCES.melee.key: return this.actor.system.carac.melee
case CATEGORIES_COMPETENCES.tir.key: return this.actor.system.carac.tir
case CATEGORIES_COMPETENCES.lancer.key: return this.actor.system.carac.lancer
case CATEGORIES_COMPETENCES.draconic.key: return this.actor.system.carac.reve
}
return undefined
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static getLabelCategorie(category) { static getLabelCategorie(category) {
return CATEGORIES_COMPETENCES[category].label; return CATEGORIES_COMPETENCES[category].label;

View File

@@ -32,6 +32,7 @@ export class RdDItemCompetenceCreature extends RdDItem {
initiative: initative, initiative: initative,
mortalite: this.system.mortalite, mortalite: this.system.mortalite,
dommages: this.system.dommages, dommages: this.system.dommages,
forceRequise: 0,
equipe: true, equipe: true,
resistance: 100, resistance: 100,
penetration: 0, penetration: 0,
@@ -43,7 +44,8 @@ export class RdDItemCompetenceCreature extends RdDItem {
carac: { key: this.name, value: this.system.carac_value }, carac: { key: this.name, value: this.system.carac_value },
equipe: true, equipe: true,
mortalite: this.system.mortalite, mortalite: this.system.mortalite,
dmg: this.system.dommages, dommages: this.system.dommages,
//dmg: this.system.dommages,
initiative: initative initiative: initative
}; };
return attaque return attaque

View File

@@ -260,7 +260,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
_updateObject(event, formData) { async _updateObject(event, formData) {
switch (this.item.type) { switch (this.item.type) {
case ITEM_TYPES.sort: case ITEM_TYPES.sort:
formData['system.bonuscase'] = RdDItemSort.bonuscasesToString(RdDItemSheetV1._listCaseTmr( formData['system.bonuscase'] = RdDItemSort.bonuscasesToString(RdDItemSheetV1._listCaseTmr(
@@ -273,8 +273,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
formData['system.niveau'] = formData['system.niveau'] ?? formData['system.base'] formData['system.niveau'] = formData['system.niveau'] ?? formData['system.base']
break break
} }
return await super._updateObject(event, formData)
return this.item.update(formData)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@@ -62,7 +62,7 @@ export class RdDItemSort extends Item {
static diffReve(sort) { return RdDItemSort.toVar((sort.system.difficulte.match(/\-?(\d)+/) ? 'R' : 'R ') + sort.system.difficulte) } static diffReve(sort) { return RdDItemSort.toVar((sort.system.difficulte.match(/\-?(\d)+/) ? 'R' : 'R ') + sort.system.difficulte) }
static coutReve(sort) { return RdDItemSort.toVar((sort.system.ptreve.match(/(\d)+\+?/) ? 'r' : 'r ') + sort.system.ptreve) } static coutReve(sort) { return RdDItemSort.toVar((Number.isInteger(sort.system.ptreve || sort.system.ptreve.match(/(\d)+\+?/)) ? 'r' : 'r ') + sort.system.ptreve) }
static getDraconicsSort(competencesDraconic, sort) { static getDraconicsSort(competencesDraconic, sort) {
// se baser sur la voie du sort? // se baser sur la voie du sort?
switch (Grammar.toLowerCaseNoAccent(sort.name)) { switch (Grammar.toLowerCaseNoAccent(sort.name)) {
@@ -148,10 +148,17 @@ export class RdDItemSort extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static incrementBonusCase(actor, sort, coord) { static incrementBonusCase(actor, sort, coord) {
let bonuscase = RdDItemSort.calculBonuscase(sort, coord)
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]);
}
static calculBonuscase(sort, coord) {
if (TMRUtility.isFleuve(coord)) { if (TMRUtility.isFleuve(coord)) {
coord = FLEUVE_COORD; coord = FLEUVE_COORD
} }
let list = RdDItemSort.stringToBonuscases(sort.system.bonuscase); let list = RdDItemSort.stringToBonuscases(sort.system.bonuscase)
const existing = list.find(it => it.case == coord) const existing = list.find(it => it.case == coord)
const bonus = Number(existing?.bonus ?? 0) + 1 const bonus = Number(existing?.bonus ?? 0) + 1
if (existing) { if (existing) {
@@ -160,11 +167,9 @@ export class RdDItemSort extends Item {
else { else {
list.push({ case: coord, bonus: 1 }) list.push({ case: coord, bonus: 1 })
} }
return RdDItemSort.bonuscasesToString(list)
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': RdDItemSort.bonuscasesToString(list) }]);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getCaseBonus(sort, coord) { static getCaseBonus(sort, coord) {
const search = TMRUtility.isFleuve(coord) const search = TMRUtility.isFleuve(coord)
@@ -189,4 +194,22 @@ export class RdDItemSort extends Item {
.map(it => it.split(':')) .map(it => it.split(':'))
.map(it => { return { case: it[0], bonus: it[1] } }); .map(it => { return { case: it[0], bonus: it[1] } });
} }
static prepareSortEnReserve(sort, draconic, ptreve, coord) {
return {
type: ITEM_TYPES.sortreserve,
name: sort.name,
img: sort.img,
system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' }
};
}
static prepareSortAddLancement(sort, reveSort) {
const precedents = sort.system.lancements ?? []
const lancements = [...precedents, {
timestamp: game.system.rdd.calendrier.getTimestamp(),
reve: reveSort
}]
return lancements
}
} }

View File

@@ -1,4 +1,4 @@
import { ITEM_TYPES, renderTemplate } from "./constants.js"; import { ITEM_TYPES, RDD_CONFIG, renderTemplate } from "./constants.js";
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES, CATEGORIES_COMPETENCES_CREATURES } from "./item/base-items.js"; import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES, CATEGORIES_COMPETENCES_CREATURES } from "./item/base-items.js";
import { ITEM_ACTIONS, DEFAULT_ACTIONS, COMMON_ACTIONS } from "./item/item-actions.js"; import { ITEM_ACTIONS, DEFAULT_ACTIONS, COMMON_ACTIONS } from "./item/item-actions.js";
@@ -629,7 +629,7 @@ export class RdDItem extends Item {
_armeChatData() { _armeChatData() {
return [ return [
`<b>Compétence</b>: ${this.system.competence}`, `<b>Compétence</b>: ${this.system.competence}`,
`<b>Dommages</b>: ${this.system.dommages} ${this.system.mortalite == 'non-mortel' ? '(Non mortel)' : ''}`, `<b>Dommages</b>: ${this.system.dommages} ${this.system.mortalite == RDD_CONFIG.encaissement.nonmortel ? '(Non mortel)' : ''}`,
`<b>Force minimum</b>: ${this.system.force}`, `<b>Force minimum</b>: ${this.system.force}`,
`<b>Resistance</b>: ${this.system.resistance}`, `<b>Resistance</b>: ${this.system.resistance}`,
...this._inventaireTemplateChatData() ...this._inventaireTemplateChatData()

View File

@@ -1,4 +1,4 @@
import { ITEM_TYPES } from "../constants.js"; import { ITEM_TYPES, RDD_CONFIG } from "../constants.js";
import { RdDItem } from "../item.js"; import { RdDItem } from "../item.js";
import { BASE_CORPS_A_CORPS } from "./base-items.js"; import { BASE_CORPS_A_CORPS } from "./base-items.js";
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
@@ -27,10 +27,11 @@ export const ATTAQUE_TYPE = {
TIR: '(tir)', TIR: '(tir)',
LANCER: '(lancer)' LANCER: '(lancer)'
} }
export const ATTAQUE_TYPE_MELEE = [ATTAQUE_TYPE.UNE_MAIN, ATTAQUE_TYPE.DEUX_MAINS, ATTAQUE_TYPE.CORPS_A_CORPS]
export const CORPS_A_CORPS = 'Corps à corps' export const CORPS_A_CORPS = 'Corps à corps'
export const PUGILAT = 'pugilat' export const PUGILAT = 'pugilat'
export const EMPOIGNADE = 'empoignade' export const EMPOIGNADE = RDD_CONFIG.encaissement.empoignade
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDItemArme extends RdDItem { export class RdDItemArme extends RdDItem {
@@ -44,6 +45,16 @@ export class RdDItemArme extends RdDItem {
isParade() { return this.system.resistance > 0 && this.system.categorie_parade } isParade() { return this.system.resistance > 0 && this.system.categorie_parade }
isBouclier() { return RdDItemArme.getCategorieParade(this).includes('bouclier') } isBouclier() { return RdDItemArme.getCategorieParade(this).includes('bouclier') }
getCompetenceAction(main) {
switch (main) {
case ATTAQUE_TYPE.UNE_MAIN: return this.competence1Mains()
case ATTAQUE_TYPE.DEUX_MAINS: return this.competence2Mains()
case ATTAQUE_TYPE.LANCER: return this.system.lancer
case ATTAQUE_TYPE.TIR: return this.system.tir
default: return this.system.competence
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static valeurMain(valeurs, main) { static valeurMain(valeurs, main) {
valeurs = valeurs?.toString() ?? "" valeurs = valeurs?.toString() ?? ""
@@ -77,17 +88,26 @@ export class RdDItemArme extends RdDItem {
return arme.name return arme.name
case ITEM_TYPES.arme: case ITEM_TYPES.arme:
switch (maniement) { switch (maniement) {
case ATTAQUE_TYPE.COMPETENCE: return arme.system.competence; case ATTAQUE_TYPE.COMPETENCE: return arme.system.competence
case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains() case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains()
case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains() case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains()
case ATTAQUE_TYPE.TIR: case 'tir': return arme.system.tir case ATTAQUE_TYPE.TIR: case 'tir': return arme.system.tir
case ATTAQUE_TYPE.LANCER: case 'lancer': return arme.system.lancer; case ATTAQUE_TYPE.LANCER: case 'lancer': return arme.system.lancer
case ATTAQUE_TYPE.CORPS_A_CORPS: return CORPS_A_CORPS case ATTAQUE_TYPE.CORPS_A_CORPS: return CORPS_A_CORPS
} }
} }
return undefined return undefined
} }
getTypeAttaques() {
return [
...(this.system.unemain && this.system.competence && this.system.resistance > 0) ? [ATTAQUE_TYPE.UNE_MAIN] : [],
...(this.system.deuxmains && this.system.competence && this.system.resistance > 0) ? [ATTAQUE_TYPE.DEUX_MAINS] : [],
...(this.system.lancer && this.system.resistance > 0) ? [ATTAQUE_TYPE.LANCER] : [],
...(this.system.tir) ? [ATTAQUE_TYPE.TIR] : [],
]
}
static computeNiveauArmes(armes, competences) { static computeNiveauArmes(armes, competences) {
for (const arme of armes) { for (const arme of armes) {
arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences); arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
@@ -254,15 +274,23 @@ export class RdDItemArme extends RdDItem {
return this.system.resistance > 0 || (this.system.tir != '' && this.system.portee_courte > 0) return this.system.resistance > 0 || (this.system.tir != '' && this.system.portee_courte > 0)
} }
isEmpoignade() {
return this.system.mortalite == RDD_CONFIG.encaissement.empoignade
}
isUtilisableEmpoigne() {
return this.system.baseInit == 3 || this.system.baseInit == 4 || this.system.competence == "Dague"
}
static pugilat(actor) { static pugilat(actor) {
return RdDItemArme.$corpsACorps(actor, 'Pugilat', PUGILAT) return RdDItemArme.$corpsACorps(actor, 'Pugilat', PUGILAT)
} }
static empoignade(actor) { static empoignade(actor) {
return RdDItemArme.$corpsACorps(actor, 'Empoignade', EMPOIGNADE) return RdDItemArme.$corpsACorps(actor, 'Empoignade', RDD_CONFIG.encaissement.empoignade)
} }
static $corpsACorps(actor, name, cac, system) { static $corpsACorps(actor, name, cac) {
const competence = actor?.getCompetenceCorpsACorps() ?? BASE_CORPS_A_CORPS const competence = actor?.getCompetenceCorpsACorps() ?? BASE_CORPS_A_CORPS
const melee = actor ? actor.system.carac['melee'].value : 0 const melee = actor ? actor.system.carac['melee'].value : 0
return new RdDItemArme({ return new RdDItemArme({
@@ -277,10 +305,10 @@ export class RdDItemArme extends RdDItem {
force: 0, force: 0,
dommages: "0", dommages: "0",
dommagesReels: 0, dommagesReels: 0,
mortalite: cac == EMPOIGNADE ? EMPOIGNADE : 'non-mortel', mortalite: cac == RDD_CONFIG.encaissement.empoignade ? RDD_CONFIG.encaissement.empoignade : RDD_CONFIG.encaissement.nonmortel,
competence: CORPS_A_CORPS, competence: CORPS_A_CORPS,
resistance: 1, resistance: 1,
baseInit: cac == EMPOIGNADE ? 3 : 4, baseInit: cac == RDD_CONFIG.encaissement.empoignade ? 3 : 4,
cac: cac, cac: cac,
deuxmains: true, deuxmains: true,
categorie_parade: 'sans-armes' categorie_parade: 'sans-armes'

View File

@@ -14,27 +14,28 @@ export const SANS_COMPETENCE = {
description: "", description: "",
descriptionmj: "", descriptionmj: "",
defaut_carac: "", defaut_carac: "",
}, },
img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp" img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp"
} }
export const CATEGORIES_COMPETENCES = { export const CATEGORIES_COMPETENCES = {
"generale": { base: -4, label: "Générales" }, generale: { key: 'generale', base: -4, label: "Générales" },
"particuliere": { base: -8, label: "Particulières" }, particuliere: { key: 'particuliere', base: -8, label: "Particulières" },
"specialisee": { base: -11, label: "Spécialisées" }, specialisee: { key: 'specialisee', base: -11, label: "Spécialisées" },
"connaissance": { base: -11, label: "Connaissances" }, connaissance: { key: 'connaissance', base: -11, label: "Connaissances" },
"draconic": { base: -11, label: "Draconic" }, draconic: { key: 'draconic', base: -11, label: "Draconic" },
"melee": { base: -6, label: "Mêlée" }, melee: { key: 'melee', base: -6, label: "Mêlée" },
"tir": { base: -8, label: "Tir" }, tir: { key: 'tir', base: -8, label: "Tir" },
"lancer": { base: -8, label: "Lancer" } lancer: { key: 'lancer', base: -8, label: "Lancer" }
} }
export const CATEGORIES_COMPETENCE_COMBAT = [CATEGORIES_COMPETENCES.melee, CATEGORIES_COMPETENCES.tir, CATEGORIES_COMPETENCES.lancer].map(it => it.key)
export const CATEGORIES_COMPETENCES_CREATURES = { export const CATEGORIES_COMPETENCES_CREATURES = {
"generale": { base: 0, label: "Générale" }, generale: { key: 'generale', base: 0, label: "Générale" },
"naturelle": { base: 0, label: "Arme naturelle" }, naturelle: { key: 'naturelle', base: 0, label: "Arme naturelle" },
"melee": { base: 0, label: "Mêlée" }, melee: { key: 'melee', base: 0, label: "Mêlée" },
"parade": { base: 0, label: "Parade" }, parade: { key: 'parade', base: 0, label: "Parade" },
"tir": { base: 0, label: "Tir" }, tir: { key: 'tir', base: 0, label: "Tir" },
"lancer": { base: 0, label: "Lancer" }, lancer: { key: 'lancer', base: 0, label: "Lancer" },
"possession": { base: 0, label: "Possession" }, possession: { key: 'possession', base: 0, label: "Possession" },
} }

View File

@@ -71,21 +71,25 @@ export class RdDItemBlessure extends RdDItem {
return 0 return 0
} }
static async createBlessure(actor, gravite, localisation = '', attackerToken) { static async createBlessure(actor, gravite, localisation = '', attackerToken = undefined) {
const definition = RdDItemBlessure.getDefinition(gravite) const blessure = RdDItemBlessure.prepareBlessure(gravite, localisation, attackerToken);
const blessure = { const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
return blessures[0]
}
static prepareBlessure(gravite, localisation, attackerToken) {
const definition = RdDItemBlessure.getDefinition(gravite);
return {
name: definition.label, name: definition.label,
type: 'blessure', type: 'blessure',
img: definition.icon, img: definition.icon,
system: { system: {
gravite: gravite, gravite: gravite,
difficulte: - gravite, difficulte: -gravite,
localisation: localisation, localisation: localisation,
origine: attackerToken?.name ?? "" origine: attackerToken?.name ?? ""
} }
} }
const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
return blessures[0]
} }
static async createTacheSoinBlessure(actor, gravite) { static async createTacheSoinBlessure(actor, gravite) {

View File

@@ -12,12 +12,13 @@ const _SPACEHOLDER = { placeholder: true }
const _VENDRE = { const _VENDRE = {
code: 'item-vendre', label: 'Vendre ou donner', icon: it => 'fa-solid fa-comments-dollar', code: 'item-vendre', label: 'Vendre ou donner', icon: it => 'fa-solid fa-comments-dollar',
filter: it => Misc.toInt(it.system.quantite) > 0, filter: it => Misc.toInt(it.system.quantite) > 0 || it.parent?.type == ACTOR_TYPES.commerce,
action: (item, actor) => item.proposerVente() action: (item, actor) => item.proposerVente()
} }
const _ACHETER = { const _ACHETER = {
code: 'item-acheter', label: 'Acheter', icon: it => 'fa-regular fa-coins', code: 'item-acheter', label: 'Acheter', icon: it => 'fa-regular fa-coins',
filter: it => Misc.toInt(it.system.quantite) > 0 && it.parent?.type == ACTOR_TYPES.commerce, filter: it => it.parent?.type == ACTOR_TYPES.commerce,
allowLimited: true,
action: (item, actor) => actor.vente(item) action: (item, actor) => actor.vente(item)
} }
const _MONTRER = { const _MONTRER = {

View File

@@ -6,8 +6,8 @@ const tableEffets = [
{ code: "passeur", resultat: "succes", description: "Déplacer le demi-rêve à (force) cases", method: EffetsRencontre.passeur}, { code: "passeur", resultat: "succes", description: "Déplacer le demi-rêve à (force) cases", method: EffetsRencontre.passeur},
{ code: "reve+f", resultat: "succes", description: "Gain de (force) points de rêve" , method: EffetsRencontre.reve_plus_force}, { code: "reve+f", resultat: "succes", description: "Gain de (force) points de rêve" , method: EffetsRencontre.reve_plus_force},
{ code: "teleport", resultat: "succes", description: "Déplacer le demi-rêve (même type)", method: EffetsRencontre.teleportation_typecase }, { code: "teleport", resultat: "succes", description: "Déplacer le demi-rêve (même type)", method: EffetsRencontre.teleportation_typecase },
{ code: "part+tete", resultat: "succes", description: "Tête de dragon sur réussite particulière", method: EffetsRencontre.rdd_part_tete }, { code: "part+tete", resultat: "succes", description: "Tête de dragon sur particulière", method: EffetsRencontre.rdd_part_tete },
{ code: "part+xp", resultat: "succes", description: "Expérience sur réussite particulière", method: EffetsRencontre.experience_particuliere }, { code: "part+xp", resultat: "succes", description: "Expérience sur particulière", method: EffetsRencontre.experience_particuliere },
{ code: "seuil", resultat: "succes", description: "Récupération de seuil de rêve", method: EffetsRencontre.regain_seuil }, { code: "seuil", resultat: "succes", description: "Récupération de seuil de rêve", method: EffetsRencontre.regain_seuil },
{ code: "reve-1", resultat: "echec", description: "Perte de 1 point de rêve", method: EffetsRencontre.reve_moins_1 }, { code: "reve-1", resultat: "echec", description: "Perte de 1 point de rêve", method: EffetsRencontre.reve_moins_1 },
@@ -19,7 +19,7 @@ const tableEffets = [
{ code: "aleatoire", resultat: "echec", description: "Déplacement aléatoire", method: EffetsRencontre.deplacement_aleatoire }, { code: "aleatoire", resultat: "echec", description: "Déplacement aléatoire", method: EffetsRencontre.deplacement_aleatoire },
{ code: "sort-aleatoire", resultat: "echec", description: "Déclenche un sort en réserve aléatoire", method: EffetsRencontre.sort_aleatoire }, { code: "sort-aleatoire", resultat: "echec", description: "Déclenche un sort en réserve aléatoire", method: EffetsRencontre.sort_aleatoire },
{ code: "rompu", resultat: "echec", description: "Demi-rêve interrompu", method: EffetsRencontre.demireve_rompu }, { code: "rompu", resultat: "echec", description: "Demi-rêve interrompu", method: EffetsRencontre.demireve_rompu },
{ code: "echec-queue", resultat: "echec", description: "Queue(s) de dragon sur échec", method: EffetsRencontre.rdd_echec_queue }, { code: "echec-queue", resultat: "echec", description: "Queue(s) de dragon", method: EffetsRencontre.rdd_echec_queue },
{ code: "reve+1", resultat: "succes", description: "Gain de 1 point de rêve", method: EffetsRencontre.reve_plus_1 }, { code: "reve+1", resultat: "succes", description: "Gain de 1 point de rêve", method: EffetsRencontre.reve_plus_1 },
{ code: "vie-f", resultat: "echec", description: "Perte de (force) points de vie", method: EffetsRencontre.vie_moins_force }, { code: "vie-f", resultat: "echec", description: "Perte de (force) points de vie", method: EffetsRencontre.vie_moins_force },

View File

@@ -1,3 +1,4 @@
import { RDD_CONFIG } from "./constants.js";
import { RdDItemArme } from "./item/arme.js"; import { RdDItemArme } from "./item/arme.js";
import { RdDPossession } from "./rdd-possession.js"; import { RdDPossession } from "./rdd-possession.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
@@ -35,7 +36,7 @@ export class RdDBonus {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static dmg(rollData, actor, isEntiteIncarnee = false) { static dmg(rollData, actor) {
const diff = rollData.diffLibre; const diff = rollData.diffLibre;
const dmgArme = RdDBonus.dmgArme(rollData.arme, rollData.arme?.system.dommagesReels) const dmgArme = RdDBonus.dmgArme(rollData.arme, rollData.arme?.system.dommagesReels)
const forceRequise = rollData.arme ? RdDItemArme.valeurMain(rollData.arme.system.force ?? 0, RdDItemArme.getMainAttaque(rollData.competence)) : 0 const forceRequise = rollData.arme ? RdDItemArme.valeurMain(rollData.arme.system.force ?? 0, RdDItemArme.getMainAttaque(rollData.competence)) : 0
@@ -47,19 +48,19 @@ export class RdDBonus {
penetration: RdDBonus._peneration(rollData), penetration: RdDBonus._peneration(rollData),
dmgTactique: RdDBonus.dmgBonus(rollData.tactique), dmgTactique: RdDBonus.dmgBonus(rollData.tactique),
dmgParticuliere: RdDBonus._dmgParticuliere(rollData), dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris.used), dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris?.used),
mortalite: RdDBonus._calculMortalite(rollData, isEntiteIncarnee), mortalite: RdDBonus.mortalite(rollData.dmg?.mortalite, rollData.arme?.system.mortalite),
dmgActor: RdDBonus.bonusDmg(actor, rollData.selectedCarac?.label.toLowerCase(), dmgArme), dmgActor: RdDBonus.bonusDmg(actor, rollData.selectedCarac?.label.toLowerCase(), dmgArme),
dmgForceInsuffisante: Math.min(0, actor.getForce() - forceRequise) dmgForceInsuffisante: Math.min(0, actor.getForce() - forceRequise)
} }
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere + dmg.dmgForceInsuffisante dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere + dmg.dmgForceInsuffisante
return dmg; return dmg
} }
static dmgRollV2(rollData, attaque) { static dmgRollV2(rollData, attaque) {
const actor = rollData.active.actor const actor = rollData.active.actor
const arme = attaque.arme const arme = attaque.arme
const dmgArme = RdDBonus.dmgArme(arme, attaque.dommagesArme) const dmgArme = RdDBonus.dmgArme(arme, attaque.dommages)
const dmg = { const dmg = {
total: 0, total: 0,
dmgArme: dmgArme, dmgArme: dmgArme,
@@ -68,11 +69,12 @@ export class RdDBonus {
dmgTactique: attaque.tactique?.dmg ?? 0, dmgTactique: attaque.tactique?.dmg ?? 0,
dmgParticuliere: RdDBonus._dmgParticuliere(rollData), dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
dmgSurprise: rollData.opponent?.surprise?.dmg ?? 0, dmgSurprise: rollData.opponent?.surprise?.dmg ?? 0,
mortalite: RdDBonus.mortalite(attaque.dmg?.mortalite, arme?.system.mortalite, rollData.opponent?.actor?.isEntite()), mortalite: RdDBonus.mortalite(attaque.dmg?.mortalite, arme?.system.mortalite),
dmgActor: RdDBonus.bonusDmg(actor, attaque.carac.key, dmgArme, attaque.forceRequise), dmgActor: RdDBonus.bonusDmg(actor, attaque.carac.key, dmgArme, attaque.forceRequise),
dmgForceInsuffisante: Math.min(0, actor.getForce() - attaque.forceRequise), dmgForceInsuffisante: Math.min(0, actor.getForce() - (attaque.forceRequise ?? 0)),
dmgDiffLibre: ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(attaque.diff ?? 0) : 0 dmgDiffLibre: ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(attaque.diff ?? 0) : 0
} }
dmg.isEmpoignade = dmg.mortalite == RDD_CONFIG.encaissement.empoignade
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere + dmg.dmgForceInsuffisante + dmg.dmgDiffLibre dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere + dmg.dmgForceInsuffisante + dmg.dmgDiffLibre
return dmg return dmg
} }
@@ -93,21 +95,14 @@ export class RdDBonus {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _calculMortalite(rollData, isEntiteIncarnee) { static mortalite(mortaliteSelect, mortaliteArme) {
return RdDBonus.mortalite(rollData.dmg?.mortalite, rollData.arme?.system.mortalite, isEntiteIncarnee) return mortaliteSelect ?? mortaliteArme ?? RDD_CONFIG.encaissement.mortel
}
static mortalite(mortaliteSelect, mortaliteArme, isEntiteIncarnee) {
return isEntiteIncarnee ? "entiteincarnee"
: mortaliteSelect
?? mortaliteArme
?? "mortel";
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static dmgArme(arme, dommagesMain) { static dmgArme(arme, dommages) {
if (arme) { if (arme) {
let dmgBase = dommagesMain ?? Number(arme.system.dommages ?? 0); let dmgBase = dommages ?? Number(arme.system.dommages ?? 0);
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278) //Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
return dmgBase + Math.min(dmgBase, arme.system.magique ? arme.system.ecaille_efficacite : 0); return dmgBase + Math.min(dmgBase, arme.system.magique ? arme.system.ecaille_efficacite : 0);
} }

View File

@@ -1,5 +1,5 @@
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js";
import { ENTITE_BLURETTE, HIDE_DICE, renderTemplate, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; import { HIDE_DICE, renderTemplate, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js"; import { RdDBonus } from "./rdd-bonus.js";
@@ -15,9 +15,8 @@ import { RdDItemCompetence } from "./item-competence.js";
import { MAP_PHASE, RdDInitiative } from "./initiative.mjs"; import { MAP_PHASE, RdDInitiative } from "./initiative.mjs";
import RollDialog from "./roll/roll-dialog.mjs"; import RollDialog from "./roll/roll-dialog.mjs";
import { PART_DEFENSE } from "./roll/roll-part-defense.mjs"; import { PART_DEFENSE } from "./roll/roll-part-defense.mjs";
import { RollDialogAdapter } from "./roll/roll-dialog-adapter.mjs";
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs"; import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2, ROLL_DIALOG_V2_TEST } from "./settings/options-avancees.js"; import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs"; import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs";
import { RollBasicParts } from "./roll/roll-basic-parts.mjs"; import { RollBasicParts } from "./roll/roll-basic-parts.mjs";
@@ -57,6 +56,12 @@ export class RdDCombatManager extends Combat {
} }
} }
static getCombatant(actorId, tokenId) {
return game.combat?.combatants.find(it => it.actor.id == actorId &&
it.token.id == tokenId
)
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async nextRound() { async nextRound() {
await this.finDeRound(); await this.finDeRound();
@@ -380,7 +385,7 @@ export class RdDCombat {
if (defenderToken && Misc.isFirstConnectedGM()) { if (defenderToken && Misc.isFirstConnectedGM()) {
const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id) const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id)
rddCombat?.removeChatMessageActionsPasseArme(msg.paramChatDefense.attackerRoll.passeArme) rddCombat?.removeChatMessageActionsPasseArme(msg.paramChatDefense.attackerRoll.passeArme)
if (msg.defenderRoll.ids) {/* TODO: delete roll V1 */ if (msg.defenderRoll.v2) {/* TODO: delete roll V1 */
RollDialog.loadRollData(msg.paramChatDefense) RollDialog.loadRollData(msg.paramChatDefense)
rddCombat?._chatMessageDefenseV2(msg.paramChatDefense) rddCombat?._chatMessageDefenseV2(msg.paramChatDefense)
} else { } else {
@@ -403,7 +408,6 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
static registerChatCallbacks(html) { static registerChatCallbacks(html) {
for (let button of [ for (let button of [
'.button-defense',
'.button-parade', '.button-parade',
'.button-esquive', '.button-esquive',
'.button-encaisser', '.button-encaisser',
@@ -475,8 +479,6 @@ export class RdDCombat {
switch (button) { switch (button) {
case '.particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value); case '.particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value);
case '.button-defense': return this.defenseV2(attackerRoll);
case '.button-parade': return this.parade(attackerRoll, armeParadeId); case '.button-parade': return this.parade(attackerRoll, armeParadeId);
case '.button-esquive': return this.esquive(attackerRoll, compId, competence); case '.button-esquive': return this.esquive(attackerRoll, compId, competence);
case '.button-encaisser': return this.encaisser(attackerRoll, defenderRoll); case '.button-encaisser': return this.encaisser(attackerRoll, defenderRoll);
@@ -561,7 +563,7 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isEchecTotal(rollData) { static isEchecTotal(rollData) {
if (rollData.ids /* roll V2*/) { if (rollData.v2 /* roll V2*/) {
// TODO: en cas de demi-surprise à l'attaque, tout échec est un echec total. // TODO: en cas de demi-surprise à l'attaque, tout échec est un echec total.
// TODO: en cas de demi-surprise en défense, pas de changement à la règle de base // TODO: en cas de demi-surprise en défense, pas de changement à la règle de base
return rollData.rolled.isETotal return rollData.rolled.isETotal
@@ -575,7 +577,7 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isParticuliere(rollData) { static isParticuliere(rollData) {
if (rollData.ids /* roll V2*/) { if (rollData.v2 /* roll V2*/) {
return rollData.rolled.isPart return rollData.rolled.isPart
} }
if (rollData.attackerRoll || !rollData.ajustements.surprise.used) { if (rollData.attackerRoll || !rollData.ajustements.surprise.used) {
@@ -586,7 +588,7 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isReussite(rollData) { static isReussite(rollData) {
if (rollData.ids /* roll V2*/) { if (rollData.v2 /* roll V2*/) {
return rollData.rolled.isSuccess return rollData.rolled.isSuccess
} }
if (!rollData.ajustements.surprise.used) { if (!rollData.ajustements.surprise.used) {
@@ -602,7 +604,7 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
async proposerAjustementTirLancer(rollData) { async proposerAjustementTirLancer(rollData) {
if (['tir', 'lancer'].includes(rollData.competence.system.categorie)) { if (['tir', 'lancer'].includes(rollData.competence.system.categorie)) {
if (this.defender.isEntite([ENTITE_BLURETTE])) { if (this.defender.isEntiteBlurette()) {
ChatMessage.create({ ChatMessage.create({
content: `<strong>La cible est une blurette, l'arme à distance sera perdue dans le blurêve`, content: `<strong>La cible est une blurette, l'arme à distance sera perdue dans le blurêve`,
whisper: ChatUtility.getGMs() whisper: ChatUtility.getGMs()
@@ -686,11 +688,7 @@ export class RdDCombat {
async doRollAttaque(rollData, callbacks = []) { async doRollAttaque(rollData, callbacks = []) {
// TODO V2 await this.proposerAjustementTirLancer(rollData) // TODO V2 await this.proposerAjustementTirLancer(rollData)
await RollDialog.create(rollData, { await RollDialog.create(rollData, {
onRollDone: (dialog) => { onRollDone: RollDialog.onRollDoneClose,
if (!OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST))
dialog.close()
},
customChatMessage: true,
callbacks: [ callbacks: [
async (roll) => await this.onAttaqueV2(roll), async (roll) => await this.onAttaqueV2(roll),
...callbacks ...callbacks
@@ -730,26 +728,24 @@ export class RdDCombat {
async _chatMessageDefenseV2(paramDemandeDefense) { async _chatMessageDefenseV2(paramDemandeDefense) {
const attackerRoll = paramDemandeDefense.attackerRoll; const attackerRoll = paramDemandeDefense.attackerRoll;
RollBasicParts.loadSurprises(attackerRoll) RollBasicParts.loadSurprises(attackerRoll)
attackerRoll.passeArme = attackerRoll.passeArme ?? foundry.utils.randomID(16)
attackerRoll.dmg = RdDBonus.dmgRollV2(attackerRoll, attackerRoll.current.attaque) attackerRoll.dmg = RdDBonus.dmgRollV2(attackerRoll, attackerRoll.current.attaque)
// attackerRoll.current.attaque.dmg = attackerRoll.dmg
// attaque.dmg = attackerRoll.current.attaque.dmg const defenseData = RollBasicParts.prepareDefense(attackerRoll)
const attaque = RollDialog.saveParts(attackerRoll)
const defense = {
attackerRoll: attaque,
ids: RollBasicParts.reverseIds(attaque),
passeArme: attaque.passeArme ?? foundry.utils.randomID(16)
}
const choixDefense = await ChatMessage.create({ const choixDefense = await ChatMessage.create({
// message privé: du défenseur à lui même (et aux GMs) // message privé: du défenseur à lui même (et aux GMs)
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)), speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
alias: this.attacker?.getAlias(), alias: this.attacker?.getAlias(),
whisper: ChatUtility.getOwners(this.defender), whisper: ChatUtility.getOwners(this.defender),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', attackerRoll) content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', defenseData)
}); });
// flag pour garder les jets d'attaque/defense // flag pour garder les jets d'attaque/defense
ChatUtility.setMessageData(choixDefense, 'rollData', defense) ChatUtility.setMessageData(choixDefense, 'demande-defense', true)
ChatUtility.setMessageData(choixDefense, 'rollData', {
ids: defenseData.ids,
attackerRoll: RollDialog.saveParts(attackerRoll),
passeArme: defenseData.passeArme
})
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -804,7 +800,7 @@ export class RdDCombat {
essais: {} essais: {}
}; };
if (this.attacker.isCreatureEntite()) { if (this.attacker.isCreatureOuEntite()) {
MappingCreatureArme.setRollDataCreature(rollData); MappingCreatureArme.setRollDataCreature(rollData);
} }
else if (arme) { else if (arme) {
@@ -873,7 +869,7 @@ export class RdDCombat {
async _onAttaqueNormale(attackerRoll) { async _onAttaqueNormale(attackerRoll) {
console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll); console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll);
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite()); attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker);
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} } let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
attackerRoll.show = { attackerRoll.show = {
cible: this.defender?.getAlias() ?? 'la cible', cible: this.defender?.getAlias() ?? 'la cible',
@@ -892,7 +888,10 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
isPossession(attackerRoll) { isPossession(attackerRoll) {
return attackerRoll.selectedCarac.label.toLowerCase() == 'possession'; const carac = attackerRoll.v2
? attackerRoll.current.carac?.label
: attackerRoll.selectedCarac.label
return carac?.toLowerCase() == 'possession';
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -1056,7 +1055,7 @@ export class RdDCombat {
dialog.render(true); dialog.render(true);
} }
async defenseV2(attackerRoll) { async defenseV2(attackerRoll, callbacks = []) {
// this._prepareParade(attackerRoll, arme, competence); // this._prepareParade(attackerRoll, arme, competence);
RollDialog.loadRollData(attackerRoll) RollDialog.loadRollData(attackerRoll)
await this.doRollDefense({ await this.doRollDefense({
@@ -1067,15 +1066,14 @@ export class RdDCombat {
opponentId: this.attackerId, opponentId: this.attackerId,
}, },
type: { allowed: [ROLL_TYPE_DEFENSE], current: ROLL_TYPE_DEFENSE }, type: { allowed: [ROLL_TYPE_DEFENSE], current: ROLL_TYPE_DEFENSE },
attackerRoll: RollDialogAdapter.mapActionAttaque(attackerRoll), attackerRoll: attackerRoll,
passeArme: attackerRoll.passeArme, passeArme: attackerRoll.passeArme,
}) }, callbacks)
} }
async doRollDefense(rollData, callbacks = []) { async doRollDefense(rollData, callbacks = []) {
await RollDialog.create(rollData, { await RollDialog.create(rollData, {
onRollDone: RollDialog.onRollDoneClose, onRollDone: RollDialog.onRollDoneClose,
customChatMessage: true,
callbacks: [ callbacks: [
async (roll) => { async (roll) => {
this.removeChatMessageActionsPasseArme(roll.passeArme); this.removeChatMessageActionsPasseArme(roll.passeArme);
@@ -1109,7 +1107,7 @@ export class RdDCombat {
show: {} show: {}
}; };
if (this.defender.isCreatureEntite()) { if (this.defender.isCreatureOuEntite()) {
MappingCreatureArme.setRollDataCreature(defenderRoll); MappingCreatureArme.setRollDataCreature(defenderRoll);
} }
@@ -1236,7 +1234,7 @@ export class RdDCombat {
show: {} show: {}
}; };
if (this.defender.isCreatureEntite()) { if (this.defender.isCreatureOuEntite()) {
MappingCreatureArme.setRollDataCreature(rollData); MappingCreatureArme.setRollDataCreature(rollData);
} }
return rollData; return rollData;

View File

@@ -461,12 +461,7 @@ export class RdDCommands {
async supprimerSignesDraconiquesEphemeres() { async supprimerSignesDraconiquesEphemeres() {
if (game.user.isGM) { if (game.user.isGM) {
game.actors.forEach(actor => { game.actors.forEach(actor => actor.supprimerSignesDraconiques(it => it.system.ephemere))
const ephemeres = actor.items.filter(item => item.type = 'signedraconique' && item.system.ephemere);
if (ephemeres.length > 0) {
actor.deleteEmbeddedDocuments("Item", ephemeres.map(item => item.id));
}
});
} }
else { else {
ui.notifications.warn("Seul le MJ est autorisé à utiliser la commande /signe"); ui.notifications.warn("Seul le MJ est autorisé à utiliser la commande /signe");

View File

@@ -4,6 +4,8 @@ import { ChatUtility } from "./chat-utility.js";
import { RdDRollResult } from "./rdd-roll-result.js"; import { RdDRollResult } from "./rdd-roll-result.js";
import { RdDRoll } from "./rdd-roll.js"; import { RdDRoll } from "./rdd-roll.js";
import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs"; import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs";
import { MAP_PHASE } from "./initiative.mjs";
import { RdDCombatManager } from "./rdd-combat.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDEmpoignade { export class RdDEmpoignade {
@@ -12,6 +14,49 @@ export class RdDEmpoignade {
static init() { static init() {
} }
/* -------------------------------------------- */
static isCombatantEmpoignade(actorId, tokenId) {
const combatant = RdDCombatManager.getCombatant(actorId, tokenId)
return MAP_PHASE.empoignade.rang == combatant?.system.init.rang
}
static async ajustementEmpoignade(attacker, defender, adjust = 1) {
const empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
const empId = empoignade?.system.empoignadeid ?? foundry.utils.randomID(16)
if (empoignade) {
if (empoignade.system.empoigneurid == defender.id) {
adjust = - adjust
}
empoignade.system.pointsemp += adjust
await RdDEmpoignade.$updateEtatEmpoignade(empoignade, attacker, defender)
}
else {
await RdDEmpoignade.$createEtatEmpoignade({
name: `Empoignade de ${attacker.name} sur ${defender.name}`,
type: ITEM_TYPES.empoignade,
system: {
description: "",
empoignadeid: empId,
empoigneurid: attacker.id,
empoigneid: defender.id,
pointsemp: adjust,
empoigneurname: attacker.name,
empoignename: defender.name
}
}, attacker, defender)
}
const result = RdDEmpoignade.getEmpoignadeById(defender, empId);
const defGrappled = result.system.pointsemp == (result.system.empoigneid == defender.id ? 2 : -2)
const attGrappled = result.system.pointsemp == (result.system.empoigneurid == attacker.id ? -2 : 2)
const grappling = Math.abs(result.system.pointsemp) > 0
await defender.setEffect(STATUSES.StatusGrappling, grappling && !defGrappled)
await attacker.setEffect(STATUSES.StatusGrappling, grappling && !attGrappled)
await defender.setEffect(STATUSES.StatusGrappled, defGrappled)
await attacker.setEffect(STATUSES.StatusGrappled, attGrappled)
return result
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static registerChatCallbacks(html) { static registerChatCallbacks(html) {
$(html).on("click", '.defense-empoignade-cac', event => { $(html).on("click", '.defense-empoignade-cac', event => {
@@ -184,7 +229,7 @@ export class RdDEmpoignade {
selectedCarac: attacker.system.carac.melee, selectedCarac: attacker.system.carac.melee,
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender) malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
} }
if (attacker.isCreatureEntite()) { if (attacker.isCreatureOuEntite()) {
MappingCreatureArme.setRollDataCreature(rollData) MappingCreatureArme.setRollDataCreature(rollData)
} }
if (empoignade.system.pointsemp >= 2) { if (empoignade.system.pointsemp >= 2) {
@@ -237,10 +282,7 @@ export class RdDEmpoignade {
if (rollData.rolled.isSuccess && isNouvelle) { if (rollData.rolled.isSuccess && isNouvelle) {
const objectEmpoignade = rollData.empoignade.toObject(); RdDEmpoignade.$createEtatEmpoignade(rollData.empoignade)
// Creer l'empoignade sur attaquant/defenseur
attacker.creerObjetParMJ(objectEmpoignade);
defender.creerObjetParMJ(objectEmpoignade);
} }
rollData.empoignade.isSuccess = rollData.rolled.isSuccess; rollData.empoignade.isSuccess = rollData.rolled.isSuccess;
@@ -259,7 +301,7 @@ export class RdDEmpoignade {
return return
} }
let empoignade = this.getEmpoignade(attacker, defender) let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
if (!empoignade) { if (!empoignade) {
ui.notifications.warn("Une erreur s'est produite : Aucune empoignade trouvée !!") ui.notifications.warn("Une erreur s'est produite : Aucune empoignade trouvée !!")
@@ -317,18 +359,33 @@ export class RdDEmpoignade {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $updateEtatEmpoignade(empoignade) { static async $createEtatEmpoignade(empoignade) {
console.log("UPDATE Empoignade", empoignade) console.log("CREATE Empoignade", empoignade)
let defender = game.actors.get(empoignade.system.empoigneid) let defender = game.actors.get(empoignade.system.empoigneid)
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
let update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
await defender.updateEmbeddedDocuments('Item', [update])
let attacker = game.actors.get(empoignade.system.empoigneurid) let attacker = game.actors.get(empoignade.system.empoigneurid)
emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol } // Creer l'empoignade sur attaquant/defenseur
await attacker.updateEmbeddedDocuments('Item', [update]) await attacker.creerObjetParMJ(empoignade)
await defender.creerObjetParMJ(empoignade)
}
/* -------------------------------------------- */
static async $updateEtatEmpoignade(empoignade, attacker, defender) {
console.log("UPDATE Empoignade", empoignade)
const belligerants = [
attacker ?? game.actors.get(empoignade.system.empoigneurid),
defender ?? game.actors.get(empoignade.system.empoigneid)]
await Promise.all(
belligerants.map(async belligerant => {
const emp = RdDEmpoignade.getEmpoignadeById(belligerant, empoignade.system.empoignadeid)
return await belligerant.updateEmbeddedDocuments('Item', [{
_id: emp._id,
"system.pointsemp": empoignade.system.pointsemp,
"system.ausol": empoignade.system.ausol
}])
}))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -347,7 +404,7 @@ export class RdDEmpoignade {
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) { if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return return
} }
let empoignade = this.getEmpoignade(attacker, defender) let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
empoignade.system.ausol = true empoignade.system.ausol = true
await this.$updateEtatEmpoignade(empoignade) await this.$updateEtatEmpoignade(empoignade)
@@ -366,7 +423,7 @@ export class RdDEmpoignade {
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) { if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return return
} }
let empoignade = this.getEmpoignade(attacker, defender) let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
await defender.setEffect(STATUSES.StatusProne, true); await defender.setEffect(STATUSES.StatusProne, true);
await this.$deleteEmpoignade(empoignade) await this.$deleteEmpoignade(empoignade)
@@ -382,7 +439,7 @@ export class RdDEmpoignade {
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) { if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return return
} }
let empoignade = this.getEmpoignade(attacker, defender) let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
//console.log("Perte d'endurance :!!!", perteMode) //console.log("Perte d'endurance :!!!", perteMode)
let endValue = defender.system.sante.endurance.value let endValue = defender.system.sante.endurance.value
@@ -423,9 +480,17 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async createEmpoignade(attacker, defender) { static async createEmpoignade(attacker, defender) {
return await Item.create({ return await Item.create({
name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name, name: "Empoignade de " + attacker.name + ' sur ' + defender.name,
type: 'empoignade', type: ITEM_TYPES.empoignade,
system: { description: "", empoignadeid: foundry.utils.randomID(16), compteempoigne: 0, empoigneurid: attacker.id, empoigneid: defender.id, ptsemp: 0, empoigneurname: attacker.name, empoignename: defender.name } system: {
description: "",
empoignadeid: foundry.utils.randomID(16),
empoigneurid: attacker.id,
empoigneid: defender.id,
pointsemp: 0,
empoigneurname: attacker.name,
empoignename: defender.name
}
}, },
{ {
temporary: true temporary: true

View File

@@ -89,6 +89,7 @@ import { Migrations } from './migrations.js'
import RollDialog from "./roll/roll-dialog.mjs" import RollDialog from "./roll/roll-dialog.mjs"
import ChatRollResult from "./roll/chat-roll-result.mjs" import ChatRollResult from "./roll/chat-roll-result.mjs"
import ExportPdf from "./actor/export-pdf/export-pdf.mjs"
/** /**
* RdD system * RdD system
@@ -296,6 +297,7 @@ export class SystemReveDeDragon {
RdDPossession.init() RdDPossession.init()
TMRRencontres.init() TMRRencontres.init()
ExportScriptarium.init() ExportScriptarium.init()
ExportPdf.init()
RollDialog.init() RollDialog.init()
ChatRollResult.init() ChatRollResult.init()
} }

View File

@@ -95,7 +95,7 @@ export class RdDPossession {
static selectCompetenceDraconicOuPossession(rollData, rollingActor) { static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
rollData.competence = rollingActor.getDraconicOuPossession(); rollData.competence = rollingActor.getDraconicOuPossession();
if (rollingActor.isCreatureEntite()) { if (rollingActor.isCreatureOuEntite()) {
const carac = rollingActor.system.carac const carac = rollingActor.system.carac
rollData.carac = carac rollData.carac = carac
rollData.competence.system.defaut_carac = 'reve' rollData.competence.system.defaut_carac = 'reve'

View File

@@ -16,17 +16,20 @@ const levelDown = [
]; ];
const levelImpossible = { score: 0, norm: 0, sign: 0, part: 0, epart: 0, etotal: 1 }; const levelImpossible = { score: 0, norm: 0, sign: 0, part: 0, epart: 0, etotal: 1 };
const reussiteNormale = { code: "norm", isPart: false, isSign: false, isSuccess: true, isEchec: false, isEPart: false, isETotal: false, ptTache: 1, ptQualite: 0, quality: "Réussite normale", condition: (target, roll) => (roll > target.sign && roll <= target.norm) };
const reussiteSignificative = { code: "sign", isPart: false, isSign: true, isSuccess: true, isEchec: false, isEPart: false, isETotal: false, ptTache: 2, ptQualite: 1, quality: "Réussite significative", condition: (target, roll) => (roll > target.part && roll <= target.sign) };
const reussiteInsuffisante = { code: "notSign", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: false, isETotal: false, ptTache: 0, ptQualite: -2, quality: "Réussite insuffisante", condition: (target, roll) => false }
const reussites = [ const reussites = [
{ code: "etotal", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: true, isETotal: true, ptTache: -4, ptQualite: -6, quality: "Echec total", condition: (target, roll) => roll >= target.etotal && roll <= 100 }, { code: "etotal", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: true, isETotal: true, ptTache: -4, ptQualite: -6, quality: "Echec total", condition: (target, roll) => roll >= target.etotal && roll <= 100 },
{ code: "epart", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: true, isETotal: false, ptTache: -2, ptQualite: -4, quality: "Echec particulier", condition: (target, roll) => (roll >= target.epart && roll < target.etotal) }, { code: "epart", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: true, isETotal: false, ptTache: -2, ptQualite: -4, quality: "Echec particulier", condition: (target, roll) => (roll >= target.epart && roll < target.etotal) },
{ code: "echec", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: false, isETotal: false, ptTache: 0, ptQualite: -2, quality: "Echec normal", condition: (target, roll) => (roll > target.norm && roll < target.etotal) }, { code: "echec", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: false, isETotal: false, ptTache: 0, ptQualite: -2, quality: "Echec normal", condition: (target, roll) => (roll > target.norm && roll < target.etotal) },
{ code: "norm", isPart: false, isSign: false, isSuccess: true, isEchec: false, isEPart: false, isETotal: false, ptTache: 1, ptQualite: 0, quality: "Réussite normale", condition: (target, roll) => (roll > target.sign && roll <= target.norm) }, reussiteNormale,
{ code: "sign", isPart: false, isSign: true, isSuccess: true, isEchec: false, isEPart: false, isETotal: false, ptTache: 2, ptQualite: 1, quality: "Réussite significative", condition: (target, roll) => (roll > target.part && roll <= target.sign) }, reussiteSignificative,
{ code: "part", isPart: true, isSign: true, isSuccess: true, isEchec: false, isEPart: false, isETotal: false, ptTache: 3, ptQualite: 2, quality: "Réussite Particulière!", condition: (target, roll) => (roll > 0 && roll <= target.part) }, { code: "part", isPart: true, isSign: true, isSuccess: true, isEchec: false, isEPart: false, isETotal: false, ptTache: 3, ptQualite: 2, quality: "Réussite Particulière!", condition: (target, roll) => (roll > 0 && roll <= target.part) },
{ code: "error", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: true, isETotal: true, ptTache: 0, ptQualite: 0, quality: "Jet de dés invalide", condition: (target, roll) => (roll <= 0 || roll > 100) } { code: "error", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: true, isETotal: true, ptTache: 0, ptQualite: 0, quality: "Jet de dés invalide", condition: (target, roll) => (roll <= 0 || roll > 100) }
]; ];
const reussiteInsuffisante = { code: "notSign", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: false, isETotal: false, ptTache: 0, ptQualite: -2, quality: "Réussite insuffisante", condition: (target, roll) => false }
/* -------------------------------------------- */ /* -------------------------------------------- */
const CARAC_MAXIMUM_RESOLUTION = 40; const CARAC_MAXIMUM_RESOLUTION = 40;
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -156,6 +159,11 @@ export class RdDResolutionTable {
} }
} }
/* -------------------------------------------- */
static replaceParticuliereDemiSurprise(chances) {
foundry.utils.mergeObject(chances, reussites.find(x => x.code == 'part'), { overwrite: true });
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static significativeRequise(chances) { static significativeRequise(chances) {
chances.roll = Math.min(chances.part + 1, chances.sign) chances.roll = Math.min(chances.part + 1, chances.sign)
@@ -192,6 +200,7 @@ export class RdDResolutionTable {
if (chances.norm < roll * diviseur) { if (chances.norm < roll * diviseur) {
return reussiteInsuffisante return reussiteInsuffisante
} }
return reussiteSignificative
} }
return reussite return reussite
} }

View File

@@ -1,4 +1,4 @@
import { ENTITE_BLURETTE, ENTITE_INCARNE, renderTemplate } from "./constants.js"; import { ENTITE_NONINCARNE, RDD_CONFIG, renderTemplate } from "./constants.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
/** /**
@@ -16,34 +16,29 @@ export class RdDEncaisser extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
constructor(html, actor) { constructor(html, actor) {
let dialogConf = { if (actor.isEntiteNonIncarnee([ENTITE_NONINCARNE])) {
throw `${actor.name} est une entité non incarnée et ne peut pas subnir de dommages`
}
const dialogConf = {
title: "Jet d'Encaissement", title: "Jet d'Encaissement",
content: html, content: html,
} default: RDD_CONFIG.encaissement.mortel,
buttons: {
if (!actor.isEntite()) { [RDD_CONFIG.encaissement.mortel]: { label: "Mortel", callback: html => this.performEncaisser(RDD_CONFIG.encaissement.mortel) },
dialogConf.default = "mortel";
dialogConf.buttons = {
"mortel": { label: "Mortel", callback: html => this.performEncaisser("mortel") },
"non-mortel": { label: "Non-mortel", callback: html => this.performEncaisser("non-mortel") },
"sonne": { label: "Sonné", callback: html => this.actor.setSonne() },
};
}
else if (actor.isEntite([ENTITE_BLURETTE, ENTITE_INCARNE])) {
dialogConf.default = "entiteincarnee"
dialogConf.buttons = {
"entiteincarnee": { label: "Entité incarnée", callback: html => this.performEncaisser("entiteincarnee") }
} }
} }
if (!actor.isEntite()) {
let dialogOptions = { dialogConf.buttons[RDD_CONFIG.encaissement.nonmortel] = { label: "Non-mortel", callback: html => this.performEncaisser(RDD_CONFIG.encaissement.nonmortel) }
classes: ["rdd-roll-dialog"], dialogConf.buttons["sonne"] = { label: "Sonné", callback: html => this.actor.setSonne() }
width: 320,
height: 'fit-content'
} }
// Select proper roll dialog template and stuff // Select proper roll dialog template and stuff
super(dialogConf, dialogOptions); super(dialogConf, {
classes: ["rdd-roll-dialog"],
width: 320,
height: 'fit-content'
});
this.actor = actor; this.actor = actor;
this.modifier = 0; this.modifier = 0;

View File

@@ -25,7 +25,7 @@ export class RdDRollDialogEthylisme extends Dialog {
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = html; this.html = html;
this.bringToTop(); this.bringToFront();
this.html.find(".force-alcool").change((event) => { this.html.find(".force-alcool").change((event) => {
this.rollData.forceAlcool = Misc.toInt(event.currentTarget.value); this.rollData.forceAlcool = Misc.toInt(event.currentTarget.value);

View File

@@ -22,7 +22,7 @@ export class RdDRollResolutionTable extends Dialog {
RdDRollResolutionTable.resolutionTable.render(true); RdDRollResolutionTable.resolutionTable.render(true);
} }
else{ else{
RdDRollResolutionTable.resolutionTable.bringToTop(); RdDRollResolutionTable.resolutionTable.bringToFront();
} }
} }
@@ -70,7 +70,7 @@ export class RdDRollResolutionTable extends Dialog {
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = html; this.html = html;
this.bringToTop(); this.bringToFront();
this.html.find("[name='diffLibre']").val(Misc.toInt(this.rollData.diffLibre)); this.html.find("[name='diffLibre']").val(Misc.toInt(this.rollData.diffLibre));

View File

@@ -8,7 +8,7 @@ import { RdDCarac } from "./rdd-carac.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { ACTOR_TYPES, renderTemplate } from "./constants.js"; import { ACTOR_TYPES, RDD_CONFIG, renderTemplate } from "./constants.js";
import { EMPOIGNADE } from "./item/arme.js"; import { EMPOIGNADE } from "./item/arme.js";
/** /**
@@ -128,7 +128,7 @@ export class RdDRoll extends Dialog {
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = html; this.html = html;
this.bringToTop(); this.bringToFront();
console.log('RdDRoll.activateListeners', this.rollData); console.log('RdDRoll.activateListeners', this.rollData);
@@ -206,7 +206,7 @@ export class RdDRoll extends Dialog {
this.updateRollResult(html); this.updateRollResult(html);
}); });
this.html.find("input.check-mortalite").change((event) => { this.html.find("input.check-mortalite").change((event) => {
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel"; this.rollData.dmg.mortalite = event.currentTarget.checked ? RDD_CONFIG.encaissement.nonmortel : RDD_CONFIG.encaissement.mortel;
this.updateRollResult(html); this.updateRollResult(html);
}); });
this.html.find('.cuisine-proportions').change((event) => { this.html.find('.cuisine-proportions').change((event) => {
@@ -333,8 +333,8 @@ export class RdDRoll extends Dialog {
// Mise à jour valeurs // Mise à jour valeurs
this.html.find(".dialog-roll-title").text(this._getTitle(rollData)); this.html.find(".dialog-roll-title").text(this._getTitle(rollData));
this.html.find("input.check-mortalite").prop('checked', rollData.dmg.mortalite == 'non-mortel'); this.html.find("input.check-mortalite").prop('checked', rollData.dmg.mortalite == RDD_CONFIG.encaissement.nonmortel);
this.html.find("label.dmg-arme-actor").text(rollData.dmg.mortalite == EMPOIGNADE ? EMPOIGNADE : Misc.toSignedString(rollData.dmg.total)); this.html.find("label.dmg-arme-actor").text(rollData.dmg.isEmpoignade ? EMPOIGNADE : Misc.toSignedString(rollData.dmg.total));
this.html.find("label.arme-mortalite").text(rollData.dmg.mortalite); this.html.find("label.arme-mortalite").text(rollData.dmg.mortalite);
this.html.find("div.placeholder-ajustements").empty().append(adjustements); this.html.find("div.placeholder-ajustements").empty().append(adjustements);
this.html.find("div.placeholder-resolution").empty().append(resolutionTable) this.html.find("div.placeholder-resolution").empty().append(resolutionTable)

View File

@@ -82,7 +82,7 @@ export class RdDTMRDialog extends Dialog {
this.subdialog = undefined this.subdialog = undefined
this.displaySize = undefined this.displaySize = undefined
if (!this.viewOnly && !game.user.isGM) { if (!this.viewOnly && !game.user.isGM) {
this.$tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); ChatUtility.tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")");
} }
this.callbacksOnAnimate = []; this.callbacksOnAnimate = [];
const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def); const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def);
@@ -125,7 +125,11 @@ export class RdDTMRDialog extends Dialog {
HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue")); HtmlUtility.showControlWhen(this.html.find(".appliquerFatigue"), ReglesOptionnelles.isUsing("appliquer-fatigue"));
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getCoordActor())); HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getCoordActor()));
this.html.find('form.tmr-dialog *').click(event => this.subdialog?.bringToTop()); this.html.find('form.tmr-dialog *').click(event => {
if (this.subdialog?.rendered){
this.subdialog?.bringToFront()
}
})
// Roll Sort // Roll Sort
this.html.find('.lancer-sort').click(event => this.lancerUnSort()); this.html.find('.lancer-sort').click(event => this.lancerUnSort());
@@ -169,26 +173,26 @@ export class RdDTMRDialog extends Dialog {
async forceTMRDisplay() { async forceTMRDisplay() {
if (this.rendered) { if (this.rendered) {
this.bringToTop() this.bringToFront()
this.bringSubDialogToTop(); this.bringSubDialogToFront();
} }
} }
bringSubDialogToTop() { bringSubDialogToFront() {
if (this.subdialog?.bringToTop && this.subdialog?.element && this.subdialog?.element[0]) { if (this.subdialog?.bringToFront && this.subdialog?.element && this.subdialog?.element[0]) {
this.subdialog.bringToTop(); this.subdialog.bringToFront();
} }
} }
async restoreTMRAfterAction() { async restoreTMRAfterAction() {
this.subdialog = undefined this.subdialog = undefined
await this.maximize() await this.maximize()
this.bringToTop() this.bringToFront()
} }
forceTMRContinueAction() { forceTMRContinueAction() {
ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR'); ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR');
this.bringSubDialogToTop(); this.bringSubDialogToFront();
return false return false
} }
@@ -343,19 +347,8 @@ export class RdDTMRDialog extends Dialog {
this.forceTMRContinueAction() this.forceTMRContinueAction()
return false return false
} }
this.descenteTMR = true; this.descenteTMR = true
if (this.actor.tmrApp) { await await this.actor.quitterTMR(message, this.viewOnly, this.cumulFatigue)
this.actor.tmrApp = undefined // Cleanup reference
const appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue")
await this.actor.santeIncDec(
appliquerFatigue ? "fatigue" : "endurance",
(appliquerFatigue ? 1 : -1) * this.cumulFatigue)
if (!this.viewOnly) {
await this.actor.setEffect(STATUSES.StatusDemiReve, false)
this.$tellToUserAndGM(message)
}
}
this.pixiTMR.close(); this.pixiTMR.close();
this.pixiTMR = undefined this.pixiTMR = undefined
await super.close(); await super.close();
@@ -412,7 +405,7 @@ export class RdDTMRDialog extends Dialog {
async $ignorerRencontre() { async $ignorerRencontre() {
if (this.currentRencontre) { if (this.currentRencontre) {
console.log("-> ignorer", this.currentRencontre); console.log("-> ignorer", this.currentRencontre);
this.$tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name); ChatUtility.tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
await this.$deleteRencontreTMRAtPosition() await this.$deleteRencontreTMRAtPosition()
this.updateTokens(); this.updateTokens();
this.$updateValuesDisplay(); this.$updateValuesDisplay();
@@ -578,29 +571,6 @@ export class RdDTMRDialog extends Dialog {
}, 500); }, 500);
} }
/* -------------------------------------------- */
_tellToUser(message) {
ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id] });
}
/* -------------------------------------------- */
$tellToGM(message) {
ChatMessage.create({
user: game.user.id,
content: message,
whisper: ChatUtility.getGMs()
});
}
/* -------------------------------------------- */
$tellToUserAndGM(message) {
ChatMessage.create({
user: game.user.id,
content: message,
whisper: ChatUtility.getUserAndGMs()
})
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async manageRencontre(tmr) { async manageRencontre(tmr) {
if (this.viewOnly) { if (this.viewOnly) {
@@ -676,14 +646,14 @@ export class RdDTMRDialog extends Dialog {
? TMRUtility.getTMRType(tmr.coord) + " ??" ? TMRUtility.getTMRType(tmr.coord) + " ??"
: tmr.label + " (" + tmr.coord + ")"); : tmr.label + " (" + tmr.coord + ")");
this.setTMRPendingAction({ bringToTop: () => { } }) this.setTMRPendingAction({ bringToFront: () => { } })
const myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE }); const myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
this.restoreTMRAfterAction() this.restoreTMRAfterAction()
if (myRoll == 7) { if (myRoll == 7) {
this._tellToUser(myRoll + ": Rencontre en " + coordTMR); ChatUtility.tellToUser(myRoll + ": Rencontre en " + coordTMR);
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre()) return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
} else { } else {
this._tellToUser(myRoll + ": Pas de rencontre en " + coordTMR); ChatUtility.tellToUser(myRoll + ": Pas de rencontre en " + coordTMR);
return undefined; return undefined;
} }
} }

View File

@@ -75,30 +75,27 @@ const fatigueLineMalus = [0, -1, -2, -3, -4, -5, -6, -7];
/* -------------------------------------------- */ /* -------------------------------------------- */
const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "Complètement fait", "Ivre mort"]; const nomEthylisme = ["Emeché", "Gris", "Pinté", "Pas frais", "Ivre", "Bu", "Complètement fait", "Ivre mort"];
/* -------------------------------------------- */ const TABLE_ENCAISSEMENT_MORTEL = [
const definitionsEncaissement = { { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
"mortel": [ { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 }, { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 }, { minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 }, { minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4 }, ]
{ minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6 }, const TABLE_ENCAISSEMENT_NONMORTEL = [
], { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
"non-mortel": [ { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 }, { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 }, { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 }, { minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 }, ]
{ minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 }, const TABLE_ENCAISSEMENT_ENTITE = [
], { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
"entiteincarnee": [ { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
{ minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 }, { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 },
{ minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 }, { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 4 },
{ minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 }, { minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 6 },
{ minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 0 }, ]
{ minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 0 },
]
};
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDUtility { export class RdDUtility {
@@ -278,7 +275,7 @@ export class RdDUtility {
Handlebars.registerHelper('plusMoins', diff => parseInt(diff) ? (diff > 0 ? '+' : '') + Math.round(diff) : diff) Handlebars.registerHelper('plusMoins', diff => parseInt(diff) ? (diff > 0 ? '+' : '') + Math.round(diff) : diff)
Handlebars.registerHelper('fractionOneN', n => new Handlebars.SafeString(Misc.getFractionOneN(n))) Handlebars.registerHelper('fractionOneN', n => new Handlebars.SafeString(Misc.getFractionOneN(n)))
// Handle v12 removal of this helper // Handle v12 removal of this helper
Handlebars.registerHelper('select', function (selected, options) { Handlebars.registerHelper('select', function (selected, options) {
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected)); const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
@@ -286,7 +283,7 @@ export class RdDUtility {
const html = options.fn(this); const html = options.fn(this);
return html.replace(rgx, "$& selected"); return html.replace(rgx, "$& selected");
}) })
// logic // logic
Handlebars.registerHelper('either', (a, b) => a ?? b); Handlebars.registerHelper('either', (a, b) => a ?? b);
// string manipulation // string manipulation
@@ -299,7 +296,7 @@ export class RdDUtility {
Handlebars.registerHelper('grammar-un', str => Grammar.articleIndetermine(str)); Handlebars.registerHelper('grammar-un', str => Grammar.articleIndetermine(str));
Handlebars.registerHelper('grammar-accord', (genre, ...args) => Grammar.accord(genre, args)); Handlebars.registerHelper('grammar-accord', (genre, ...args) => Grammar.accord(genre, args));
Handlebars.registerHelper('json-stringify', object => JSON.stringify(object)) Handlebars.registerHelper('json-stringify', object => JSON.stringify(object))
// math // math
Handlebars.registerHelper('math-sum', (...values) => values.slice(0, -1).reduce(Misc.sum(), 0)) Handlebars.registerHelper('math-sum', (...values) => values.slice(0, -1).reduce(Misc.sum(), 0))
Handlebars.registerHelper('math-abs', diff => Math.abs(parseInt(diff))) Handlebars.registerHelper('math-abs', diff => Math.abs(parseInt(diff)))
@@ -613,20 +610,20 @@ export class RdDUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getLocalisation(type = 'personnage') { static async getLocalisation(type = 'personnage') {
const loc = { result: await RdDDice.rollTotal("1d20")}; const loc = { result: await RdDDice.rollTotal("1d20") };
if (type == 'personnage') { if (type == 'personnage') {
if (loc.result <= 3) loc.txt = "Jambe, genou, pied, jarret"; if (loc.result <= 3) loc.txt = "Jambe, genou, pied, jarret";
else if (loc.result <= 7) loc.txt = "Hanche, cuisse, fesse"; else if (loc.result <= 7) loc.txt = "Hanche, cuisse, fesse";
else if (loc.result <= 9) loc.txt = "Ventre, reins"; else if (loc.result <= 9) loc.txt = "Ventre, reins";
else if (loc.result <= 12) loc.txt = "Poitrine, dos"; else if (loc.result <= 12) loc.txt = "Poitrine, dos";
else if (loc.result <= 14) loc.txt = "Avant-bras, main, coude"; else if (loc.result <= 14) loc.txt = "Avant-bras, main, coude";
else if (loc.result <= 18) loc.txt = "Epaule, bras, omoplate"; else if (loc.result <= 18) loc.txt = "Epaule, bras, omoplate";
else if (loc.result == 19) loc.txt = "Tête"; else if (loc.result == 19) loc.txt = "Tête";
else if (loc.result == 20) loc.txt = "Tête (visage)"; else if (loc.result == 20) loc.txt = "Tête (visage)";
} else { } else {
if (loc.result <= 7) loc.txt = "Jambes/Pattes"; if (loc.result <= 7) loc.txt = "Jambes/Pattes";
else if (loc.result <= 18) loc.txt = "Corps"; else if (loc.result <= 18) loc.txt = "Corps";
else if (loc.result <= 20) loc.txt = "Tête"; else if (loc.result <= 20) loc.txt = "Tête";
} }
return loc return loc
} }
@@ -671,13 +668,13 @@ export class RdDUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async prepareEncaissement(actor, dmg, roll, armure) { static async prepareEncaissement(targetActor, dmg, roll, armure) {
const jetTotal = roll.total + dmg.total - armure const jetTotal = roll.total + dmg.total - armure
const encaissement = RdDUtility._selectEncaissement(jetTotal, dmg.mortalite); const encaissement = RdDUtility.$selectEncaissement(targetActor, jetTotal, dmg.mortalite)
const over20 = Math.max(jetTotal - 20, 0); const over20 = Math.max(jetTotal - 20, 0)
encaissement.dmg = dmg encaissement.dmg = dmg
if (ReglesOptionnelles.isUsing('localisation-aleatoire')) { if (ReglesOptionnelles.isUsing('localisation-aleatoire')) {
encaissement.dmg.loc = dmg.loc ?? await RdDUtility.getLocalisation(actor.type) encaissement.dmg.loc = dmg.loc ?? await RdDUtility.getLocalisation(targetActor.type)
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;' encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;'
} }
else { else {
@@ -693,15 +690,21 @@ export class RdDUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _selectEncaissement(degats, mortalite) { static $selectEncaissement(targetActor, degats, mortalite) {
const table = definitionsEncaissement[mortalite] === undefined ? definitionsEncaissement["mortel"] : definitionsEncaissement[mortalite]; const table = RdDUtility.$getTableEncaissement(targetActor, mortalite)
for (let encaissement of table) { const encaissement = table.find(it => ((it.minimum ?? degats) <= degats && degats <= (it.maximum ?? degats)))
if ((encaissement.minimum === undefined || encaissement.minimum <= degats) return foundry.utils.duplicate(encaissement ?? table[0])
&& (encaissement.maximum === undefined || degats <= encaissement.maximum)) { }
return foundry.utils.duplicate(encaissement);
} static $getTableEncaissement(targetActor, mortalite) {
if (targetActor.isEntite()) {
return TABLE_ENCAISSEMENT_ENTITE
} }
return foundry.utils.duplicate(table[0]); switch (mortalite) {
case RDD_CONFIG.encaissement.nonmortel: return TABLE_ENCAISSEMENT_NONMORTEL
case RDD_CONFIG.encaissement.entiteincarnee: return TABLE_ENCAISSEMENT_ENTITE
}
return TABLE_ENCAISSEMENT_MORTEL
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@@ -1,11 +1,17 @@
import { ChatUtility } from "../chat-utility.js" import { ChatUtility } from "../chat-utility.js"
import RollDialog from "./roll-dialog.mjs" import RollDialog, { ALL_ROLL_TYPES } from "./roll-dialog.mjs"
import { RdDCarac } from "../rdd-carac.js" import { RdDCarac } from "../rdd-carac.js"
import { RdDCombat } from "../rdd-combat.js" import { RdDCombat } from "../rdd-combat.js"
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs" import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { RdDResolutionTable } from "../rdd-resolution-table.js" import { RdDResolutionTable } from "../rdd-resolution-table.js"
import { RDD_CONFIG, renderTemplate } from "../constants.js" import { RDD_CONFIG, renderTemplate } from "../constants.js"
import { EMPOIGNADE } from "../item/arme.js" import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js"
import { RollTypeCuisine } from "./roll-type-cuisine.mjs"
import { RollTypeMeditation } from "./roll-type-meditation.mjs"
import { PART_DEFENSE } from "./roll-part-defense.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
import { RdDRollTables } from "../rdd-rolltables.js"
import { RdDEmpoignade } from "../rdd-empoignade.js"
export default class ChatRollResult { export default class ChatRollResult {
static init() { static init() {
@@ -16,15 +22,18 @@ export default class ChatRollResult {
static onReady() { static onReady() {
foundry.applications.handlebars.loadTemplates({ foundry.applications.handlebars.loadTemplates({
'partial-infojet': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-infojet.hbs',
'partial-appel-chance': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-appel-chance.hbs', 'partial-appel-chance': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-appel-chance.hbs',
'partial-attaque-particuliere': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-attaque-particuliere.hbs', 'partial-attaque-particuliere': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-attaque-particuliere.hbs',
'partial-choix-maladresse': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-choix-maladresse.hbs',
'partial-maladresse': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-maladresse.hbs',
'partial-encaissement': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-encaissement.hbs', 'partial-encaissement': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-encaissement.hbs',
'partial-recul-choc': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-recul-choc.hbs', 'partial-recul-choc': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-recul-choc.hbs',
'partial-info-appel-moral': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-info-appel-moral.hbs', 'partial-info-appel-moral': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-info-appel-moral.hbs',
}) })
} }
async display(roll) { async display(roll, impacts) {
this.prepareDisplay(roll) this.prepareDisplay(roll)
const chatMessage = await ChatUtility.createChatWithRollMode( const chatMessage = await ChatUtility.createChatWithRollMode(
@@ -34,8 +43,9 @@ export default class ChatRollResult {
roll.active.actor, roll.active.actor,
roll.current?.rollmode?.key roll.current?.rollmode?.key
) )
const save = RollDialog.saveParts(roll) const save = RollDialog.saveParts(roll, impacts)
ChatUtility.setMessageData(chatMessage, 'rollData', save)
await this.saveChatMessageRoll(chatMessage, save)
return chatMessage return chatMessage
} }
@@ -45,7 +55,7 @@ export default class ChatRollResult {
roll.show.chance = this.isAppelChancePossible(roll) roll.show.chance = this.isAppelChancePossible(roll)
roll.show.encaissement = this.isShowEncaissement(roll) roll.show.encaissement = this.isShowEncaissement(roll)
roll.show.recul = this.getRecul(roll) roll.show.recul = this.getRecul(roll)
//roll.show.particuliere = roll.show.particuliere ?? [] roll.show.maladresse = this.getMaladresse(roll)
} }
isAppelChancePossible(roll) { isAppelChancePossible(roll) {
@@ -57,11 +67,28 @@ export default class ChatRollResult {
isShowEncaissement(roll) { isShowEncaissement(roll) {
switch (roll.type.current) { switch (roll.type.current) {
case ROLL_TYPE_DEFENSE: case ROLL_TYPE_DEFENSE:
return roll.rolled.isEchec && roll.attackerRoll?.dmg.mortalite != EMPOIGNADE return roll.rolled.isEchec
} }
return false return false
} }
getMaladresse(roll) {
switch (roll.type.current) {
case ROLL_TYPE_DEFENSE:
if (roll.rolled.isETotal) {
const arme = roll.current[PART_DEFENSE].arme
return arme ? 'avec-arme' : 'sans-arme'
}
break
case ROLL_TYPE_ATTAQUE:
if (roll.rolled.isETotal || (roll.rolled.isEchec && roll.active.surprise == 'demi')) {
const arme = roll.current[PART_ATTAQUE].arme
return arme.system.baseInit > 4 ? 'avec-arme' : 'sans-arme'
}
break
}
return undefined
}
getRecul(roll, defender = roll.active.actor, attacker = roll.opponent?.actor) { getRecul(roll, defender = roll.active.actor, attacker = roll.opponent?.actor) {
switch (roll.type.current) { switch (roll.type.current) {
@@ -97,17 +124,22 @@ export default class ChatRollResult {
} }
async buildRollHtml(roll) { async buildRollHtml(roll) {
const template = `systems/foundryvtt-reve-de-dragon/templates/roll/result/chat-${roll.type.current}.hbs` const template = ALL_ROLL_TYPES.find(it => it.code == roll.type.current).chatResultTemplate
return await renderTemplate(template, roll) const html = await renderTemplate(template, roll)
return await RdDTextEditor.enrichHTML(html, undefined, { showLink: false })
} }
async chatListeners(html) { async chatListeners(html) {
$(html).on("click", '.appel-chance', event => this.onClickAppelChance(event)) $(html).on("click", '.appel-chance', event => this.onClickAppelChance(event))
$(html).on("click", '.appel-destinee', event => this.onClickAppelDestinee(event)) $(html).on("click", '.appel-destinee', event => this.onClickAppelDestinee(event))
$(html).on("click", '.button-defense', event => this.onClickDefense(event))
$(html).on("click", '.encaissement', event => this.onClickEncaissement(event)) $(html).on("click", '.encaissement', event => this.onClickEncaissement(event))
$(html).on("click", '.resister-recul', event => this.onClickRecul(event)) $(html).on("click", '.resister-recul', event => this.onClickRecul(event))
$(html).on("click", '.choix-particuliere', event => this.onClickChoixParticuliere(event)) $(html).on("click", '.choix-particuliere', event => this.onClickChoixParticuliere(event))
$(html).on("click", '.faire-gouter', event => this.onClickFaireGouter(event))
$(html).on("click", '.monter-tmr-normale', event => this.onClickMonteeTMR(event, 'normal'))
$(html).on("click", '.monter-tmr-rapide', event => this.onClickMonteeTMR(event, 'rapide'))
$(html).on("click", '.tirer-maladresse', event => this.onClickTirerMaladresse(event))
} }
getCombat(roll) { getCombat(roll) {
@@ -115,15 +147,24 @@ export default class ChatRollResult {
case ROLL_TYPE_DEFENSE: case ROLL_TYPE_DEFENSE:
return RdDCombat.rddCombatForAttackerAndDefender(roll.ids.opponentId, roll.ids.opponentTokenId, roll.ids.actorTokenId) return RdDCombat.rddCombatForAttackerAndDefender(roll.ids.opponentId, roll.ids.opponentTokenId, roll.ids.actorTokenId)
case ROLL_TYPE_ATTAQUE: case ROLL_TYPE_ATTAQUE:
return RdDCombat.rddCombatForAttackerAndDefender(roll.ids.actorId, roll.ids.actorTokenId, roll.ids.opponentId) return RdDCombat.rddCombatForAttackerAndDefender(roll.ids.actorId, roll.ids.actorTokenId, roll.ids.opponentTokenId)
} }
return undefined return undefined
} }
async saveChatMessageRoll(chatMessage, savedRoll) {
await ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll)
}
loadChatMessageRoll(chatMessage) {
return ChatUtility.getMessageData(chatMessage, 'rollData')
}
async updateChatMessage(chatMessage, savedRoll) { async updateChatMessage(chatMessage, savedRoll) {
ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll) await this.saveChatMessageRoll(chatMessage, savedRoll)
const copy = foundry.utils.duplicate(savedRoll) const copy = foundry.utils.duplicate(savedRoll)
RollDialog.loadRollData(copy) RollDialog.loadRollData(copy)
savedRoll.dmg = copy.current.attaque?.dmg
this.prepareDisplay(copy) this.prepareDisplay(copy)
chatMessage.update({ content: await this.buildRollHtml(copy) }) chatMessage.update({ content: await this.buildRollHtml(copy) })
chatMessage.render(true) chatMessage.render(true)
@@ -131,7 +172,7 @@ export default class ChatRollResult {
onClickAppelChance(event) { onClickAppelChance(event) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData') const savedRoll = this.loadChatMessageRoll(chatMessage)
const actor = game.actors.get(savedRoll.ids.actorId) const actor = game.actors.get(savedRoll.ids.actorId)
actor.rollAppelChance( actor.rollAppelChance(
() => this.onAppelChanceSuccess(savedRoll, chatMessage), () => this.onAppelChanceSuccess(savedRoll, chatMessage),
@@ -139,10 +180,13 @@ export default class ChatRollResult {
event.preventDefault() event.preventDefault()
} }
onAppelChanceSuccess(savedRoll, chatMessage) { async onAppelChanceSuccess(savedRoll, chatMessage) {
const reRoll = foundry.utils.duplicate(savedRoll) const reRoll = foundry.utils.duplicate(savedRoll)
console.log('onAppelChanceSuccess savedRoll', savedRoll)
reRoll.type.retry = true reRoll.type.retry = true
await this.updateChatMessage(chatMessage, reRoll)
const callbacks = [r => ChatUtility.removeChatMessageId(chatMessage.id)] const callbacks = [r => ChatUtility.removeChatMessageId(chatMessage.id)]
// TODO: annuler les effets // TODO: annuler les effets
switch (reRoll.type.current) { switch (reRoll.type.current) {
case ROLL_TYPE_DEFENSE: case ROLL_TYPE_DEFENSE:
@@ -165,7 +209,7 @@ export default class ChatRollResult {
onClickAppelDestinee(event) { onClickAppelDestinee(event) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData') const savedRoll = this.loadChatMessageRoll(chatMessage)
const actor = game.actors.get(savedRoll.ids.actorId) const actor = game.actors.get(savedRoll.ids.actorId)
actor.appelDestinee(async () => { actor.appelDestinee(async () => {
@@ -176,23 +220,46 @@ export default class ChatRollResult {
}) })
} }
async onClickDefense(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
const attackerRoll = savedRoll.attackerRoll
this.getCombat(attackerRoll)?.defenseV2(attackerRoll,
[roll => { ChatUtility.removeChatMessageId(chatMessage.id) }]
)
}
async onClickEncaissement(event) { async onClickEncaissement(event) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData') const isMessageDemande = ChatUtility.getMessageData(chatMessage, 'demande-defense')
const savedRoll = this.loadChatMessageRoll(chatMessage)
const attaque = savedRoll.attackerRoll const attaque = savedRoll.attackerRoll
const defender = game.actors.get(savedRoll.ids.actorId)
const attacker = game.actors.get(savedRoll.ids.opponentId)
const defenderToken = savedRoll.ids.actorTokenId ? canvas.tokens.get(savedRoll.ids.actorTokenId) : undefined const defenderToken = savedRoll.ids.actorTokenId ? canvas.tokens.get(savedRoll.ids.actorTokenId) : undefined
const attackerToken = savedRoll.ids.opponentTokenId ? canvas.tokens.get(savedRoll.ids.opponentTokenId) : undefined const attackerToken = savedRoll.ids.opponentTokenId ? canvas.tokens.get(savedRoll.ids.opponentTokenId) : undefined
await defender?.encaisserDommages(attaque.dmg, attacker, undefined, attackerToken, defenderToken) switch (attaque.dmg.mortalite) {
case RDD_CONFIG.encaissement.empoignade:
savedRoll.done.encaissement = true savedRoll.done = savedRoll.done ?? {}
await this.updateChatMessage(chatMessage, savedRoll) savedRoll.done.empoignade = await RdDEmpoignade.ajustementEmpoignade(attackerToken.actor, defenderToken.actor)
break
case RDD_CONFIG.encaissement.entiteincarnee:
case RDD_CONFIG.encaissement.nonmortel:
case RDD_CONFIG.encaissement.mortel:
const defender = defenderToken?.actor ?? game.actors.get(savedRoll.ids.actorId)
const attacker = attackerToken?.actor ?? game.actors.get(savedRoll.ids.opponentId)
await defender?.encaisserDommages(attaque.dmg, attacker, undefined, attackerToken, defenderToken)
break
}
if (isMessageDemande) {
ChatUtility.removeChatMessageId(chatMessage.id)
} else {
savedRoll.done.encaissement = true
await this.updateChatMessage(chatMessage, savedRoll)
}
} }
async onClickRecul(event) { async onClickRecul(event) {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData') const savedRoll = this.loadChatMessageRoll(chatMessage)
const defender = game.actors.get(savedRoll.ids.actorId) const defender = game.actors.get(savedRoll.ids.actorId)
const attacker = game.actors.get(savedRoll.ids.opponentId) const attacker = game.actors.get(savedRoll.ids.opponentId)
savedRoll.done.recul = await defender.encaisserRecul(attacker.getForce(), savedRoll.attackerRoll.dmg.dmgArme) savedRoll.done.recul = await defender.encaisserRecul(attacker.getForce(), savedRoll.attackerRoll.dmg.dmgArme)
@@ -203,10 +270,37 @@ export default class ChatRollResult {
async onClickChoixParticuliere(event) { async onClickChoixParticuliere(event) {
const choix = event.currentTarget.attributes['data-particuliere'].value const choix = event.currentTarget.attributes['data-particuliere'].value
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData') const savedRoll = this.loadChatMessageRoll(chatMessage)
savedRoll.particuliere = choix savedRoll.particuliere = choix
savedRoll.particulieres = [RDD_CONFIG.particuliere[choix]] savedRoll.particulieres = [RDD_CONFIG.particuliere[choix]]
await this.updateChatMessage(chatMessage, savedRoll) await this.updateChatMessage(chatMessage, savedRoll)
await this.getCombat(savedRoll)?.onAttaqueV2(savedRoll, callbacks) await this.getCombat(savedRoll)?.onAttaqueV2(savedRoll)
}
async onClickFaireGouter(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
if (!savedRoll.type.retry) {
savedRoll.type.retry = true
await this.updateChatMessage(chatMessage, savedRoll)
}
await new RollTypeCuisine().onFaireGouter(savedRoll)
}
async onClickMonteeTMR(event, mode) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
if (await new RollTypeMeditation().onMonteeTMR(savedRoll, mode)) {
savedRoll.done.meditation = true
await this.updateChatMessage(chatMessage, savedRoll)
}
}
async onClickTirerMaladresse(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const typeMaladresse = event.currentTarget.attributes['data-maladresse'].value
const savedRoll = this.loadChatMessageRoll(chatMessage)
savedRoll.maladresse = await RdDRollTables.getMaladresse({ arme: typeMaladresse == 'avec-arme', toChat: false })
savedRoll.type.retry = true
await this.updateChatMessage(chatMessage, savedRoll)
} }
} }

View File

@@ -1,4 +1,4 @@
import { ActorToken } from "../actor-token.mjs" import { TokenActor } from "../technical/actor-token.mjs"
import { StatusEffects } from "../settings/status-effects.js" import { StatusEffects } from "../settings/status-effects.js"
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs" import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.mjs" import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
@@ -9,8 +9,8 @@ export class RollBasicParts {
static restore(rollData) { static restore(rollData) {
rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id
rollData.active = RollBasicParts.$getActor(rollData) rollData.active = RollBasicParts.getTokenActor(rollData)
rollData.opponent = RollBasicParts.$getOpponent(rollData) rollData.opponent = RollBasicParts.getTokenActorOpponent(rollData)
if (rollData.type.opposed == undefined) { if (rollData.type.opposed == undefined) {
rollData.type.opposed = rollData.opponent != null rollData.type.opposed = rollData.opponent != null
} }
@@ -26,7 +26,7 @@ export class RollBasicParts {
static loadSurprise(who, forceRequise) { static loadSurprise(who, forceRequise) {
if (who?.actor) { if (who?.actor) {
foundry.utils.mergeObject(who, foundry.utils.mergeObject(who,
StatusEffects.getActorEffetSurprise(who.actor, forceRequise), StatusEffects.getActorEffetSurprise(who.actor),
{ overwrite: true, inPlace: true }) { overwrite: true, inPlace: true })
} }
} }
@@ -40,6 +40,7 @@ export class RollBasicParts {
} }
static initFrom(rollData) { static initFrom(rollData) {
const isOpposed = rollData.type.opposed && rollData.opponent
return { return {
selected: {}, selected: {},
type: rollData.type, type: rollData.type,
@@ -47,46 +48,60 @@ export class RollBasicParts {
sceneId: rollData.ids.sceneId, sceneId: rollData.ids.sceneId,
actorId: rollData.active.id, actorId: rollData.active.id,
actorTokenId: rollData.active.tokenId, actorTokenId: rollData.active.tokenId,
opponentId: rollData.type.opposed ? rollData.opponent.id : undefined, opponentId: isOpposed ? rollData.opponent.id : undefined,
opponentTokenId: rollData.type.opposed ? rollData.opponent.tokenId : undefined, opponentTokenId: isOpposed ? rollData.opponent.tokenId : undefined,
} }
} }
} }
static prepareDefense(attackerRoll) {
if (!attackerRoll.passeArme) {
attackerRoll.passeArme = foundry.utils.randomID(16);
}
return {
ids: RollBasicParts.reverseIds(attackerRoll),
active: attackerRoll.opponent,
opponent: attackerRoll.active,
attackerRoll: attackerRoll,
passeArme: attackerRoll.passeArme,
show: { encaissement: true }
}
}
static reverseIds(rollData) { static reverseIds(rollData) {
return { return {
sceneId: rollData.ids.sceneId, sceneId: rollData.ids.sceneId,
actorId: rollData.ids.opponentId, actorId: rollData.ids.opponentId,
actorTokenId: rollData.ids.opponentTokenId, actorTokenId: rollData.ids.opponentTokenId,
opponentId: rollData.ids.actorId, opponentId: rollData.ids.actorId,
opponentTokenId: rollData.actorTokenId opponentTokenId: rollData.ids.actorTokenId
} }
} }
static $getActor(rollData) { static getTokenActor(rollData) {
if (rollData.ids.actorTokenId) { if (rollData.ids.actorTokenId) {
return ActorToken.fromTokenId(rollData.ids.actorTokenId, rollData.ids.sceneId) return TokenActor.fromTokenId(rollData.ids.actorTokenId, rollData.ids.sceneId)
} }
else { else {
const actorId = rollData.ids.actorId ?? (canvas.tokens.controlled.length == 1 const actorId = rollData.ids.actorId ?? (canvas.tokens.controlled.length == 1
/** TODO: jets de plusieurs personnages??? */ /** TODO: jets de plusieurs personnages??? */
? canvas.tokens.controlled[0] ? canvas.tokens.controlled[0]
: undefined) : undefined)
return ActorToken.fromActorId(actorId, () => { throw new Error("Pas d'acteur sélectionné") }) return TokenActor.fromActorId(actorId, () => { throw new Error("Pas d'acteur sélectionné") })
} }
} }
static $getOpponent(rollData) { static getTokenActorOpponent(rollData) {
if (rollData.ids.opponentTokenId) { if (rollData.ids.opponentTokenId) {
return ActorToken.fromTokenId(rollData.ids.opponentTokenId, rollData.ids.sceneId) return TokenActor.fromTokenId(rollData.ids.opponentTokenId, rollData.ids.sceneId)
} }
else if (rollData.ids.opponentId) { else if (rollData.ids.opponentId) {
return ActorToken.fromActorId(rollData.ids.opponentId) return TokenActor.fromActorId(rollData.ids.opponentId)
} }
else { else {
const targets = Array.from(game.user.targets) const targets = Array.from(game.user.targets)
if (targets.length == 1) { if (targets.length == 1) {
return ActorToken.fromToken(targets[0]) return TokenActor.fromToken(targets[0])
} }
else { else {
return undefined return undefined

View File

@@ -1,10 +1,10 @@
export const ROLL_TYPE_ATTAQUE = 'attaque' export const ROLL_TYPE_ATTAQUE = 'attaque'
export const ROLL_TYPE_COMP = 'comp' export const ROLL_TYPE_COMP = 'comp'
export const ROLL_TYPE_CUISINE = 'cuisine'
export const ROLL_TYPE_DEFENSE = 'defense' export const ROLL_TYPE_DEFENSE = 'defense'
export const ROLL_TYPE_JEU = 'jeu' export const ROLL_TYPE_JEU = 'jeu'
export const ROLL_TYPE_MEDITATION = 'meditation' export const ROLL_TYPE_MEDITATION = 'meditation'
export const ROLL_TYPE_CUISINE = 'cuisine'
export const ROLL_TYPE_OEUVRE = 'oeuvre' export const ROLL_TYPE_OEUVRE = 'oeuvre'
export const ROLL_TYPE_SORT = 'sort' export const ROLL_TYPE_SORT = 'sort'
export const ROLL_TYPE_TACHE = 'tache' export const ROLL_TYPE_TACHE = 'tache'
@@ -12,9 +12,7 @@ export const ROLL_TYPE_TACHE = 'tache'
export const ATTAQUE_ROLL_TYPES = [ROLL_TYPE_ATTAQUE] export const ATTAQUE_ROLL_TYPES = [ROLL_TYPE_ATTAQUE]
export const COMBAT_ROLL_TYPES = [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE] export const COMBAT_ROLL_TYPES = [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE]
export const DEMIREVE_ROLL_TYPES = [ROLL_TYPE_SORT] export const DEMIREVE_ROLL_TYPES = [ROLL_TYPE_SORT]
export const DEFAULT_ROLL_TYPES = [ROLL_TYPE_COMP, ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_CUISINE, ROLL_TYPE_OEUVRE, ROLL_TYPE_TACHE] export const DEFAULT_ROLL_TYPES = [ROLL_TYPE_COMP, ROLL_TYPE_ATTAQUE, ROLL_TYPE_TACHE, ROLL_TYPE_MEDITATION, ROLL_TYPE_CUISINE, ROLL_TYPE_OEUVRE, ROLL_TYPE_JEU]
export const ALL_ROLL_TYPES = [...DEFAULT_ROLL_TYPES, ...COMBAT_ROLL_TYPES, ...DEMIREVE_ROLL_TYPES]
export const DIFF = { export const DIFF = {

View File

@@ -8,7 +8,7 @@ import { RdDItemArme } from "../item/arme.js";
import { RdDBonus } from "../rdd-bonus.js"; import { RdDBonus } from "../rdd-bonus.js";
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js"; import { ITEM_TYPES, RDD_CONFIG } from "../constants.js";
import { CARACS } from "../rdd-carac.js"; import { CARACS } from "../rdd-carac.js";
import { ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"; import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE, ROLL_TYPE_OEUVRE } from "./roll-constants.mjs";
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"; import { PART_ATTAQUE } from "./roll-part-attaque.mjs";
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -27,7 +27,8 @@ export class RollDialogAdapter {
RollDialogAdapter.setRollDataRolled(rollData, rolled, rollTitle) RollDialogAdapter.setRollDataRolled(rollData, rolled, rollTitle)
RollDialogAdapter.adjustRollDataForV1(rollData) RollDialogAdapter.adjustRollDataForV1(rollData)
RollDialogAdapter.adjustAttaqueParticuliere(rollData) RollDialogAdapter.adjustAttaqueParticuliere(rollData)
RollDialogAdapter.adjustAttaqueDmg(rollData)
RollDialogAdapter.adjustDemiSurprise(rollData)
return rolled return rolled
} }
@@ -47,6 +48,10 @@ export class RollDialogAdapter {
rolled.finalLevel = rollData.current.totaldiff rolled.finalLevel = rollData.current.totaldiff
rolled.bonus = rollData.current.bonus ?? 0 rolled.bonus = rollData.current.bonus ?? 0
rolled.factorHtml = Misc.getFractionOneN(rollData.current.sign.diviseur) rolled.factorHtml = Misc.getFractionOneN(rollData.current.sign.diviseur)
if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) {
rolled.niveauNecessaire = RdDResolutionTable.findNiveauNecessaire(rolled.caracValue, rolled.roll)
rolled.ajustementNecessaire = rolled.niveauNecessaire - diff
}
return rolled return rolled
} }
@@ -67,19 +72,20 @@ export class RollDialogAdapter {
if (rollData.ajustements == undefined) { if (rollData.ajustements == undefined) {
rollData.ajustements = {} rollData.ajustements = {}
} }
rollData.selectedCarac = rollData.active.actor.system.carac[rollData.current.carac.key] rollData.selectedCarac = rollData.active.actor.getCaracByName(rollData.current.carac.key)
const compKey = rollData.current.comp?.key const compKey = rollData.current.comp?.key
if (compKey) { if (compKey) {
rollData.competence = rollData.refs[PART_COMP].all.find(it => it.key == compKey)?.comp rollData.competence = rollData.refs[PART_COMP].all.find(it => it.key == compKey)?.comp
rollData.jetResistance = rollData.type.jetResistance rollData.jetResistance = rollData.type.jetResistance
} }
const oeuvreKey = rollData.current.oeuvre?.key if (rollData.type.current == ROLL_TYPE_OEUVRE) {
if (oeuvreKey) { const oeuvreKey = rollData.current.oeuvre?.key
const oeuvreCurrent = rollData.current[PART_OEUVRE]; if (rollData.type.current == ROLL_TYPE_OEUVRE && oeuvreKey) {
rollData.oeuvre = oeuvreCurrent.oeuvre const oeuvreCurrent = rollData.current[PART_OEUVRE];
// rollData.oeuvre = rollData.refs[PART_OEUVRE].oeuvres.find(it => it.key == oeuvreKey)?.oeuvre rollData.oeuvre = oeuvreCurrent.oeuvre
rollData.art = oeuvreCurrent.art.type rollData.art = oeuvreCurrent.art.type
}
} }
// pour appel moral // pour appel moral
rollData.diviseurSignificative = rollData.current.sign rollData.diviseurSignificative = rollData.current.sign
@@ -87,19 +93,30 @@ export class RollDialogAdapter {
rollData.use.moral = true rollData.use.moral = true
} }
if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) { if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) {
rolled.niveauNecessaire = this.findNiveauNecessaire(carac, rolled.roll) rolled.niveauNecessaire = RdDResolutionTable.findNiveauNecessaire(rollData.selectedCarac.value, rolled.roll)
rolled.ajustementNecessaire = rolled.niveauNecessaire - diff rolled.ajustementNecessaire = rolled.niveauNecessaire - diff
} }
rollData.ajustements = rollData.ajustements.map(aj => { rollData.ajustements = rollData.ajustements.map(a => { return { label: a.label, value: a.value } })
return {
used: true,
label: aj.label,
value: aj.diff,
descr: aj.diff == undefined ? aj.label : undefined
}
})
} }
static adjustDemiSurprise(rollData) {
if (rollData.active.surprise == 'demi' && rollData.rolled.isPart) {
RdDResolutionTable.replaceParticuliereDemiSurprise(rollData.rolled)
}
}
static adjustAttaqueDmg(rollData) {
switch (rollData.type.current) {
case ROLL_TYPE_ATTAQUE:
rollData.dmg = RdDBonus.dmgRollV2(rollData, rollData.current.attaque)
break
case ROLL_TYPE_DEFENSE:
rollData.dmg = RdDBonus.dmgRollV2(rollData.attackerRoll, rollData.attackerRoll.current.attaque)
break
}
}
static adjustAttaqueParticuliere(rollData) { static adjustAttaqueParticuliere(rollData) {
if (rollData.type.current != ROLL_TYPE_ATTAQUE || !rollData.rolled.isPart) { if (rollData.type.current != ROLL_TYPE_ATTAQUE || !rollData.rolled.isPart) {
return return
@@ -107,7 +124,7 @@ export class RollDialogAdapter {
const attaque = rollData.current.attaque; const attaque = rollData.current.attaque;
const choix = [] const choix = []
const isEmpoignade = attaque.dmg.mortalite == 'empoignade'; const isEmpoignade = attaque.dmg.isEmpoignade
const isCharge = attaque.tactique == 'charge' const isCharge = attaque.tactique == 'charge'
/* TODO: cas de créatures faisant des lancers, Glou, Glipzouk */ /* TODO: cas de créatures faisant des lancers, Glou, Glipzouk */
const isMeleeDiffNegative = (attaque.comp.type == ITEM_TYPES.competencecreature || rollData.current.carac.key == CARACS.MELEE) const isMeleeDiffNegative = (attaque.comp.type == ITEM_TYPES.competencecreature || rollData.current.carac.key == CARACS.MELEE)
@@ -148,8 +165,6 @@ export class RollDialogAdapter {
comp: attackerRoll.competence, comp: attackerRoll.competence,
main: RdDItemArme.getMainAttaque(attackerRoll.competence), main: RdDItemArme.getMainAttaque(attackerRoll.competence),
equipe: attackerRoll.arme.system.equipe, equipe: attackerRoll.arme.system.equipe,
// carac: { key: caracCode, value: caracValue },
// dommagesArme: dommagesArme,
diff: attackerRoll.diffLibre, diff: attackerRoll.diffLibre,
particuliere: attackerRoll.particuliere, particuliere: attackerRoll.particuliere,
tactique: RdDBonus.find(attackerRoll.tactique), tactique: RdDBonus.find(attackerRoll.tactique),

View File

@@ -43,11 +43,14 @@ import { renderTemplate } from "../constants.js";
import { RollTypeCuisine } from "./roll-type-cuisine.mjs"; import { RollTypeCuisine } from "./roll-type-cuisine.mjs";
import { RollPartCuisine } from "./roll-part-cuisine.mjs"; import { RollPartCuisine } from "./roll-part-cuisine.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2_TEST } from "../settings/options-avancees.js"; import { OptionsAvancees, ROLL_DIALOG_V2_TEST } from "../settings/options-avancees.js";
import { ActorImpacts } from "../technical/actor-impacts.mjs";
import { RollPartEmpoignade } from "./roll-part-empoignade.mjs";
import { RollPartEmpoignadeTaille } from "./roll-part-empoignade-taille.mjs";
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
const ALL_ROLL_TYPES = [ export const ALL_ROLL_TYPES = [
new RollTypeComp(), new RollTypeComp(),
new RollTypeTache(), new RollTypeTache(),
new RollTypeAttaque(), new RollTypeAttaque(),
@@ -84,6 +87,8 @@ const ROLL_PARTS = [
new RollPartConditions(), new RollPartConditions(),
new RollPartEthylisme(), new RollPartEthylisme(),
new RollPartMalusArmure(), new RollPartMalusArmure(),
new RollPartEmpoignadeTaille(),
new RollPartEmpoignade(),
new RollPartEncTotal(), new RollPartEncTotal(),
new RollPartSurEnc(), new RollPartSurEnc(),
new RollPartAppelMoral(), new RollPartAppelMoral(),
@@ -172,15 +177,16 @@ const ROLL_PARTS = [
/* -------------------------------------------- */ /* -------------------------------------------- */
export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2) export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2)
{ {
static onRollDoneDoNothing(dialog) { static onCloseDoNothing() {
}
static onRollDoneDoNothing(dialog, roll) {
dialog.render() dialog.render()
} }
static onRollDoneClose(dialog) { static onRollDoneClose(dialog, roll) {
if (!OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST)) if (roll.type.retry || !OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST))
dialog.close() dialog.close()
} }
static init() { static init() {
} }
@@ -197,7 +203,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
ChatRollResult.onReady() ChatRollResult.onReady()
foundry.applications.handlebars.loadTemplates(ALL_ROLL_TYPES.map(m => m.template)) foundry.applications.handlebars.loadTemplates(ALL_ROLL_TYPES.map(m => m.chatResultTemplate))
foundry.applications.handlebars.loadTemplates(ROLL_PARTS.map(p => p.template)) foundry.applications.handlebars.loadTemplates(ROLL_PARTS.map(p => p.template))
ROLL_PARTS.forEach(p => p.onReady()) ROLL_PARTS.forEach(p => p.onReady())
@@ -235,6 +241,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
static async create(rollData, rollOptions = {}) { static async create(rollData, rollOptions = {}) {
const rollDialog = new RollDialog(rollData, rollOptions) const rollDialog = new RollDialog(rollData, rollOptions)
rollDialog.render(true) rollDialog.render(true)
return rollDialog
} }
static get PARTS() { static get PARTS() {
@@ -292,7 +299,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
return rollData return rollData
} }
static saveParts(rollData) { static saveParts(rollData, impacts) {
const target = RollBasicParts.initFrom(rollData) const target = RollBasicParts.initFrom(rollData)
ROLL_PARTS.filter(p => p.isActive(rollData)) ROLL_PARTS.filter(p => p.isActive(rollData))
.forEach(p => p.storeClean(rollData, target)) .forEach(p => p.storeClean(rollData, target))
@@ -301,12 +308,19 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
target.result = rollData.result target.result = rollData.result
target.done = rollData.done ?? {} target.done = rollData.done ?? {}
target.dmg = rollData.dmg target.dmg = rollData.dmg
if (impacts) {
target.reverse = {
active: impacts.active?.reverseImpacts(),
opponent: impacts.opponent?.reverseImpacts()
}
}
return target return target
} }
constructor(rollData, rollOptions) { constructor(rollData, rollOptions) {
super() super()
this.hooks = []
this.rollData = RollDialog.$prepareRollData(rollData) this.rollData = RollDialog.$prepareRollData(rollData)
this.rollOptions = { this.rollOptions = {
callbacks: [ callbacks: [
@@ -314,13 +328,28 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
async r => await r.active.actor.appliquerAppelMoral(r), async r => await r.active.actor.appliquerAppelMoral(r),
...(rollOptions.callbacks ?? []) ...(rollOptions.callbacks ?? [])
], ],
customChatMessage: rollOptions.customChatMessage, onRollDone: rollOptions.onRollDone ?? RollDialog.onRollDoneDoNothing,
onRollDone: rollOptions.onRollDone ?? RollDialog.onRollDoneDoNothing onClose: rollOptions.onClose ?? RollDialog.onCloseDoNothing
} }
this.chatRollResult = new ChatRollResult(); this.chatRollResult = new ChatRollResult()
this.selectType() this.selectType()
this.registerHooks(rollData);
} }
registerHooks(rollData) {
ROLL_PARTS.filter(p => p.isValid(rollData))
.forEach(p => p.getHooks(this).forEach(h => {
const hook = h.hook;
const id = Hooks.on(hook, h.fn)
this.hooks.push({ hook, id })
}))
}
unregisterHooks() {
this.hooks.forEach(h => Hooks.off(h.hook, h.id))
}
selectType() { selectType() {
const selectedType = this.getSelectedType(); const selectedType = this.getSelectedType();
this.rollData.type.label = selectedType.title(this.rollData) this.rollData.type.label = selectedType.title(this.rollData)
@@ -376,7 +405,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
return RollDialog.getActiveParts(rollData) return RollDialog.getActiveParts(rollData)
.map(p => p.getAjustements(rollData)) .map(p => p.getAjustements(rollData))
.reduce((a, b) => a.concat(b)) .reduce((a, b) => a.concat(b))
.sort((a, b) => a.diff == undefined ? 1 : b.diff == undefined ? -1 : 0) .sort((a, b) => a.value == undefined ? 1 : b.value == undefined ? -1 : 0)
} }
async buildHTMLTable(carac, diff) { async buildHTMLTable(carac, diff) {
@@ -398,7 +427,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
visibleRollParts.forEach(p => p.prepareContext(rollData)) visibleRollParts.forEach(p => p.prepareContext(rollData))
RollDialog.calculAjustements(rollData) RollDialog.calculAjustement(rollData)
const templates = RollDialog.getActiveParts(rollData).map(p => p.toTemplateData()) const templates = RollDialog.getActiveParts(rollData).map(p => p.toTemplateData())
const context = await super._prepareContext() const context = await super._prepareContext()
@@ -420,12 +449,11 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
} }
} }
static calculAjustements(rollData) { static calculAjustement(rollData) {
rollData.ajustements = RollDialog.getAjustements(rollData) rollData.ajustements = RollDialog.getAjustements(rollData)
rollData.ajustements.forEach(it => it.isDiff = it.diff != undefined)
rollData.current.totaldiff = rollData.ajustements rollData.current.totaldiff = rollData.ajustements
.map(adj => adj.diff) .filter(a => a.value != undefined)
.filter(d => d != undefined) .map(a => a.value)
.reduce(Misc.sum(), 0) .reduce(Misc.sum(), 0)
} }
@@ -433,30 +461,47 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
return ALL_ROLL_TYPES.find(m => m.code == this.rollData.type.current) return ALL_ROLL_TYPES.find(m => m.code == this.rollData.type.current)
} }
async close(options) {
if (this.rollOptions.onClose) {
this.rollOptions.onClose()
}
this.unregisterHooks()
return await super.close(options)
}
async roll() { async roll() {
const roll = RollDialog.saveParts(this.rollData) const roll = RollDialog.saveParts(this.rollData)
const selectedRollType = this.getSelectedType(roll);
RollDialog.loadRollData(roll) RollDialog.loadRollData(roll)
const selectedRollType = this.getSelectedType(roll);
selectedRollType.onSelect(roll)
roll.current.resultat = this.rollData.current[PART_TRICHER]?.resultat ?? -1 roll.current.resultat = this.rollData.current[PART_TRICHER]?.resultat ?? -1
roll.choix = {} roll.choix = {}
roll.rolled = await RollDialogAdapter.rollDice(roll, this.rollTitle(roll)) roll.rolled = await RollDialogAdapter.rollDice(roll, this.rollTitle(roll))
roll.result = selectedRollType.getResult(roll)
const impacts = new ActorImpacts(roll.active)
roll.result = selectedRollType.getResult(roll, impacts)
console.info('RollDialog.roll:', roll) console.info('RollDialog.roll:', roll)
const callbacks = [ const callbacks = [
...this.rollOptions.callbacks, ...this.rollOptions.callbacks,
...selectedRollType.callbacks(this.rollOptions), ...selectedRollType.callbacks(this.rollOptions),
] ]
await Promise.all(callbacks.map(async callback => await callback(roll))) await Promise.all(callbacks.map(async callback => await callback(roll)))
await this.chatRollResult.display(roll)
this.rollOptions.onRollDone(this) await impacts.applyImpacts()
selectedRollType.onApplyImpacts(roll, impacts)
await this.chatRollResult.display(roll, impacts)
this.rollOptions.onRollDone(this, roll)
} }
static loadRollData(roll) { static loadRollData(roll) {
RollDialog.$prepareRollData(roll) RollDialog.$prepareRollData(roll)
RollDialog.calculAjustements(roll) RollDialog.calculAjustement(roll)
roll.v2 = true roll.v2 = true
return roll
} }
async defaultCallback(roll, rolled) { async defaultCallback(roll, rolled) {

View File

@@ -1,15 +1,25 @@
import { RDD_CONFIG } from "../constants.js"
import { ATTAQUE_TYPE_MELEE } from "../item/arme.js"
import { RdDBonus } from "../rdd-bonus.js" import { RdDBonus } from "../rdd-bonus.js"
import { DIFF, ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs" import { CARACS } from "../rdd-carac.js"
import { RdDEmpoignade } from "../rdd-empoignade.js"
import { DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP } from "./roll-constants.mjs"
import RollDialog from "./roll-dialog.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs" import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs" import { PART_COMP } from "./roll-part-comp.mjs"
import { PART_DIFF } from "./roll-part-diff.mjs" import { PART_DIFF } from "./roll-part-diff.mjs"
import { RollPartSelect } from "./roll-part-select.mjs" import { RollPartSelect } from "./roll-part-select.mjs"
import { PART_SIGN } from "./roll-part-sign.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs" import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
export const PART_ATTAQUE = 'attaque' export const PART_ATTAQUE = 'attaque'
const TACTIQUES = RdDBonus.tactiques.filter(it => it.isTactique) const TACTIQUES = RdDBonus.tactiques.filter(it => it.isTactique)
const FILTER_ATTAQUE_EMPOIGNADE = attaque => attaque.arme.isEmpoignade()
const FILTER_ATTAQUE_NON_EMPOIGNADE = attaque => !attaque.arme.isEmpoignade()
const FILTER_ATTAQUE_EMPOIGNE = attaque => attaque.arme.isUtilisableEmpoigne() && ATTAQUE_TYPE_MELEE.includes(attaque.main)
export class RollPartAttaque extends RollPartSelect { export class RollPartAttaque extends RollPartSelect {
get code() { return PART_ATTAQUE } get code() { return PART_ATTAQUE }
@@ -20,7 +30,8 @@ export class RollPartAttaque extends RollPartSelect {
loadRefs(rollData) { loadRefs(rollData) {
const refs = this.getRefs(rollData) const refs = this.getRefs(rollData)
const attaques = rollData.active.actor.listAttaques() const attaques = rollData.active.actor.listAttaques()
refs.attaques = attaques.map(it => RollPartAttaque.$extractAttaque(it, rollData.active.actor)) refs.all = attaques.map(it => RollPartAttaque.$extractAttaque(it, rollData.active.actor))
this.filterAttaquesEmpoignade(rollData)
refs.tactiques = TACTIQUES refs.tactiques = TACTIQUES
if (refs.attaques.length > 0) { if (refs.attaques.length > 0) {
const attaque = this.findAttaque(refs.attaques, this.getSaved(rollData)) const attaque = this.findAttaque(refs.attaques, this.getSaved(rollData))
@@ -28,6 +39,10 @@ export class RollPartAttaque extends RollPartSelect {
} }
} }
isAttaqueEmpoignade(it) {
return it.arme.isEmpoignade()
}
store(rollData, targetData) { store(rollData, targetData) {
super.store(rollData, targetData) super.store(rollData, targetData)
this.getSaved(targetData).dmg = this.getCurrent(rollData).dmg this.getSaved(targetData).dmg = this.getCurrent(rollData).dmg
@@ -36,7 +51,7 @@ export class RollPartAttaque extends RollPartSelect {
restore(rollData) { restore(rollData) {
const saved = this.getSaved(rollData) const saved = this.getSaved(rollData)
super.restore(rollData) super.restore(rollData)
if (saved.dmg) { if (saved.dmg != undefined) {
this.getCurrent(rollData).dmg = this.getSaved(rollData).dmg this.getCurrent(rollData).dmg = this.getSaved(rollData).dmg
} }
} }
@@ -50,14 +65,6 @@ export class RollPartAttaque extends RollPartSelect {
choices(refs) { return refs.attaques } choices(refs) { return refs.attaques }
static $extractAttaque(attaque, actor) { static $extractAttaque(attaque, actor) {
// const extracted = foundry.utils.mergeObject({
// key: `${attaque.action}::${attaque.label}`,
// tactique: TACTIQUES[0]
// },
// attaque
// )
// return extracted
// extracted.initialDiff = attaque.comp?.system.default_diffLibre ?? 0
attaque.key = `${attaque.action}::${attaque.label}` attaque.key = `${attaque.action}::${attaque.label}`
attaque.tactique = TACTIQUES[0] attaque.tactique = TACTIQUES[0]
attaque.initialDiff = attaque.comp?.system.default_diffLibre ?? 0 attaque.initialDiff = attaque.comp?.system.default_diffLibre ?? 0
@@ -65,20 +72,28 @@ export class RollPartAttaque extends RollPartSelect {
} }
prepareContext(rollData) { prepareContext(rollData) {
this.filterAttaquesEmpoignade(rollData)
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
current.dmg = RdDBonus.dmgRollV2(rollData, current) current.dmg = RdDBonus.dmgRollV2(rollData, current)
} }
filterAttaquesEmpoignade(rollData) {
const refs = this.getRefs(rollData)
const isEmpoignade = RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId)
refs.isEmpoignadeEnCours = RdDEmpoignade.isEmpoignadeEnCours(rollData.active.actor)
const filterAttaques = isEmpoignade ?
FILTER_ATTAQUE_EMPOIGNADE
: refs.isEmpoignadeEnCours
? FILTER_ATTAQUE_EMPOIGNE
: FILTER_ATTAQUE_NON_EMPOIGNADE
refs.attaques = refs.all.filter(filterAttaques)
}
getAjustements(rollData) { getAjustements(rollData) {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
const ajustements = [] const tactique = current.tactique ? [{ label: current.tactique.label, value: current.tactique.attaque }] : []
if (current.tactique) { const surprise = rollData.opponent?.surprise ? [{ label: rollData.opponent.surprise.label, value: rollData.opponent.surprise.attaque }] : []
ajustements.push({ label: current.tactique.label, diff: current.tactique.attaque }) return [...tactique, ...surprise]
}
if (rollData.opponent?.surprise) {
ajustements.push({ label: rollData.opponent.surprise.label, diff: rollData.opponent.surprise.attaque })
}
return ajustements
} }
@@ -90,6 +105,7 @@ export class RollPartAttaque extends RollPartSelect {
const selectAttaque = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-attaque"]`) const selectAttaque = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-attaque"]`)
const selectTactique = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-tactique"]`) const selectTactique = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-tactique"]`)
const checkMortalite = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="check-mortalite"]`) const checkMortalite = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="check-mortalite"]`)
const utiliserDagueEmpoignade = rollDialog.element.querySelector(`roll-section[name="${this.code}"] a.utiliser-dague-empoignade`)
const current = this.getCurrent(rollDialog.rollData) const current = this.getCurrent(rollDialog.rollData)
selectAttaque.addEventListener("change", e => { selectAttaque.addEventListener("change", e => {
@@ -107,9 +123,26 @@ export class RollPartAttaque extends RollPartSelect {
}) })
checkMortalite?.addEventListener("change", e => { checkMortalite?.addEventListener("change", e => {
current.dmg.mortalite = (e.currentTarget.checked ? 'mortel' : 'non-mortel') current.dmg.mortalite = (e.currentTarget.checked ? RDD_CONFIG.encaissement.mortel : RDD_CONFIG.encaissement.nonmortel)
rollDialog.render() rollDialog.render()
}) })
utiliserDagueEmpoignade?.addEventListener("click", e => {
e.preventDefault()
const rollData = rollDialog.rollData
this.utiliserDagueEmpoignade(rollData)
})
}
utiliserDagueEmpoignade(rollData) {
RollDialog.create({
ids: { actorId: rollData.ids.actorId, actorTokenId: rollData.ids.actorTokenId },
type: { allowed: [ROLL_TYPE_COMP], current: ROLL_TYPE_COMP },
selected: {
carac: { key: CARACS.DEXTERITE, forced: true },
comp: { key: 'Dague', forced: true },
diff: { type: DIFF.IMPOSEE, value: -4 }
}
})
} }
impactOtherPart(part, rollData) { impactOtherPart(part, rollData) {
@@ -123,7 +156,9 @@ export class RollPartAttaque extends RollPartSelect {
part.setDiff(rollData, { type: DIFF.ATTAQUE, value: current.initialDiff }) part.setDiff(rollData, { type: DIFF.ATTAQUE, value: current.initialDiff })
current.initialDiff = undefined current.initialDiff = undefined
} }
break
} }
case PART_SIGN: return part.setArme(rollData, false, current.forceRequise)
} }
} }
return undefined return undefined

View File

@@ -1,3 +1,4 @@
import { Grammar } from "../grammar.js"
import { RollPartSelect } from "./roll-part-select.mjs" import { RollPartSelect } from "./roll-part-select.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs" import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
@@ -12,22 +13,36 @@ export class RollPartCarac extends RollPartSelect {
loadRefs(rollData) { loadRefs(rollData) {
const refs = this.getRefs(rollData) const refs = this.getRefs(rollData)
refs.all = this.$getActorCaracs(rollData) const selected = this.getSelected(rollData)
const actor = rollData.active.actor
refs.all = [...this.$getActorCaracs(actor), ...this.$getCaracCompetenceCreature(actor)]
.filter(c => !selected.forced ||
(selected.key ?
Grammar.includesLowerCaseNoAccent(c.label, selected.key)
: c.key == '')
)
refs.caracs = refs.all refs.caracs = refs.all
this.$selectCarac(rollData) this.$selectCarac(rollData)
} }
choices(refs) { return refs.caracs } choices(refs) { return refs.caracs }
$getActorCaracs(rollData) { $getActorCaracs(actor) {
return Object.entries(rollData.active.actor.getCarac()) return Object.entries(actor.getCarac())
.filter(([key, c]) => key != 'taille') .filter(([key, c]) => key != 'taille')
/* TODO: filter by context */
.map(([key, carac]) => { .map(([key, carac]) => {
return RollPartCarac.$extractCarac(key, carac) return RollPartCarac.$extractCarac(key, carac)
}) })
} }
$getCaracCompetenceCreature(actor) {
if (actor.isPersonnage()) {
return []
}
return actor.getCompetences()
.map(it => { return { key: it.name, label: it.name, value: parseInt(it.system.carac_value) } })
}
static $extractCarac(key, carac) { static $extractCarac(key, carac) {
return { return {
key: key, key: key,
@@ -40,7 +55,6 @@ export class RollPartCarac extends RollPartSelect {
allowed = allowed.filter(it => it != undefined) allowed = allowed.filter(it => it != undefined)
const refs = this.getRefs(rollData) const refs = this.getRefs(rollData)
refs.caracs = allowed.length > 0 refs.caracs = allowed.length > 0
// ? refs.all.filter(it => allowed.includes(Grammar.toLowerCaseNoAccent(it.key)))
? refs.all.filter(it => allowed.includes(it.key)) ? refs.all.filter(it => allowed.includes(it.key))
: refs.all : refs.all
this.$selectCarac(rollData) this.$selectCarac(rollData)

View File

@@ -35,7 +35,7 @@ export class RollPartCheckbox extends RollPart {
getAjustements(rollData) { getAjustements(rollData) {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
if (current.checked) { if (current.checked) {
return [{ label: this.getCheckboxLabelAjustement(rollData), diff: current.value }] return [{ label: this.getCheckboxLabelAjustement(rollData), value: current.value }]
} }
return [] return []
} }

View File

@@ -47,7 +47,7 @@ export class RollPartCoeur extends RollPartSelect {
if (current.key != '') { if (current.key != '') {
return [{ return [{
label: "Coeur pour " + current.label, label: "Coeur pour " + current.label,
diff: current.value value: current.value
}] }]
} }
return [] return []

View File

@@ -18,13 +18,16 @@ export class RollPartComp extends RollPartSelect {
loadRefs(rollData) { loadRefs(rollData) {
const refs = this.getRefs(rollData) const refs = this.getRefs(rollData)
const selected = this.getSelected(rollData) const selected = this.getSelected(rollData)
refs.all = this.$getActorComps(rollData) const all = this.$getActorComps(rollData)
.filter(comp => !selected.forced || if (selected.forced) {
(selected.key ? refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selected.key))
Grammar.includesLowerCaseNoAccent(comp.name, selected.key) if (refs.all.length == 0) {
: comp.key == '') refs.all = all.filter(comp => Grammar.includesLowerCaseNoAccent(comp.label, selected.key))
) }
}
else {
refs.all = all
}
refs.comps = refs.all refs.comps = refs.all
this.$selectComp(rollData) this.$selectComp(rollData)
} }
@@ -33,7 +36,7 @@ export class RollPartComp extends RollPartSelect {
$getActorComps(rollData) { $getActorComps(rollData) {
const competences = (rollData.active.actor?.getCompetences() ?? []) const competences = (rollData.active.actor?.getCompetences() ?? [])
.map(RollPartComp.$extractComp) .map(RollPartComp.extractComp)
.sort(Misc.ascending(it => Grammar.toLowerCaseNoAccentNoSpace(it.label))) .sort(Misc.ascending(it => Grammar.toLowerCaseNoAccentNoSpace(it.label)))
/* TODO: filter competences */ /* TODO: filter competences */
const listCompetences = [ const listCompetences = [
@@ -43,7 +46,7 @@ export class RollPartComp extends RollPartSelect {
return listCompetences return listCompetences
} }
static $extractComp(comp) { static extractComp(comp) {
return { return {
key: comp.name, key: comp.name,
label: comp.name, label: comp.name,
@@ -52,12 +55,16 @@ export class RollPartComp extends RollPartSelect {
} }
} }
filterComps(rollData, allowed = []) { filterComps(rollData, allowed = [], sorting = undefined) {
const sans = allowed.includes('')
allowed = allowed.filter(it => it != undefined) allowed = allowed.filter(it => it != undefined)
const refs = this.getRefs(rollData) const refs = this.getRefs(rollData)
refs.comps = allowed.length > 0 refs.comps = allowed.length > 0
? refs.all.filter(it => allowed.includes(it.label)) ? refs.all.filter(it => allowed.includes(it.label) || (sans && it.key == ''))
: refs.all : refs.all
if (sorting && refs.comps.length > 0) {
refs.comps.sort(sorting)
}
this.$selectComp(rollData) this.$selectComp(rollData)
} }
@@ -66,7 +73,7 @@ export class RollPartComp extends RollPartSelect {
} }
setSpecialComp(rollData, comps) { setSpecialComp(rollData, comps) {
this.getRefs(rollData).comps = comps.map(RollPartComp.$extractComp) this.getRefs(rollData).comps = comps.map(RollPartComp.extractComp)
.sort(Misc.ascending(it => Grammar.toLowerCaseNoAccentNoSpace(it.label))) .sort(Misc.ascending(it => Grammar.toLowerCaseNoAccentNoSpace(it.label)))
} }

View File

@@ -57,7 +57,7 @@ export class RollPartConditions extends RollPart {
getAjustements(rollData) { getAjustements(rollData) {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
if (current.value != 0) { if (current.value != 0) {
return [{ label: DESCR_CONDITIONS, diff: current.value }] return [{ label: DESCR_CONDITIONS, value: current.value }]
} }
return [] return []
} }

View File

@@ -19,55 +19,153 @@ export class RollPartCuisine extends RollPartSelect {
isValid(rollData) { return rollData.active.actor.isPersonnage() } isValid(rollData) { return rollData.active.actor.isPersonnage() }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_CUISINE) } visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_CUISINE) }
restore(rollData) {
super.restore(rollData)
this.$restoreSavedOptions(rollData)
}
store(rollData, targetData) {
const current = this.getCurrent(rollData)
this.setSaved(targetData, {
key: current.key,
fabriquer: current.fabriquer,
proportions: current.proportions,
value: current.value,
})
}
loadRefs(rollData) { loadRefs(rollData) {
const refs = this.getRefs(rollData) const refs = this.getRefs(rollData)
refs.recettes = rollData.active.actor.items const actor = rollData.active.actor
refs.cuisine = actor.getCompetence('Cuisine')
const recettes = actor.items
.filter(it => it.type == ITEM_TYPES.recettecuisine) .filter(it => it.type == ITEM_TYPES.recettecuisine)
.map(it => RollPartCuisine.$extractRecette(it, rollData.active.actor)) .map(RollPartCuisine.$extractPreparationRecette)
if (refs.recettes.length > 0) {
this.$selectRecette(rollData) const ingredientsBruts = actor.items
.filter(it => it.getUtilisationCuisine() == 'brut')
.map(RollPartCuisine.$extractPreparationBrut)
refs.preparations = [RollPartCuisine.$preparationBasique(), ...recettes, ...ingredientsBruts]
refs.preparations.forEach(p => p.comp = refs.cuisine)
if (refs.preparations.length > 0) {
this.$selectPreparation(rollData)
this.$restoreSavedOptions(rollData)
} }
} }
choices(refs) { return refs.recettes } $restoreSavedOptions(rollData) {
const saved = this.getSaved(rollData)
const current = this.getCurrent(rollData)
if (saved.fabriquer != undefined) {
current.fabriquer = saved.fabriquer
}
if (saved.proportions != undefined) {
current.proportions = saved.proportions
}
if (saved.value != undefined) {
current.value = saved.value
}
}
static $extractRecette(recette, actor) { choices(refs) { return refs.preparations }
static $preparationBasique() {
return {
key: '',
label: "Improvisation du moment",
img: RollPartCuisine.$getImgIngredient(),
sust: 1,
exotisme: 0,
ingredients: "Ce qu'il y a sous la main",
proportions: 8,
proportionsMax: 50,
value: 0,
fabriquer: false,
}
}
static $extractPreparationRecette(recette) {
const proportions = recette.system.sust ?? 1
return { return {
key: recette.id, key: recette.id,
label: recette.name, label: recette.name,
caracs: RollPartCuisine.getCaracs(recette), img: 'systems/foundryvtt-reve-de-dragon/icons/cuisine/ragout.svg',
qualite: recette.system.niveau, sust: 1,
exotisme: recette.system.exotisme,
ingredients: recette.system.ingredients,
proportions: proportions,
proportionsMax: proportions * 10,
value: -recette.system.niveau, value: -recette.system.niveau,
recette: recette, recette: recette,
comp: actor.getCompetence('Cuisine') fabriquer: true,
} }
} }
static getCaracs(recette){
// TODO: permettre différentes caractéristiques pour la cuisine? static $extractPreparationBrut(ingredient) {
return [CARACS.ODORATGOUT, CARACS.EMPATHIE, CARACS.DEXTERITE] return {
key: ingredient.id,
label: ingredient.name + ' cuisiné',
img: RollPartCuisine.$getImgIngredient(ingredient.type),
sust: ingredient.system.sust ?? 1,
exotisme: ingredient.system.exotisme,
ingredients: ingredient.name,
proportions: Math.min(10, ingredient.system.quantite),
proportionsMax: Math.min(50, ingredient.system.quantite),
value: 0,
ingredient: ingredient,
fabriquer: true,
}
} }
$selectRecette(rollData, key) { static $getImgIngredient(type = ITEM_TYPES.ingredient) {
switch (type) {
case ITEM_TYPES.herbe:
case ITEM_TYPES.plante:
return `systems/foundryvtt-reve-de-dragon/icons/cuisine/${type}.svg`
case ITEM_TYPES.faune:
return 'systems/foundryvtt-reve-de-dragon/icons/cuisine/gibier.svg'
}
return 'systems/foundryvtt-reve-de-dragon/icons/cuisine/ragout.svg'
}
$selectPreparation(rollData, key) {
this.selectByKey(rollData, key, 0) this.selectByKey(rollData, key, 0)
} }
async _onRender(rollDialog, context, options) { async _onRender(rollDialog, context, options) {
const selectRecette = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-recette"]`) const current = this.getCurrent(rollDialog.rollData)
selectRecette.addEventListener("change", e => { const selectPreparation = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-preparation"]`)
const inputDiff = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="diff-var"]`)
const checkboxFabriquer = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="fabriquer"]`)
const inputProportions = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="proportions"]`)
selectPreparation.addEventListener("change", e => {
const selectOptions = e.currentTarget.options const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex const index = selectOptions.selectedIndex
this.$selectRecette(rollDialog.rollData, selectOptions[index]?.value) this.$selectPreparation(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.render() rollDialog.render()
}) })
checkboxFabriquer?.addEventListener("change", e => {
current.fabriquer = e.currentTarget.checked
})
inputDiff?.addEventListener("change", e => {
current.value = parseInt(e.currentTarget.value)
})
inputProportions?.addEventListener("change", e => {
current.proportions = parseInt(e.currentTarget.value)
})
} }
impactOtherPart(part, rollData) { impactOtherPart(part, rollData) {
if (this.visible(rollData)) { if (this.visible(rollData)) {
const current = this.getCurrent(rollData)
switch (part.code) { switch (part.code) {
case PART_CARAC: return part.filterCaracs(rollData, current.caracs) case PART_CARAC: return part.filterCaracs(rollData, [CARACS.ODORATGOUT])
case PART_COMP: return part.filterComps(rollData, [current.comp?.name]) case PART_COMP: return part.filterComps(rollData, [this.getRefs(rollData).cuisine.name])
} }
} }
return undefined return undefined

View File

@@ -1,9 +1,6 @@
import { ITEM_TYPES } from "../constants.js" import { ITEM_TYPES, RDD_CONFIG } from "../constants.js"
import { Grammar } from "../grammar.js"
import { ATTAQUE_TYPE, RdDItemArme } from "../item/arme.js" import { ATTAQUE_TYPE, RdDItemArme } from "../item/arme.js"
import { RdDBonus } from "../rdd-bonus.js"
import { CARACS } from "../rdd-carac.js" import { CARACS } from "../rdd-carac.js"
import { StatusEffects } from "../settings/status-effects.js"
import { DIFF, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs" import { DIFF, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs" import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs" import { PART_COMP } from "./roll-part-comp.mjs"
@@ -18,6 +15,8 @@ export class RollPartDefense extends RollPartSelect {
get code() { return PART_DEFENSE } get code() { return PART_DEFENSE }
get section() { return ROLLDIALOG_SECTION.CHOIX } get section() { return ROLLDIALOG_SECTION.CHOIX }
isValid(rollData) { return rollData.attackerRoll != undefined }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) } visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) }
static getDiffAttaque(attackerRoll) { static getDiffAttaque(attackerRoll) {
@@ -30,13 +29,22 @@ export class RollPartDefense extends RollPartSelect {
const attackerRoll = rollData.attackerRoll const attackerRoll = rollData.attackerRoll
const defenseur = rollData.active.actor const defenseur = rollData.active.actor
refs.isDistance = [ATTAQUE_TYPE.TIR, ATTAQUE_TYPE.LANCER].find(it => it == attackerRoll?.main) refs.isDistance = [ATTAQUE_TYPE.TIR, ATTAQUE_TYPE.LANCER].find(it => it == attackerRoll?.main)
const esquives = refs.isDistance == ATTAQUE_TYPE.TIR ? [] : defenseur.getCompetencesEsquive() const isEmpoignade = attackerRoll.dmg.isEmpoignade
.map(it => RollPartDefense.$extractEsquive(it, defenseur)) const isEmpoignadeEnCours = isEmpoignade && defenseur.itemTypes[ITEM_TYPES.empoignade].find(it =>
[it.system.empoigneurid, it.system.empoigneid].includes(rollData.ids.opponentId) &&
it.system.pointsemp != 0)
const parades = defenseur.items.filter(it => it.isParade() && (!refs.isDistance || it.isBouclier())) const esquives = (refs.isDistance == ATTAQUE_TYPE.TIR || isEmpoignadeEnCours)
.map(it => RollPartDefense.$extractParade(it, attackerRoll?.arme, defenseur)) ? []
: defenseur.getCompetencesEsquive()
const parades = isEmpoignade
? [RdDItemArme.empoignade(defenseur)]
: defenseur.items.filter(it => it.isParade() && (!refs.isDistance || it.isBouclier()))
refs.defenses = [...esquives, ...parades].filter(it => it != undefined) refs.defenses = [
...esquives.map(it => RollPartDefense.$extractEsquive(it, defenseur)),
...parades.map(it => RollPartDefense.$extractParade(it, attackerRoll?.arme, defenseur))
]
this.$selectDefense(rollData) this.$selectDefense(rollData)
} }
@@ -104,7 +112,7 @@ export class RollPartDefense extends RollPartSelect {
case PART_CARAC: return part.filterCaracs(rollData, [current.carac]) case PART_CARAC: return part.filterCaracs(rollData, [current.carac])
case PART_COMP: return part.filterComps(rollData, [current.comp?.name]) case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
case PART_DIFF: return part.setDiff(rollData, this.getDiffDefense(rollData)) case PART_DIFF: return part.setDiff(rollData, this.getDiffDefense(rollData))
case PART_SIGN: return part.setArmeDisparate(rollData, this.isArmeDisparate(rollData)) case PART_SIGN: return part.setArme(rollData, this.isArmeDisparate(rollData), current.forceRequise)
} }
} }
return undefined return undefined
@@ -113,7 +121,7 @@ export class RollPartDefense extends RollPartSelect {
isArmeDisparate(rollData) { isArmeDisparate(rollData) {
const armeDefense = this.getCurrent(rollData).arme const armeDefense = this.getCurrent(rollData).arme
if (armeDefense) { if (armeDefense) {
const armeAttaque = rollData.attackerRoll?.arme const armeAttaque = rollData.attackerRoll?.current.attaque.arme
return RdDItemArme.defenseArmeParade(armeAttaque, armeDefense) == 'sign' return RdDItemArme.defenseArmeParade(armeAttaque, armeDefense) == 'sign'
} }
return false return false
@@ -126,7 +134,11 @@ export class RollPartDefense extends RollPartSelect {
return { diff: 0, type: DIFF.LIBRE } return { diff: 0, type: DIFF.LIBRE }
} }
else { else {
return { diff: rollData.attackerRoll.diff ?? 0, type: DIFF.DEFENSE } const attackerRoll = rollData.attackerRoll
const diff = attackerRoll.v2
? attackerRoll.selected.diff.value
: attackerRoll.diff
return { diff: diff ?? 0, type: DIFF.DEFENSE }
} }
} }
} }

View File

@@ -1,10 +1,15 @@
import { DIFF, DIFFS, ROLL_TYPE_MEDITATION, ROLL_TYPE_OEUVRE, ROLL_TYPE_SORT, ROLL_TYPE_TACHE } from "./roll-constants.mjs"; import { DIFF, DIFFS, ROLL_TYPE_CUISINE, ROLL_TYPE_MEDITATION, ROLL_TYPE_OEUVRE, ROLL_TYPE_SORT, ROLL_TYPE_TACHE } from "./roll-constants.mjs";
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"; import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
export const PART_DIFF = "diff" export const PART_DIFF = "diff"
const EXCLUDED_ROLL_TYPES = [ROLL_TYPE_TACHE, ROLL_TYPE_MEDITATION, ROLL_TYPE_SORT, ROLL_TYPE_OEUVRE] const EXCLUDED_ROLL_TYPES = [
ROLL_TYPE_TACHE,
ROLL_TYPE_MEDITATION,
ROLL_TYPE_SORT,
ROLL_TYPE_CUISINE,
ROLL_TYPE_OEUVRE]
export class RollPartDiff extends RollPart { export class RollPartDiff extends RollPart {
@@ -53,15 +58,15 @@ export class RollPartDiff extends RollPart {
setDiff(rollData, diff) { setDiff(rollData, diff) {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
current.value = diff.diff current.value = diff.diff ?? current.value
current.type = diff.type current.type = diff.type ?? current.type
} }
getAjustements(rollData) { getAjustements(rollData) {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
return [{ return [{
label: current.label, label: current.label,
diff: current.value value: current.value
}] }]
} }

View File

@@ -0,0 +1,40 @@
import { RDD_CONFIG } from "../constants.js"
import { ATTAQUE_TYPE_MELEE } from "../item/arme.js"
import { RdDEmpoignade } from "../rdd-empoignade.js"
import { COMBAT_ROLL_TYPES } from "./roll-constants.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
const EMPOIGNADE_TAILLE = "empoignade-taille"
export class RollPartEmpoignadeTaille extends RollPartCheckbox {
get code() { return EMPOIGNADE_TAILLE }
isValid(rollData) {
return RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId)
}
visible(rollData) {
return COMBAT_ROLL_TYPES.includes(rollData.type.current) &&
RdDEmpoignade.isEmpoignadeEnCours(rollData.active.actor) &&
this.getTailleDiff(rollData) != 0
}
getTailleDiff(rollData) {
const taille = rollData.active.actor.getTaille()
const tailleOpponent = rollData.opponent.actor.getTaille()
const diff = taille - tailleOpponent
const diffTailleAbs = Math.max(0, Math.abs(diff) - 1)
const signDiff = Math.sign(diff)
return signDiff * diffTailleAbs
}
getCheckboxIcon(rollData) { return `<img src="${RDD_CONFIG.icons.empoignade}">` }
getCheckboxLabel(rollData) {
return `Taille ${rollData.active.actor.getTaille()} vs ${rollData.opponent.actor.getTaille()} `
}
getCheckboxValue(rollData) {
return this.getTailleDiff(rollData)
}
}

View File

@@ -0,0 +1,30 @@
import { RDD_CONFIG } from "../constants.js"
import { ATTAQUE_TYPE_MELEE } from "../item/arme.js"
import { RdDEmpoignade } from "../rdd-empoignade.js"
import { ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
const EMPOIGNADE = "empoignade"
export class RollPartEmpoignade extends RollPartCheckbox {
get code() { return EMPOIGNADE }
isValid(rollData) {
return RdDEmpoignade.isCombatantEmpoignade(rollData.ids.opponentId, rollData.ids.opponentTokenId) &&
!RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId)
}
visible(rollData) {
return rollData.type.current == ROLL_TYPE_ATTAQUE &&
ATTAQUE_TYPE_MELEE.includes(rollData.current[PART_ATTAQUE].main) &&
RdDEmpoignade.isCombatantEmpoignade(rollData.ids.opponentId, rollData.ids.opponentTokenId) &&
!RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId) &&
!RdDEmpoignade.isEmpoignadeEnCours(rollData.active.actor)
}
getCheckboxIcon(rollData) { return `<img src="${RDD_CONFIG.icons.empoignade}">` }
getCheckboxLabel(rollData) { return "vs. empoigneur" }
getCheckboxValue(rollData) { return 4 }
}

View File

@@ -1,3 +1,4 @@
import { RDD_CONFIG } from "../constants.js"
import { RdDItemCompetence } from "../item-competence.js" import { RdDItemCompetence } from "../item-competence.js"
import { RdDCarac } from "../rdd-carac.js" import { RdDCarac } from "../rdd-carac.js"
import { RollPartCheckbox } from "./roll-part-checkbox.mjs" import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
@@ -25,7 +26,7 @@ export class RollPartEncTotal extends RollPartCheckbox {
}) })
} }
getCheckboxIcon(rollData) { return '<i class="fa-solid fa-weight-hanging"></i>' } getCheckboxIcon(rollData) { return `<img src="${RDD_CONFIG.icons.surenc}">` }
getCheckboxLabel(rollData) { return "Enc. total" } getCheckboxLabel(rollData) { return "Enc. total" }
getCheckboxValue(rollData) { return - rollData.active.actor.getEncTotal() } getCheckboxValue(rollData) { return - rollData.active.actor.getEncTotal() }
} }

View File

@@ -1,15 +1,16 @@
import { Grammar } from "../grammar.js"
import { ITEM_TYPES } from "../constants.js" import { ITEM_TYPES } from "../constants.js"
import { CARACS } from "../rdd-carac.js" import { CARACS } from "../rdd-carac.js"
import { ROLL_TYPE_JEU } from "./roll-constants.mjs" import { ROLL_TYPE_JEU } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs" import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs" import { PART_COMP, RollPartComp } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs" import { RollPartSelect } from "./roll-part-select.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs" import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
import { RdDItem } from "../item.js"
import { Misc } from "../misc.js"
export const PART_JEU = "jeu" export const PART_JEU = "jeu"
const COMPETENCE_JEU = 'Jeu' export const COMPETENCE_JEU = 'Jeu'
export class RollPartJeu extends RollPartSelect { export class RollPartJeu extends RollPartSelect {
@@ -21,8 +22,12 @@ export class RollPartJeu extends RollPartSelect {
loadRefs(rollData) { loadRefs(rollData) {
const refs = this.getRefs(rollData) const refs = this.getRefs(rollData)
refs.jeux = rollData.active.actor.itemTypes[ITEM_TYPES.jeu] const actor = rollData.active.actor
.map(it => RollPartJeu.$extractJeu(it, rollData.active.actor)) const compJeu = actor.getCompetence(COMPETENCE_JEU)
refs.jeux = actor.itemTypes[ITEM_TYPES.jeu]
.map(it => RollPartJeu.$extractJeu(it, compJeu))
if (refs.jeux.length > 0) { if (refs.jeux.length > 0) {
this.$selectJeu(rollData) this.$selectJeu(rollData)
} }
@@ -30,18 +35,17 @@ export class RollPartJeu extends RollPartSelect {
choices(refs) { return refs.jeux } choices(refs) { return refs.jeux }
static $extractJeu(jeu, actor) { static $extractJeu(jeu, compJeu) {
const comp = actor.getCompetence(COMPETENCE_JEU)
const caracs = jeu.system.caraccomp.toLowerCase().split(/[.,:\/-]/).map(it => it.trim()) const caracs = jeu.system.caraccomp.toLowerCase().split(/[.,:\/-]/).map(it => it.trim())
const base = RollPartJeu.$getJeuBase(jeu, comp, caracs) const base = RollPartJeu.$getJeuBase(jeu, compJeu, caracs)
return { return {
key: jeu.id, key: jeu.id,
label: jeu.name, label: jeu.name,
caracs: caracs, caracs: caracs,
jeu: jeu, jeu: jeu,
value: (base ?? comp).system.niveau, value: 0,
base: base, base: base,
comp: comp comp: compJeu
} }
} }
@@ -49,10 +53,10 @@ export class RollPartJeu extends RollPartSelect {
if (jeu.system.base < comp.system.niveau) { if (jeu.system.base < comp.system.niveau) {
return undefined return undefined
} }
return { return new RdDItem({
id: comp.id, id: comp.id,
name: `Jeu ${jeu.name}`, name: `Jeu ${Misc.lowerFirst(jeu.name)}`,
type: comp.type, type: ITEM_TYPES.competence,
img: comp.img, img: comp.img,
system: foundry.utils.mergeObject( system: foundry.utils.mergeObject(
{ {
@@ -61,9 +65,9 @@ export class RollPartJeu extends RollPartSelect {
default_carac: caracs.length > 0 ? caracs[0] : CARACS.CHANCE default_carac: caracs.length > 0 ? caracs[0] : CARACS.CHANCE
}, },
comp.system, comp.system,
{ inplace: true, overwrite: false } { overwrite: false }
) )
} })
} }
prepareContext(rollData) { prepareContext(rollData) {
@@ -77,6 +81,15 @@ export class RollPartJeu extends RollPartSelect {
$selectJeu(rollData, key) { $selectJeu(rollData, key) {
this.selectByKey(rollData, key, 0) this.selectByKey(rollData, key, 0)
if (rollData.type.current == ROLL_TYPE_JEU) {
RollPartJeu.forceCompJeu(rollData)
}
}
static forceCompJeu(rollData) {
const jeu = rollData.current[PART_JEU].base ?? rollData.current[PART_JEU].comp
rollData.refs[PART_COMP].comps = [jeu].map(it => RollPartComp.extractComp(it))
rollData.current[PART_COMP] = rollData.refs[PART_COMP].comps[0]
} }
async _onRender(rollDialog, context, options) { async _onRender(rollDialog, context, options) {
@@ -95,7 +108,7 @@ export class RollPartJeu extends RollPartSelect {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
switch (part.code) { switch (part.code) {
case PART_CARAC: return part.filterCaracs(rollData, current.caracs) case PART_CARAC: return part.filterCaracs(rollData, current.caracs)
case PART_COMP: return part.filterComps(rollData,[current.comp?.name]) case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
} }
} }
return undefined return undefined

View File

@@ -1,10 +1,10 @@
import { ITEM_TYPES } from "../constants.js" import { ITEM_TYPES } from "../constants.js"
import { Grammar } from "../grammar.js" import { Grammar } from "../grammar.js"
import { CARACS, RdDCarac } from "../rdd-carac.js" import { CARACS } from "../rdd-carac.js"
import { RdDTimestamp } from "../time/rdd-timestamp.js" import { RdDTimestamp } from "../time/rdd-timestamp.js"
import { TMRUtility } from "../tmr-utility.js" import { TMRUtility } from "../tmr-utility.js"
import { ROLL_TYPE_MEDITATION } from "./roll-constants.mjs" import { ROLL_TYPE_MEDITATION } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs" import { PART_CARAC, RollPartCarac } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs" import { PART_COMP } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs" import { RollPartSelect } from "./roll-part-select.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs" import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
@@ -34,8 +34,9 @@ export class RollPartMeditation extends RollPartSelect {
loadRefs(rollData) { loadRefs(rollData) {
const refs = this.getRefs(rollData) const refs = this.getRefs(rollData)
refs.meditations = rollData.active.actor.itemTypes[ITEM_TYPES.meditation] const actor = rollData.active.actor
.map(it => RollPartMeditation.$extractMeditation(it, rollData.active.actor)) refs.meditations = actor.itemTypes[ITEM_TYPES.meditation]
.map(it => RollPartMeditation.$extractMeditation(it, actor))
if (refs.meditations.length > 0) { if (refs.meditations.length > 0) {
this.$selectMeditation(rollData) this.$selectMeditation(rollData)
@@ -72,9 +73,10 @@ export class RollPartMeditation extends RollPartSelect {
} }
getAjustements(rollData) { getAjustements(rollData) {
const malusEchecs = { label: "Méditation", diff: this.getMalusEchecs(rollData) } const malus = this.getMalusEchecs(rollData)
const malusConditions = { label: "Conditions", diff: this.getMalusConditions(rollData) } const malusEchecs = malus == 0 ? [] : [{ label: "ditation", value: malus }]
return [malusConditions, ...(malusEchecs.diff == 0 ? [] : [malusEchecs])] const malusConditions = { label: "Conditions", value: this.getMalusConditions(rollData) }
return [malusConditions, ...malusEchecs]
} }
$selectMeditation(rollData, key) { $selectMeditation(rollData, key) {

View File

@@ -16,7 +16,7 @@ export class RollPartSelect extends RollPart {
getAjustements(rollData) { getAjustements(rollData) {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
if (current) { if (current) {
return [{ label: current.label, diff: current.value }] return [{ label: current.label, value: current.value }]
} }
return [] return []
} }
@@ -27,7 +27,7 @@ export class RollPartSelect extends RollPart {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
const newChoice = (choices.length == 0) const newChoice = (choices.length == 0)
? { key: '', value: defValue } ? { key: '', value: defValue }
: this.$getSelectedChoice(choices, key ?? current?.key ?? refs?.key ?? '') : this.$getSelectedChoice(choices, key ?? current?.key ?? refs?.key ?? choices[0].key)
this.setCurrent(rollData, newChoice) this.setCurrent(rollData, newChoice)
return newChoice return newChoice
} }

View File

@@ -1,6 +1,7 @@
import { RDD_CONFIG } from "../constants.js"
import { Misc } from "../misc.js" import { Misc } from "../misc.js"
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js" import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
import { StatusEffects } from "../settings/status-effects.js" import { demiReveStatusEffect, StatusEffects } from "../settings/status-effects.js"
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs" import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs" import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
@@ -39,29 +40,30 @@ export class RollPartSign extends RollPart {
const isCombat = this.isCombat(rollData) const isCombat = this.isCombat(rollData)
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
current.armeDisparate = isCombat && current.armeDisparate current.armeDisparate = isCombat && current.armeDisparate
current.surprise = actor.getSurprise(isCombat) // TODO: could be from rollData.active.surprise?? current.surprise = actor.getSurprise(isCombat, current.forceRequise ?? 0)
current.reasons = actor.getEffects(it => StatusEffects.niveauSurprise(it) > 0).map(it => it.name) current.reasons = actor.getEffects(it => StatusEffects.niveauSurprise(it, isCombat) > 0, current.forceRequise ?? 0)
.map(it => { return { img: it.img, label: game.i18n.localize(it.name) } })
current.diviseur = 1 current.diviseur = 1
if (current.surprise == 'demi') { if (current.surprise == 'demi') {
current.diviseur *= 2 current.diviseur *= 2
} }
if (isCombat && actor.isDemiReve()) { if (isCombat && actor.isDemiReve()) {
current.reasons.push('Demi-rêve en combat') current.reasons.push({ img: RDD_CONFIG.icons.demiReve, label: 'Demi-rêve en combat' })
} }
if (this.isParadeArmeDisparate(current)) { if (this.isParadeArmeDisparate(current)) {
current.diviseur *= 2 current.diviseur *= 2
current.reasons.push('Armes disparates') current.reasons.push({ img: RDD_CONFIG.icons.armesDisparates, label: 'Armes disparates' })
} }
if (this.isAttaqueFinesse(rollData)) { if (this.isAttaqueFinesse(rollData)) {
current.diviseur *= 2 current.diviseur *= 2
current.reasons.push('Particulière en finesse') current.reasons.push({ img: RDD_CONFIG.particuliere.finesse.img, label: 'Particulière en finesse' })
} }
if (!ReglesOptionnelles.isUsing('tripleSignificative')) { if (!ReglesOptionnelles.isUsing('tripleSignificative')) {
current.diviseur = Math.min(current.diviseur, 4); current.diviseur = Math.min(current.diviseur, 4);
} }
current.reason = current.reasons.join(', ') current.reason = current.reasons.map(it => it.label).join(', ')
} }
isAttaqueFinesse(rollData) { isAttaqueFinesse(rollData) {
@@ -76,8 +78,16 @@ export class RollPartSign extends RollPart {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
if (current.surprise == 'demi') { if (current.surprise == 'demi') {
return [ return [
{ label: 'Significative requise ' + Misc.getFractionOneN(current.diviseur), diff: undefined }, {
...current.reasons.map(it => { return { label: '<i class="fa-solid fa-triangle-exclamation"></i> ' + it, diff: undefined } }) label: 'Significative requise ' + Misc.getFractionOneN(current.diviseur)
},
...current.reasons.map(it => {
return {
label: it.img
? `<img src="${it.img}"> ${it.label}`
: `<i class="fa-solid fa-triangle-exclamation"></i> ${it.label}`
}
})
] ]
} }
return [] return []
@@ -92,7 +102,9 @@ export class RollPartSign extends RollPart {
}) })
} }
setArmeDisparate(rollData, armeDisparate) { setArme(rollData, armeDisparate, forceRequise) {
this.getCurrent(rollData).armeDisparate = armeDisparate const current = this.getCurrent(rollData)
current.armeDisparate = armeDisparate
current.forceRequise = forceRequise
} }
} }

View File

@@ -11,19 +11,39 @@ import { CARACS } from "../rdd-carac.js"
export const PART_SORT = "sort" export const PART_SORT = "sort"
export class RollPartSort extends RollPartSelect { export class RollPartSort extends RollPartSelect {
onReady() { onReady() {
// TODO: utiliser un hook pour écouter les déplacements dans les TMRs? // TODO: utiliser un hook pour écouter les déplacements dans les TMRs?
} }
get code() { return PART_SORT } get code() { return PART_SORT }
get section() { return ROLLDIALOG_SECTION.CHOIX } get section() { return ROLLDIALOG_SECTION.CHOIX }
isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() } isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_SORT) } visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_SORT) }
restore(rollData) {
const saved = this.getSaved(rollData)
this.setCurrent(rollData, {
key: saved.key,
isReserve: saved.isReserve,
ptreve: saved.ptreve
})
}
store(rollData, targetData) {
const current = this.getCurrent(rollData)
this.setSaved(targetData, {
key: current.key,
isReserve: current.isReserve,
ptreve: current.ptreve
})
}
loadRefs(rollData) { loadRefs(rollData) {
const refs = this.getRefs(rollData) const refs = this.getRefs(rollData)
const coord = rollData.active.actor.system.reve.tmrpos.coord const coord = this.getCoord(rollData)
const draconics = rollData.active.actor.getDraconicList() const draconics = rollData.active.actor.getDraconics()
const sorts = rollData.active.actor.itemTypes[ITEM_TYPES.sort] const sorts = rollData.active.actor.itemTypes[ITEM_TYPES.sort]
.map(s => RollPartSort.$extractSort(s, coord, draconics)) .map(s => RollPartSort.$extractSort(s, coord, draconics))
@@ -31,7 +51,7 @@ export class RollPartSort extends RollPartSelect {
{ {
coord: coord, coord: coord,
tmr: TMRUtility.getTMR(coord), tmr: TMRUtility.getTMR(coord),
reve: rollData.active.actor.system.reve.reve.value, reve: this.getReveActuel(rollData),
draconics: draconics, draconics: draconics,
all: sorts, all: sorts,
sorts: sorts.filter(it => RdDItemSort.isSortOnCoord(it.sort, coord)) sorts: sorts.filter(it => RdDItemSort.isSortOnCoord(it.sort, coord))
@@ -39,10 +59,18 @@ export class RollPartSort extends RollPartSelect {
{ inplace: true } { inplace: true }
) )
if (refs.sorts.length > 0) { if (refs.sorts.length > 0) {
this.$selectSort(rollData) this.$selectSort(rollData, this.getSaved(rollData))
} }
} }
getReveActuel(rollData) {
return rollData.active.actor.system.reve.reve.value
}
getCoord(rollData) {
return rollData.active.actor.system.reve.tmrpos.coord
}
choices(refs) { return refs.sorts } choices(refs) { return refs.sorts }
static $extractSort(sort, coord, draconics) { static $extractSort(sort, coord, draconics) {
@@ -54,37 +82,35 @@ export class RollPartSort extends RollPartSelect {
value: isDiffVariable ? -7 : parseInt(sort.system.difficulte), value: isDiffVariable ? -7 : parseInt(sort.system.difficulte),
ptreve: isReveVariable ? 1 : sort.system.ptreve, ptreve: isReveVariable ? 1 : sort.system.ptreve,
caseTMR: RdDItemSort.getCaseTMR(sort), caseTMR: RdDItemSort.getCaseTMR(sort),
bonusCase: RdDItemSort.getCaseBonus(sort, coord),
isDiffVariable: isDiffVariable, isDiffVariable: isDiffVariable,
isReveVariable: isReveVariable, isReveVariable: isReveVariable,
isReserve: false, isReserve: false,
sort: sort, sort: sort,
draconics: RdDItemSort.getDraconicsSort(draconics, sort).map(it => it.name) draconics: RdDItemSort.getDraconicsSort(draconics, sort).map(it => it.name),
} }
} }
getAjustements(rollData) { getAjustements(rollData) {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
if (current) { if (current) {
const reserve = current.isReserve ? const sort = { label: current.label, value: current.value }
[{ label: `Mise en réserve en ${current.coord}` }] : [] const reserve = current.isReserve ? [{ label: `Mise en réserve en ${this.getCoord(rollData)}` }] : []
const bonusCase = current.bonusCase ? const bonusCase = current.bonusCase ? [{ label: `Bonus case +${current.bonusCase}%` }] : []
[{ label: `Bonus case +${current.bonusCase}%` }] : [] const reve = { label: `Rêve ${current.ptreve}` }
return [ return [sort, ...bonusCase, reve, ...reserve]
{ label: current.label, diff: current.value },
{ label: `r${current.ptreve}` },
...bonusCase,
...reserve
]
} }
return [] return []
} }
$selectSort(rollData, key) { $selectSort(rollData, values) {
const previous = this.getCurrent(rollData) const current = this.selectByKey(rollData, values.key)
const current = this.selectByKey(rollData, key, -7) if (values.ptreve) {
if (current.key != previous.key) { } current.ptreve = values.ptreve
current.bonusCase = RdDItemSort.getCaseBonus(current.sort, }
rollData.active.actor.system.reve.tmrpos.coord) if (values.isReserve != undefined) {
current.isReserve = values.isReserve
}
} }
async _onRender(rollDialog, context, options) { async _onRender(rollDialog, context, options) {
@@ -97,7 +123,7 @@ export class RollPartSort extends RollPartSelect {
selectSort.addEventListener("change", e => { selectSort.addEventListener("change", e => {
const selectOptions = e.currentTarget.options const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex const index = selectOptions.selectedIndex
this.$selectSort(rollDialog.rollData, selectOptions[index]?.value) this.$selectSort(rollDialog.rollData, { key: selectOptions[index]?.value })
rollDialog.render() rollDialog.render()
}) })
@@ -120,7 +146,7 @@ export class RollPartSort extends RollPartSelect {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
switch (part.code) { switch (part.code) {
case PART_CARAC: return part.filterCaracs(rollData, [CARACS.REVE]) case PART_CARAC: return part.filterCaracs(rollData, [CARACS.REVE])
case PART_COMP: return part.filterComps(rollData,current.draconics ?? []) case PART_COMP: return part.filterComps(rollData, current.draconics ?? [])
} }
} }
return undefined return undefined

View File

@@ -1,3 +1,4 @@
import { RDD_CONFIG } from "../constants.js"
import { RdDCarac } from "../rdd-carac.js" import { RdDCarac } from "../rdd-carac.js"
import { RollPartCheckbox } from "./roll-part-checkbox.mjs" import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
@@ -10,7 +11,7 @@ export class RollPartSurEnc extends RollPartCheckbox {
visible(rollData) { visible(rollData) {
return RdDCarac.isActionPhysique(rollData.current.carac.key) && rollData.active.actor.isSurenc() return RdDCarac.isActionPhysique(rollData.current.carac.key) && rollData.active.actor.isSurenc()
} }
getCheckboxIcon(rollData) { return '<i class="fa-solid fa-weight-hanging"></i>' } getCheckboxIcon(rollData) { return `<img src="${RDD_CONFIG.icons.surenc}">` }
getCheckboxLabel(rollData) { return "Sur-enc." } getCheckboxLabel(rollData) { return "Sur-enc." }
getCheckboxValue(rollData) { return rollData.active.actor.computeMalusSurEncombrement() } getCheckboxValue(rollData) { return rollData.active.actor.computeMalusSurEncombrement() }
} }

View File

@@ -18,10 +18,12 @@ export class RollPartTache extends RollPartSelect {
loadRefs(rollData) { loadRefs(rollData) {
const refs = this.getRefs(rollData) const refs = this.getRefs(rollData)
const selected = this.getSelected(rollData) const selected = this.getSelected(rollData)
refs.forced = selected.forced
refs.all = rollData.active.actor.itemTypes[ITEM_TYPES.tache] refs.all = rollData.active.actor.itemTypes[ITEM_TYPES.tache]
.filter(tache => !selected.forced || tache.id == selected.key) .filter(tache => !selected.forced || tache.id == selected.key)
.filter(tache => tache.system.points_de_tache_courant < tache.system.points_de_tache) .filter(tache => tache.system.points_de_tache_courant < tache.system.points_de_tache)
.map(tache => RollPartTache.$extractTache(tache, rollData.active.actor)) .map(tache => RollPartTache.$extractTache(tache, rollData.active.actor))
refs.taches = refs.all refs.taches = refs.all
if (refs.taches.length > 0) { if (refs.taches.length > 0) {
this.$selectTache(rollData) this.$selectTache(rollData)
@@ -46,6 +48,8 @@ export class RollPartTache extends RollPartSelect {
async _onRender(rollDialog, context, options) { async _onRender(rollDialog, context, options) {
const selectTache = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-tache"]`) const selectTache = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-tache"]`)
const buttonCreate = rollDialog.element.querySelector(`roll-section[name="${this.code}"] button[name="create-tache"]`)
const buttonEdit = rollDialog.element.querySelector(`roll-section[name="${this.code}"] button[name="edit-tache"]`)
selectTache.addEventListener("change", e => { selectTache.addEventListener("change", e => {
const selectOptions = e.currentTarget.options const selectOptions = e.currentTarget.options
@@ -53,14 +57,43 @@ export class RollPartTache extends RollPartSelect {
this.$selectTache(rollDialog.rollData, selectOptions[index]?.value) this.$selectTache(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.render() rollDialog.render()
}) })
buttonCreate?.addEventListener(
"click", async e => {
e.preventDefault()
await rollDialog.rollData.active.actor.createItem(ITEM_TYPES.tache, 'Nouvelle tache')
})
buttonEdit?.addEventListener(
"click", e => {
e.preventDefault()
const current = this.getCurrent(rollDialog.rollData)
current.tache?.sheet.render(true)
})
}
getHooks(rollDialog) {
return [
{ hook: "createItem", fn: (item, options, id) => this.onCreateUpdateItem(rollDialog, item, options, id) },
{ hook: "updateItem", fn: (item, options, id) => this.onCreateUpdateItem(rollDialog, item, options, id) }
]
}
onCreateUpdateItem(rollDialog, item, options, id) {
if (item.type == ITEM_TYPES.tache && item.parent?.id == rollDialog.rollData.active.actor.id) {
this.loadRefs(rollDialog.rollData)
rollDialog.render()
}
} }
impactOtherPart(part, rollData) { impactOtherPart(part, rollData) {
if (this.visible(rollData)) { if (this.visible(rollData)) {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
switch (part.code) { if (current.tache) {
case PART_CARAC: return part.filterCaracs(rollData, [current?.tache.system.carac]) switch (part.code) {
case PART_COMP: return part.filterComps(rollData, [current.comp?.name]) case PART_CARAC: return part.filterCaracs(rollData, [current?.tache.system.carac])
case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
}
} }
} }
return undefined return undefined

View File

@@ -15,10 +15,6 @@ export class RollPartTricher extends RollPart {
current.resultat = Misc.inRange(current.resultat == undefined ? -1 : current.resultat, -1, 100) current.resultat = Misc.inRange(current.resultat == undefined ? -1 : current.resultat, -1, 100)
} }
getAjustements(rollData) {
return []
}
async _onRender(rollDialog, context, options) { async _onRender(rollDialog, context, options) {
const input = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`) const input = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`)

View File

@@ -6,6 +6,8 @@ export const ROLLDIALOG_SECTION = {
CONDITIONS: 'conditions', CONDITIONS: 'conditions',
AJUSTEMENTS: 'ajustements', AJUSTEMENTS: 'ajustements',
} }
export class RollPart { export class RollPart {
static settingKey(rollPart, key) { return `roll-part-${rollPart.code}.${key}` } static settingKey(rollPart, key) { return `roll-part-${rollPart.code}.${key}` }
@@ -28,7 +30,8 @@ export class RollPart {
rollData.selected[this.code] = {} rollData.selected[this.code] = {}
} }
} }
/** l'acteur actif du jet */
getActor(rollData) { return rollData.active.actor }
/** le conteneur de données du RollPart */ /** le conteneur de données du RollPart */
getRefs(rollData) { getRefs(rollData) {
return rollData.refs[this.code] return rollData.refs[this.code]
@@ -104,10 +107,9 @@ export class RollPart {
return { code: this.code, name: this.name, template: this.template, section: this.section } return { code: this.code, name: this.name, template: this.template, section: this.section }
} }
getAjustements(rollData) { getAjustements(rollData) { return [] }
return []
}
async _onRender(rollDialog, context, options) { } async _onRender(rollDialog, context, options) { }
getHooks() { return [] }
} }

View File

@@ -1,5 +1,4 @@
import { DIFF, ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs" import { DIFF, ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
import { RollType } from "./roll-type.mjs" import { RollType } from "./roll-type.mjs"
export class RollTypeAttaque extends RollType { export class RollTypeAttaque extends RollType {

View File

@@ -1,4 +1,4 @@
import { ROLL_TYPE_COMP } from "./roll-constants.mjs" import { DIFF, ROLL_TYPE_COMP } from "./roll-constants.mjs"
import { RollType } from "./roll-type.mjs" import { RollType } from "./roll-type.mjs"
export class RollTypeComp extends RollType { export class RollTypeComp extends RollType {
@@ -7,4 +7,9 @@ export class RollTypeComp extends RollType {
title(rollData) { return `fait un jet ${rollData.type.opposed ? ' contre ' : ''}` } title(rollData) { return `fait un jet ${rollData.type.opposed ? ' contre ' : ''}` }
onSelect(rollData) {
this.setDiffType(rollData, DIFF.LIBRE)
}
} }

View File

@@ -1,3 +1,5 @@
import { ITEM_TYPES } from "../constants.js"
import { RollBasicParts } from "./roll-basic-parts.mjs"
import { DIFF, ROLL_TYPE_CUISINE } from "./roll-constants.mjs" import { DIFF, ROLL_TYPE_CUISINE } from "./roll-constants.mjs"
import { PART_CUISINE } from "./roll-part-cuisine.mjs" import { PART_CUISINE } from "./roll-part-cuisine.mjs"
import { RollType } from "./roll-type.mjs" import { RollType } from "./roll-type.mjs"
@@ -9,19 +11,73 @@ export class RollTypeCuisine extends RollType {
visible(rollData) { return rollData.active.actor.isPersonnage() } visible(rollData) { return rollData.active.actor.isPersonnage() }
title(rollData) { title(rollData) {
const current = rollData.current[PART_CUISINE] const current = rollData.current[PART_CUISINE]
return `prépare une recette: ${current.label}` return current.recette ? `prépare une recette: ${current.label}` : `prépare: ${current.label}`
} }
onSelect(rollData) { onSelect(rollData) {
this.setDiffType(rollData, DIFF.AUCUN) this.setDiffType(rollData, DIFF.AUCUN)
} }
getResult(rollData){ getResult(rollData, impacts) {
const current = rollData.current[PART_CUISINE] const current = rollData.current[PART_CUISINE]
const qualite = rollData.rolled.isSuccess ? current.qualite : Math.min(current.qualite, current.comp.system.niveau) const diff = -current.value
return { const cuisine = rollData.refs[PART_CUISINE].cuisine
qualite: qualite + rollData.rolled.ptQualite const qualite = rollData.rolled.ptQualite + (rollData.rolled.isSuccess ? diff : Math.min(diff, cuisine.system.niveau))
const result = {
qualite: qualite,
exotisme: Math.min(Math.min(qualite, current.exotisme ?? 0), 0),
messages: []
} }
if (current.fabriquer) {
const plat = this.$prepareNourriture(rollData.active.name, current, result)
result.messages.push(`${plat.system.quantite} ${plat.name} ont été préparés dans l'équipement`)
impacts.addCreated('Item', plat)
result.plat = { id: plat.id }
}
if (current.ingredient) {
const quantite = Math.min(current.proportions, current.ingredient.system.quantite)
if (quantite == current.ingredient.system.quantite) {
impacts.addDeleted('Item', current.ingredient)
result.messages.push(`Il n'y a plus de ${ingredient.name}`)
}
else {
impacts.addDelta('Item', current.ingredient, 'system.quantite', -current.proportions)
result.messages.push(`${current.proportions} ${current.ingredient.name} ont été utilisés`)
}
}
return result
}
onApplyImpacts(roll, impacts) {
if (roll.result.plat) {
// le plat n'est pas créé immédiatement, il faut donc retrouver l'id
roll.result.plat.id = impacts.findCreatedId('Item', roll.result.plat.id)
}
}
$prepareNourriture(cuisinier, current, result) {
return {
id: foundry.utils.randomID(16),
name: current.label,
img: current.img,
type: ITEM_TYPES.nourritureboisson,
system: {
sust: current.sust,
cuisinier: cuisinier,
exotisme: result.exotisme,
encombrement: 0.1,
quantite: current.proportions,
qualite: result.qualite,
cout: result.qualite > 0 ? (result.qualite * 0.01) : 0.01,
}
}
}
async onFaireGouter(savedRoll) {
const actor = RollBasicParts.getTokenActor(savedRoll).actor
const platId = savedRoll.result.plat.id
const plat = actor.items.get(platId)
await plat?.proposerVente()
} }
} }

View File

@@ -1,6 +1,7 @@
import { PART_JEU } from "./roll-part-jeu.mjs" import { PART_JEU, RollPartJeu } from "./roll-part-jeu.mjs"
import { RollType } from "./roll-type.mjs" import { RollType } from "./roll-type.mjs"
import { ROLL_TYPE_JEU } from "./roll-constants.mjs" import { DIFF, ROLL_TYPE_JEU } from "./roll-constants.mjs"
export class RollTypeJeu extends RollType { export class RollTypeJeu extends RollType {
get code() { return ROLL_TYPE_JEU } get code() { return ROLL_TYPE_JEU }
@@ -14,4 +15,9 @@ export class RollTypeJeu extends RollType {
return `joue: ${rollData.current[PART_JEU].label}` return `joue: ${rollData.current[PART_JEU].label}`
} }
onSelect(rollData) {
this.setDiffType(rollData, DIFF.LIBRE)
RollPartJeu.forceCompJeu(rollData)
}
} }

View File

@@ -1,4 +1,5 @@
import { RdDItemSigneDraconique } from "../item/signedraconique.js" import { RdDItemSigneDraconique } from "../item/signedraconique.js"
import { RollBasicParts } from "./roll-basic-parts.mjs"
import { DIFF, ROLL_TYPE_MEDITATION } from "./roll-constants.mjs" import { DIFF, ROLL_TYPE_MEDITATION } from "./roll-constants.mjs"
import { PART_MEDITATION } from "./roll-part-meditation.mjs" import { PART_MEDITATION } from "./roll-part-meditation.mjs"
import { RollType } from "./roll-type.mjs" import { RollType } from "./roll-type.mjs"
@@ -17,6 +18,7 @@ export class RollTypeMeditation extends RollType {
onSelect(rollData) { onSelect(rollData) {
this.setDiffType(rollData, DIFF.AUCUN) this.setDiffType(rollData, DIFF.AUCUN)
} }
callbacks(rollOptions) { return [RollTypeMeditation.$onRollMeditation] } callbacks(rollOptions) { return [RollTypeMeditation.$onRollMeditation] }
static async $onRollMeditation(rollData) { static async $onRollMeditation(rollData) {
@@ -25,7 +27,7 @@ export class RollTypeMeditation extends RollType {
const rolled = rollData.rolled const rolled = rollData.rolled
if (meditation && rolled) { if (meditation && rolled) {
if (rolled.isSuccess) { if (rolled.isSuccess) {
await actor.createEmbeddedDocuments("Item", [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditation, rolled)]) await actor.createEmbeddedDocuments('Item', [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditation, rolled)])
} }
if (rolled.isEPart) { if (rolled.isEPart) {
await actor.updateEmbeddedDocuments('Item', [{ _id: meditation._id, 'system.malus': meditation.system.malus - 1 }]) await actor.updateEmbeddedDocuments('Item', [{ _id: meditation._id, 'system.malus': meditation.system.malus - 1 }])
@@ -33,4 +35,9 @@ export class RollTypeMeditation extends RollType {
await actor.santeIncDec("fatigue", 2) await actor.santeIncDec("fatigue", 2)
} }
} }
async onMonteeTMR(savedRoll, mode){
const actor = RollBasicParts.getTokenActor(savedRoll).actor
return actor?.displayTMR(mode)
}
} }

View File

@@ -16,11 +16,12 @@ export class RollTypeOeuvre extends RollType {
this.setDiffType(rollData, DIFF.AUCUN) this.setDiffType(rollData, DIFF.AUCUN)
} }
getResult(rollData){ getResult(rollData, impacts) {
const current = rollData.current[PART_OEUVRE] const current = rollData.current[PART_OEUVRE]
const qualite = rollData.rolled.isSuccess ? current.qualite : Math.min(current.qualite, current.comp.system.niveau) const qualite = rollData.rolled.isSuccess ? current.qualite : Math.min(current.qualite, current.comp.system.niveau)
return { return {
qualite: qualite + rollData.rolled.ptQualite qualite: qualite + rollData.rolled.ptQualite,
messages: []
} }
} }

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