Compare commits
	
		
			28 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 020ff4b014 | |||
| b3c7453823 | |||
| 18d003aa5d | |||
| 0b90badb5e | |||
| 290b5029d1 | |||
| a7e4aea52d | |||
| 755d15509e | |||
| 02cea84ebb | |||
| c47fc4f5b6 | |||
| 147e49f2cb | |||
| 7f4f942d50 | |||
| 8f4df1af56 | |||
| 77f2de2c5f | |||
| e5e271e424 | |||
| 43ecca8be1 | |||
| e21f7e398a | |||
| e16f89743a | |||
| a6c593c100 | |||
| cd8e190082 | |||
| f2106763c1 | |||
| 5da5cb0314 | |||
| 6d7f66569a | |||
| 3e8963b20b | |||
| 2cf5b06da8 | |||
| 68c01fc930 | |||
| 3bc1c4871b | |||
| 3d732e9a8a | |||
| 35f226af5c | 
							
								
								
									
										1
									
								
								assets/actions/armes-disparates.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/actions/armes-disparates.svg
									
									
									
									
									
										Normal 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  | 
							
								
								
									
										1
									
								
								assets/actions/empoignade.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/actions/empoignade.svg
									
									
									
									
									
										Normal 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  | 
| 
		 Before Width: | Height: | Size: 2.7 KiB After Width: | Height: | Size: 2.7 KiB  | 
							
								
								
									
										65
									
								
								assets/actions/surenc.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								assets/actions/surenc.svg
									
									
									
									
									
										Normal 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  | 
							
								
								
									
										1
									
								
								assets/ui/maladresse.svg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								assets/ui/maladresse.svg
									
									
									
									
									
										Normal 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  | 
							
								
								
									
										56
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										56
									
								
								changelog.md
									
									
									
									
									
								
							@@ -1,4 +1,60 @@
 | 
			
		||||
# 13.0
 | 
			
		||||
## 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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -648,15 +648,19 @@ select,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="coeur"] select[name="coeur"] {
 | 
			
		||||
  max-width: 4rem;
 | 
			
		||||
}
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="tricher"] img {
 | 
			
		||||
  /* image de d100 */
 | 
			
		||||
  max-width: 2.5rem;
 | 
			
		||||
  max-height: 2.5rem;
 | 
			
		||||
.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 {
 | 
			
		||||
  /* image de d100 */
 | 
			
		||||
  max-width: 2.5rem;
 | 
			
		||||
  max-height: 2.5rem;
 | 
			
		||||
}
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-buttons {
 | 
			
		||||
  display: flex;
 | 
			
		||||
  flex-direction: row-reverse;
 | 
			
		||||
@@ -707,6 +711,10 @@ select,
 | 
			
		||||
  display: flex;
 | 
			
		||||
  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 .dialog-content div.roll-chat div.chat-actions {
 | 
			
		||||
  grid-area: actions;
 | 
			
		||||
@@ -757,7 +765,10 @@ select,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .window-header {
 | 
			
		||||
  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 {
 | 
			
		||||
  margin: 0.2rem;
 | 
			
		||||
  padding: 0;
 | 
			
		||||
@@ -848,7 +859,7 @@ select,
 | 
			
		||||
  max-width: 1.4rem;
 | 
			
		||||
  max-height: 1.4rem;
 | 
			
		||||
  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 {
 | 
			
		||||
  width: calc(60% - 110px - 1rem);
 | 
			
		||||
@@ -924,6 +935,12 @@ select,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon a:hover {
 | 
			
		||||
  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:focus {
 | 
			
		||||
  color: #000;
 | 
			
		||||
@@ -1361,6 +1378,9 @@ select,
 | 
			
		||||
  margin: 0.1rem 0;
 | 
			
		||||
  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 {
 | 
			
		||||
  height: fit-content;
 | 
			
		||||
  min-height: 5rem;
 | 
			
		||||
@@ -1448,12 +1468,27 @@ select,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .competence-list .item-controls.hidden-controls {
 | 
			
		||||
  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) {
 | 
			
		||||
  font-size: 0.8em;
 | 
			
		||||
  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 {
 | 
			
		||||
  opacity: 0.6;
 | 
			
		||||
}
 | 
			
		||||
@@ -1537,22 +1572,70 @@ select,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .type-compendium {
 | 
			
		||||
  font-size: 0.6rem;
 | 
			
		||||
}
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-header {
 | 
			
		||||
  background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
 | 
			
		||||
  color: #ffffff;
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .application .window-content,
 | 
			
		||||
.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(
 | 
			
		||||
      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);
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body label,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .application .window-content label,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar label,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body .hint,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .application .window-content .hint,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar .hint,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body .permissions-list,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .application .window-content .permissions-list,
 | 
			
		||||
.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;
 | 
			
		||||
  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"] {
 | 
			
		||||
  text-align: right;
 | 
			
		||||
  padding-right: 0.5rem;
 | 
			
		||||
@@ -1593,9 +1676,12 @@ select,
 | 
			
		||||
  width: calc(100% - 2px);
 | 
			
		||||
  height: var(--form-field-height);
 | 
			
		||||
  margin: 0;
 | 
			
		||||
  color: var(--color-text-dark-primary);
 | 
			
		||||
  color: var(--rdd-color-text-primary);
 | 
			
		||||
  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 {
 | 
			
		||||
  width: 14rem;
 | 
			
		||||
  margin: 0.4rem;
 | 
			
		||||
@@ -1616,8 +1702,9 @@ select,
 | 
			
		||||
  height: 2rem;
 | 
			
		||||
}
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .window-app .window-content,
 | 
			
		||||
.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 .window-app.sheet .window-content .sheet-body,
 | 
			
		||||
.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 {
 | 
			
		||||
  padding: 0.25rem 0.5rem;
 | 
			
		||||
@@ -2292,7 +2379,7 @@ select,
 | 
			
		||||
  pointer-events: all;
 | 
			
		||||
}
 | 
			
		||||
.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%;
 | 
			
		||||
  left: 2%;
 | 
			
		||||
  width: 96%;
 | 
			
		||||
@@ -2676,6 +2763,13 @@ select,
 | 
			
		||||
.system-foundryvtt-reve-de-dragon :is(.tooltip, .tooltip-overflow) .ttt-ajustements div:nth-child(odd) {
 | 
			
		||||
  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 {
 | 
			
		||||
  max-width: 15rem;
 | 
			
		||||
  background: var(--background-tooltip);
 | 
			
		||||
@@ -2737,11 +2831,9 @@ select,
 | 
			
		||||
}
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .chat-card-button:hover {
 | 
			
		||||
  background: var(--background-custom-button-hover);
 | 
			
		||||
  background-color: red;
 | 
			
		||||
}
 | 
			
		||||
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed: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-pushed:active {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "TYPES": {
 | 
			
		||||
    "Actor": { 
 | 
			
		||||
    "Actor": {
 | 
			
		||||
      "personnage": "Personnage",
 | 
			
		||||
      "creature": "Créature",
 | 
			
		||||
      "entite": "Entité de cauchemar",
 | 
			
		||||
@@ -67,6 +67,7 @@
 | 
			
		||||
    "StatusComma": "Comma",
 | 
			
		||||
    "StatusDead": "Mort",
 | 
			
		||||
    "StatusDemiReve": "Demi-rêve",
 | 
			
		||||
    "StatusSurEnc": "Sur-encombrement",
 | 
			
		||||
    "StatusForceWeak": "Force insuffisante"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -12,7 +12,10 @@
 | 
			
		||||
    background: rgba(0,0,0,0.75);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .application .window-content,
 | 
			
		||||
  .application .window-content {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    padding: 0.2rem;
 | 
			
		||||
  }
 | 
			
		||||
  .window-app.sheet .window-content {
 | 
			
		||||
    margin: 0.2rem;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
@@ -115,7 +118,7 @@
 | 
			
		||||
    max-width: 1.4rem;
 | 
			
		||||
    max-height: 1.4rem;
 | 
			
		||||
    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 {
 | 
			
		||||
@@ -200,6 +203,9 @@
 | 
			
		||||
  i.moral-radio-checkmark-off:hover,
 | 
			
		||||
  a:hover {
 | 
			
		||||
    text-shadow: 1px 0px 0px #ff6600;
 | 
			
		||||
    img {
 | 
			
		||||
      filter: drop-shadow(1px 0px 0px #ff6600);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .rollable:hover, .rollable:focus {
 | 
			
		||||
@@ -650,9 +656,15 @@
 | 
			
		||||
    margin: 0.1rem 0;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
  }
 | 
			
		||||
  .prosemirror {
 | 
			
		||||
    menu{
 | 
			
		||||
      background-color: var(--color-background-chat-message);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .app.sheet .editor.prosemirror {
 | 
			
		||||
    height: fit-content;
 | 
			
		||||
    min-height: 5rem;
 | 
			
		||||
 | 
			
		||||
  }
 | 
			
		||||
  .app.sheet .editor.prosemirror .editor-container {
 | 
			
		||||
    min-height: 5rem;
 | 
			
		||||
@@ -741,11 +753,11 @@
 | 
			
		||||
  .foundryvtt-reve-de-dragon .item-list .item img {
 | 
			
		||||
    display: inline;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  .foundryvtt-reve-de-dragon .item-list .item-name {
 | 
			
		||||
    margin: 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  .competence-list .item-controls,
 | 
			
		||||
  .competence-list .item-actions-controls {
 | 
			
		||||
    display: contents !important;
 | 
			
		||||
@@ -754,15 +766,30 @@
 | 
			
		||||
  .competence-list .item-controls.hidden-controls {
 | 
			
		||||
    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),
 | 
			
		||||
  .item-controls i:is(.fas, .fa, .fa-solid, .fa-regular) {
 | 
			
		||||
    font-size: 0.8em;
 | 
			
		||||
    color: var(--color-controls-light);
 | 
			
		||||
  }
 | 
			
		||||
  .item-actions-controls a.actionItem i:is(.fas, .fa, .fa-solid, .fa-regular):hover,
 | 
			
		||||
  .item-controls i:is(.fas, .far, .fa-solid, .fa-regular):hover {
 | 
			
		||||
    opacity: 0.6;
 | 
			
		||||
    img {
 | 
			
		||||
        display: inline;
 | 
			
		||||
        max-width: 1rem;
 | 
			
		||||
        max-height: 1rem;
 | 
			
		||||
        margin: 0 0.1rem;
 | 
			
		||||
        border: none;
 | 
			
		||||
        filter: invert(0.8);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    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 {
 | 
			
		||||
@@ -844,26 +871,60 @@
 | 
			
		||||
  .type-compendium {
 | 
			
		||||
    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  */
 | 
			
		||||
  .window-app.sheet .window-content .sheet-header{
 | 
			
		||||
    background: #011d33 url(../assets/ui/bg_header.webp) no-repeat left top;
 | 
			
		||||
    color: rgba(255, 255, 255, 1);
 | 
			
		||||
  }
 | 
			
		||||
  .window-app .window-content{
 | 
			
		||||
    background: url(../assets/ui/bg_left.webp) no-repeat left top;
 | 
			
		||||
    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"] {
 | 
			
		||||
    text-align: right;
 | 
			
		||||
@@ -907,9 +968,14 @@
 | 
			
		||||
    width: calc(100% - 2px);
 | 
			
		||||
    height: var(--form-field-height);
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    color: var(--color-text-dark-primary);
 | 
			
		||||
    color: var(--rdd-color-text-primary);
 | 
			
		||||
    border-radius: 0.2rem;
 | 
			
		||||
  }
 | 
			
		||||
  form.app-personnage-aleatoire {
 | 
			
		||||
    h2 {
 | 
			
		||||
      min-width: 30rem,
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  .app-calendar-astrologie{
 | 
			
		||||
    div.theme-astral{
 | 
			
		||||
      width: 14rem;
 | 
			
		||||
@@ -932,8 +998,10 @@
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .window-app .window-content, .window-app.sheet .window-content .sheet-body{
 | 
			
		||||
    background: rgb(245,245,240) url(../assets/ui/bg_left.webp) no-repeat left top;
 | 
			
		||||
  .window-app .window-content,
 | 
			
		||||
  .window-app.sheet .window-content .sheet-body,
 | 
			
		||||
  .application .window-content {
 | 
			
		||||
    background: url(../assets/ui/bg_left.webp) no-repeat left top;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  section.sheet-body {
 | 
			
		||||
@@ -1654,7 +1722,7 @@
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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%;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -1927,6 +1995,13 @@
 | 
			
		||||
      div:nth-child(odd) {
 | 
			
		||||
        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 {
 | 
			
		||||
    background: var(--background-custom-button-hover);
 | 
			
		||||
    background-color: red;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .chat-card-button-pushed:hover {
 | 
			
		||||
    background: var(--background-custom-button-hover);
 | 
			
		||||
    background-color: red;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .chat-card-button:active, .chat-card-button-pushed:active {
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,9 @@
 | 
			
		||||
    text-align: justify;
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
    div {
 | 
			
		||||
      display: block;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  div.chat-actions {
 | 
			
		||||
    grid-area: actions;
 | 
			
		||||
 
 | 
			
		||||
@@ -224,15 +224,19 @@
 | 
			
		||||
    max-width: 4rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  roll-conditions roll-section[name="tricher"] img {
 | 
			
		||||
    /* image de d100 */
 | 
			
		||||
    max-width: 2.5rem;
 | 
			
		||||
    max-height: 2.5rem;
 | 
			
		||||
  roll-conditions roll-section img {
 | 
			
		||||
    max-width: 1rem;
 | 
			
		||||
    max-height: 1rem;
 | 
			
		||||
    gap: 0;
 | 
			
		||||
    margin: 0;
 | 
			
		||||
    padding: 0;
 | 
			
		||||
    filter: invert(0.8);
 | 
			
		||||
  }
 | 
			
		||||
  roll-conditions roll-section[name="tricher"] img {
 | 
			
		||||
    /* image de d100 */
 | 
			
		||||
    max-width: 2.5rem;
 | 
			
		||||
    max-height: 2.5rem;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  roll-buttons { 
 | 
			
		||||
    display: flex;
 | 
			
		||||
 
 | 
			
		||||
@@ -342,7 +342,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async createEmptyTache() {
 | 
			
		||||
    await this.actor.createItem('tache', 'Nouvelle tache');
 | 
			
		||||
    await this.actor.createItem(ITEM_TYPES.tache, 'Nouvelle tache')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  _getActionCombat(event) {
 | 
			
		||||
@@ -375,14 +375,6 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
 | 
			
		||||
    return position;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  /** @override */
 | 
			
		||||
  _updateObject(event, formData) {
 | 
			
		||||
    // Update the Actor
 | 
			
		||||
    return this.actor.update(formData);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async splitItem(item) {
 | 
			
		||||
    const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split));
 | 
			
		||||
    dialog.render(true);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										117
									
								
								module/actor.js
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								module/actor.js
									
									
									
									
									
								
							@@ -47,11 +47,12 @@ import { RdDRollResult } from "./rdd-roll-result.js";
 | 
			
		||||
import { RdDInitiative } from "./initiative.mjs";
 | 
			
		||||
import RollDialog from "./roll/roll-dialog.mjs";
 | 
			
		||||
import { OptionsAvancees, ROLL_DIALOG_V2, ROLL_DIALOG_V2_TEST } from "./settings/options-avancees.js";
 | 
			
		||||
import { ROLL_TYPE_JEU, 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_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']
 | 
			
		||||
 | 
			
		||||
@@ -184,13 +185,13 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    const actions = []
 | 
			
		||||
    const uniques = []
 | 
			
		||||
 | 
			
		||||
    const addAttaque = (arme, main = undefined, action = 'attaque') => {
 | 
			
		||||
      const dommagesArme = RdDItemArme.valeurMain(arme.system.dommages, main)
 | 
			
		||||
    const addAttaque = (arme, main = undefined) => {
 | 
			
		||||
      const dommages = RdDItemArme.valeurMain(arme.system.dommages, main)
 | 
			
		||||
      const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
 | 
			
		||||
      const ecaillesEfficacite = arme.system.magique ? arme.system.ecaille_efficacite : 0;
 | 
			
		||||
 | 
			
		||||
      const comp = this.getCompetence(RdDActor.$getCompetenceAction(arme, 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)) {
 | 
			
		||||
        return
 | 
			
		||||
      }
 | 
			
		||||
@@ -211,12 +212,13 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
        main: main,
 | 
			
		||||
        carac: { key: caracCode, value: caracValue },
 | 
			
		||||
        equipe: arme.system.equipe,
 | 
			
		||||
        dommagesArme: dommagesArme,
 | 
			
		||||
        dommages: dommages,
 | 
			
		||||
        forceRequise: forceRequise,
 | 
			
		||||
        initiative: RdDInitiative.getRollInitiative(caracValue, niveau, ajustement)
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS)
 | 
			
		||||
    this.itemTypes[ITEM_TYPES.arme]
 | 
			
		||||
      .filter(it => it.isAttaque())
 | 
			
		||||
      .sort(Misc.ascending(it => it.name))
 | 
			
		||||
@@ -226,9 +228,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
        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.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS, 'empoignade')
 | 
			
		||||
 | 
			
		||||
    return actions
 | 
			
		||||
  }
 | 
			
		||||
@@ -741,12 +741,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async sortMisEnReserve(sort, draconic, coord, ptreve) {
 | 
			
		||||
    await this.createEmbeddedDocuments("Item", [{
 | 
			
		||||
      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' }
 | 
			
		||||
    }],
 | 
			
		||||
    await this.createEmbeddedDocuments("Item", [RdDItemSort.prepareSortEnReserve(sort, draconic, ptreve, coord)],
 | 
			
		||||
      { renderSheet: false });
 | 
			
		||||
    this.tmrApp.updateTokens();
 | 
			
		||||
  }
 | 
			
		||||
@@ -760,20 +755,18 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    let updates = {};
 | 
			
		||||
    if (caracName == LIST_CARAC_PERSONNAGE.reve.code) {
 | 
			
		||||
      if (to > Misc.toInt(this.system.reve.seuil.value)) {
 | 
			
		||||
        updates[`system.reve.seuil.value`] = to; // SFA : Direct and packed changes
 | 
			
		||||
        //this.setPointsDeSeuil(to);
 | 
			
		||||
        updates[`system.reve.seuil.value`] = to
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if (caracName == LIST_CARAC_PERSONNAGE.chance.code) {
 | 
			
		||||
      if (to > Misc.toInt(this.system.compteurs.chance.value)) {
 | 
			
		||||
        updates[`system.compteurs.chance.value`] = to; // SFA : Direct and packed changes
 | 
			
		||||
        //this.setPointsDeChance(to);
 | 
			
		||||
        updates[`system.compteurs.chance.value`] = to
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    let selectedCarac = this.findCaracByName(caracName);
 | 
			
		||||
    const from = selectedCarac.value
 | 
			
		||||
    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);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -1712,15 +1705,18 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
      ui.notifications.error("Une queue ou un souffle vous empèche de lancer de sort!")
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
 | 
			
		||||
      return await this.rollUnSortV2();
 | 
			
		||||
    }
 | 
			
		||||
    // 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)))
 | 
			
		||||
    if (sorts.length == 0) {
 | 
			
		||||
      ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`);
 | 
			
		||||
      return;
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const draconicList = this.computeDraconicAndSortIndex(sorts);
 | 
			
		||||
    const reve = foundry.utils.duplicate(this.system.carac.reve);
 | 
			
		||||
    const draconicList = this.computeDraconicAndSortIndex(sorts)
 | 
			
		||||
    const reve = foundry.utils.duplicate(this.system.carac.reve)
 | 
			
		||||
 | 
			
		||||
    const dialog = await this.openRollDialog({
 | 
			
		||||
      name: 'lancer-un-sort',
 | 
			
		||||
@@ -1743,6 +1739,27 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    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'
 | 
			
		||||
    let addMsg = "";
 | 
			
		||||
@@ -1814,11 +1831,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          console.log('lancement de sort', rollData.selectedSort)
 | 
			
		||||
          const precedents = rollData.selectedSort.system.lancements ?? []
 | 
			
		||||
          const lancements = [...precedents, {
 | 
			
		||||
            timestamp: game.system.rdd.calendrier.getTimestamp(),
 | 
			
		||||
            reve: rollData.selectedSort.system.ptreve_reel
 | 
			
		||||
          }]
 | 
			
		||||
          const lancements = RdDItemSort.prepareSortAddLancement(rollData.selectedSort, rollData.selectedSort.system.ptreve_reel)
 | 
			
		||||
          await this.updateEmbeddedDocuments('Item',
 | 
			
		||||
            [{ _id: rollData.selectedSort._id, 'system.lancements': lancements }]
 | 
			
		||||
          )
 | 
			
		||||
@@ -2109,7 +2122,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  _getSignesDraconiques(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));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
@@ -2121,18 +2134,19 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
  async rollLireSigneDraconique(coord) {
 | 
			
		||||
    if (!this.isHautRevant()) {
 | 
			
		||||
      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) {
 | 
			
		||||
      ui.notifications.info(`Aucun signe draconiques en ${coord} !`);
 | 
			
		||||
      return;
 | 
			
		||||
      ui.notifications.info(`Aucun signe draconiques en ${coord} !`)
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let draconicList = this.getDraconics()
 | 
			
		||||
      .map(draconic => {
 | 
			
		||||
        let draconicLecture = foundry.utils.duplicate(draconic);
 | 
			
		||||
        draconicLecture.system.defaut_carac = "intellect";
 | 
			
		||||
        return draconicLecture;
 | 
			
		||||
        let draconicLecture = foundry.utils.duplicate(draconic)
 | 
			
		||||
        draconicLecture.system.defaut_carac = "intellect"
 | 
			
		||||
        return draconicLecture
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
    const intellect = this.system.carac.intellect;
 | 
			
		||||
@@ -2406,7 +2420,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    if (this.tmrApp) {
 | 
			
		||||
      ui.notifications.warn("Vous êtes déja dans les TMR....")
 | 
			
		||||
      this.tmrApp.forceTMRDisplay()
 | 
			
		||||
      return
 | 
			
		||||
      return false
 | 
			
		||||
    }
 | 
			
		||||
    if (mode != 'visu' && this.isDemiReve()) {
 | 
			
		||||
      ui.notifications.warn("Le personnage est déjà dans les Terres Médianes, elles s'affichent en visualisation")
 | 
			
		||||
@@ -2414,6 +2428,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    }
 | 
			
		||||
    if (mode == 'visu') {
 | 
			
		||||
      await this._doDisplayTMR(mode)
 | 
			
		||||
      return false
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      const rencontre = this.getRencontreTMREnAttente();
 | 
			
		||||
@@ -2426,6 +2441,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
        buttonLabel: 'Monter dans les TMR',
 | 
			
		||||
        onAction: async () => await this._doDisplayTMR(mode)
 | 
			
		||||
      })
 | 
			
		||||
      return true
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -2463,6 +2479,29 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    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) {
 | 
			
		||||
    const blessure = blesse.blessuresASoigner().find(it => it.id == blessureId);
 | 
			
		||||
@@ -2566,7 +2605,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    if (item?.isEquipable()) {
 | 
			
		||||
      const isEquipe = !item.system.equipe;
 | 
			
		||||
      await item.update({ "system.equipe": isEquipe });
 | 
			
		||||
      this.computeEncTotal();
 | 
			
		||||
      this.computeEncTotal()
 | 
			
		||||
      if (isEquipe)
 | 
			
		||||
        this.verifierForceMin(item);
 | 
			
		||||
    }
 | 
			
		||||
@@ -2957,6 +2996,7 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
    if (updatedEndurance && options.diff) {
 | 
			
		||||
      await this.setEffect(STATUSES.StatusUnconscious, updatedEndurance.value == 0)
 | 
			
		||||
    }
 | 
			
		||||
    await super.onUpdateActor(update, options, actorId)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
@@ -2999,9 +3039,12 @@ export class RdDActor extends RdDBaseActorSang {
 | 
			
		||||
        break
 | 
			
		||||
      case ITEM_TYPES.empoignade:
 | 
			
		||||
        await RdDEmpoignade.deleteLinkedEmpoignade(this.id, item)
 | 
			
		||||
        // TODO: check remaining emp.
 | 
			
		||||
        await this.setEffect(STATUSES.StatusGrappled, false)
 | 
			
		||||
        await this.setEffect(STATUSES.StatusGrappling, false)
 | 
			
		||||
        break
 | 
			
		||||
    }
 | 
			
		||||
    super.onDeleteItem(item, options, id)
 | 
			
		||||
    await super.onDeleteItem(item, options, id)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
 
 | 
			
		||||
@@ -56,13 +56,15 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet {
 | 
			
		||||
    if (this.options.vueDetaillee) {
 | 
			
		||||
      // On carac change
 | 
			
		||||
      this.html.find('.carac-value').change(async event => {
 | 
			
		||||
        let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", "")
 | 
			
		||||
        await this.actor.updateCarac(caracName, parseInt(event.target.value))
 | 
			
		||||
      });
 | 
			
		||||
        if (event.currentTarget.name.includes("carac.")) {
 | 
			
		||||
          let caracName = event.currentTarget.name.replace("carac.", "")
 | 
			
		||||
          await this.actor.updateCarac(caracName, parseInt(event.currentTarget.value))
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
      // On competence change
 | 
			
		||||
      this.html.find('.competence-value').change(async event => {
 | 
			
		||||
        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))
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -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 { Misc } from "../misc.js";
 | 
			
		||||
import { RdDResolutionTable } from "../rdd-resolution-table.js";
 | 
			
		||||
@@ -89,7 +89,6 @@ export class RdDBaseActorReve extends RdDBaseActor {
 | 
			
		||||
  getSConst() { return 0 }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  isSurenc() { return false }
 | 
			
		||||
  computeMalusSurEncombrement() { return 0 }
 | 
			
		||||
 | 
			
		||||
  ajustementAstrologique() { return 0 }
 | 
			
		||||
@@ -126,6 +125,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
 | 
			
		||||
  async remiseANeuf() { }
 | 
			
		||||
  async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
 | 
			
		||||
 | 
			
		||||
  computeResumeBlessure() { }
 | 
			
		||||
  countBlessures(filter = it => !it.isContusion()) { return 0 }
 | 
			
		||||
  async santeIncDec(name, inc, isCritique = false) { }
 | 
			
		||||
 | 
			
		||||
  async finDeRound(options = { terminer: false }) {
 | 
			
		||||
@@ -176,10 +177,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getCompetences(name = undefined, options = { onMessage: message => { } }) {
 | 
			
		||||
    const all = [...this.itemTypes[ITEM_TYPES.competence], ...this.itemTypes[ITEM_TYPES.competencecreature]]
 | 
			
		||||
    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 => { } }) {
 | 
			
		||||
@@ -203,6 +205,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
 | 
			
		||||
  getPossession(possessionId) {
 | 
			
		||||
    return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getEmpoignades() {
 | 
			
		||||
    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() {
 | 
			
		||||
    return this.getEffectByStatus(STATUSES.StatusDemiReve) != undefined
 | 
			
		||||
    return this.getEffectsByStatus(STATUSES.StatusDemiReve).length > 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getSurprise(isCombat = undefined) {
 | 
			
		||||
    return StatusEffects.getSurprise(this.getEffects(), isCombat)
 | 
			
		||||
  getSurprise(isCombat = undefined, forceRequise = undefined) {
 | 
			
		||||
    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: "" }) {
 | 
			
		||||
    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);
 | 
			
		||||
    await this.openRollDialog({
 | 
			
		||||
      name: 'jet-competence',
 | 
			
		||||
@@ -387,7 +366,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
 | 
			
		||||
    if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
 | 
			
		||||
      const rollData = {
 | 
			
		||||
        ids: { actorId: this.id },
 | 
			
		||||
        type: { allowed: [PART_COMP], current: PART_COMP },
 | 
			
		||||
        type: { allowed: DEFAULT_ROLL_TYPES, current: PART_COMP },
 | 
			
		||||
        selected: {
 | 
			
		||||
          carac: { key: caracName },
 | 
			
		||||
          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');
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  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 }) {
 | 
			
		||||
    RdDEmpoignade.checkEmpoignadeEnCours(this)
 | 
			
		||||
 | 
			
		||||
    const competence = this.getCompetence(idOrName);
 | 
			
		||||
    if (competence.type != ITEM_TYPES.competencecreature && OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
 | 
			
		||||
    if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
 | 
			
		||||
      const rollData = {
 | 
			
		||||
        ids: { actorId: this.id },
 | 
			
		||||
        type: { allowed: options.arme ? ATTAQUE_ROLL_TYPES : DEFAULT_ROLL_TYPES },
 | 
			
		||||
        selected: {
 | 
			
		||||
          carac: competence.type == ITEM_TYPES.competencecreature ? { key: competence.name } : undefined,
 | 
			
		||||
          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) {
 | 
			
		||||
        rollData.selected.attaque = { arme: { id: options.arme.id }, comp: { id: competence.id } }
 | 
			
		||||
        rollData.type = { allowed: ATTAQUE_ROLL_TYPES }
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      await this.rollCompetenceV2(rollData)
 | 
			
		||||
      return
 | 
			
		||||
      return await RollDialog.create(rollData)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let rollData = {
 | 
			
		||||
@@ -512,19 +481,13 @@ export class RdDBaseActorReve extends RdDBaseActor {
 | 
			
		||||
        title: 'Ne pas utiliser les automatisation de combat',
 | 
			
		||||
        buttonLabel: "Pas d'automatisation",
 | 
			
		||||
        onAction: async () => {
 | 
			
		||||
          this.rollCompetenceV2({
 | 
			
		||||
            ids: {
 | 
			
		||||
              actorId: this.id,
 | 
			
		||||
              actorTokenId: token?.id,
 | 
			
		||||
            },
 | 
			
		||||
            selected: {
 | 
			
		||||
              conditions: { value: 0 }
 | 
			
		||||
            },
 | 
			
		||||
          const rollData = {
 | 
			
		||||
            ids: { actorId: this.id, actorTokenId: token?.id, },
 | 
			
		||||
            type: {
 | 
			
		||||
              allowed: [ROLL_TYPE_COMP, ROLL_TYPE_ATTAQUE, ROLL_TYPE_OEUVRE, ROLL_TYPE_TACHE, ROLL_TYPE_JEU],
 | 
			
		||||
              current: ROLL_TYPE_COMP
 | 
			
		||||
              allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE
 | 
			
		||||
            }
 | 
			
		||||
          })
 | 
			
		||||
          };
 | 
			
		||||
          return await RollDialog.create(rollData)
 | 
			
		||||
        }
 | 
			
		||||
      })
 | 
			
		||||
    }
 | 
			
		||||
@@ -669,7 +632,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
 | 
			
		||||
  async accorder(entite, when = 'avant-encaissement') {
 | 
			
		||||
    if (when != game.settings.get(SYSTEM_RDD, "accorder-entite-cauchemar")
 | 
			
		||||
      || entite == undefined
 | 
			
		||||
      || !entite.isEntite([ENTITE_INCARNE])
 | 
			
		||||
      || !entite.isEntiteIncarnee()
 | 
			
		||||
      || entite.isEntiteAccordee(this)) {
 | 
			
		||||
      return true
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -116,6 +116,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
 | 
			
		||||
      blessure: blessure
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async santeIncDec(name, inc, isCritique = false) {
 | 
			
		||||
    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));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
@@ -292,7 +315,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  isSonne() {
 | 
			
		||||
    return this.getEffectByStatus(STATUSES.StatusStunned)
 | 
			
		||||
    return this.getEffectsByStatus(STATUSES.StatusStunned).length > 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  isEffectAllowed(effectId) { return true }
 | 
			
		||||
 
 | 
			
		||||
@@ -49,15 +49,14 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
 | 
			
		||||
    formData.calc = {
 | 
			
		||||
      fortune: Monnaie.toSolsDeniers(this.actor.getFortune()),
 | 
			
		||||
      prixTotalEquipement: this.actor.computePrixTotalEquipement(),
 | 
			
		||||
      encTotal: await this.actor.computeEncTotal(),
 | 
			
		||||
      encTotal: this.actor.getEncTotal(),
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
 | 
			
		||||
    this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires);
 | 
			
		||||
    formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
 | 
			
		||||
    formData.competences.filter(it => it.type == ITEM_TYPES.competencecreature)
 | 
			
		||||
      .forEach(it => it.isdommages = it.isDommages()
 | 
			
		||||
      )
 | 
			
		||||
      .forEach(it => it.isdommages = it.isDommages())
 | 
			
		||||
 | 
			
		||||
    return formData;
 | 
			
		||||
  }
 | 
			
		||||
@@ -230,14 +229,6 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
 | 
			
		||||
    return position;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  /** @override */
 | 
			
		||||
  _updateObject(event, formData) {
 | 
			
		||||
    // Update the Actor
 | 
			
		||||
    return this.actor.update(formData);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async splitItem(item) {
 | 
			
		||||
    const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split));
 | 
			
		||||
    dialog.render(true);
 | 
			
		||||
 
 | 
			
		||||
@@ -10,7 +10,7 @@ import { RdDConfirm } from "../rdd-confirm.js";
 | 
			
		||||
import { RdDUtility } from "../rdd-utility.js";
 | 
			
		||||
import { SystemCompendiums } from "../settings/system-compendiums.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 {
 | 
			
		||||
 | 
			
		||||
@@ -215,9 +215,11 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
    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 }
 | 
			
		||||
  isEntite(typeentite = []) { return false }
 | 
			
		||||
  isEntite() { return false }
 | 
			
		||||
  isEntiteIncarnee() { return false }
 | 
			
		||||
  isEntiteNonIncarnee() { return false }
 | 
			
		||||
  isHautRevant() { return false }
 | 
			
		||||
  isVehicule() { return false }
 | 
			
		||||
  isPersonnage() { return false }
 | 
			
		||||
@@ -241,41 +243,76 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
 | 
			
		||||
  getMonnaie(id) { return this.findItemLike(id, 'monnaie'); }
 | 
			
		||||
  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 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 onCreateItem(item, options, id) {
 | 
			
		||||
    switch (item.type) {
 | 
			
		||||
      case ITEM_TYPES.blessure:
 | 
			
		||||
        await this.changeBleedingState()
 | 
			
		||||
        break
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
    if (item.isInventaire()) {
 | 
			
		||||
      await this._removeItemFromConteneur(item)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  async _removeItemFromConteneur(item) {
 | 
			
		||||
    const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id))
 | 
			
		||||
      .map(conteneur => {
 | 
			
		||||
@@ -524,16 +561,22 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  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))
 | 
			
		||||
        .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() {
 | 
			
		||||
    return Math.floor(this.encTotal ?? 0);
 | 
			
		||||
    return Math.floor(this.encTotal ?? 0)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async createItem(type, name = undefined) {
 | 
			
		||||
@@ -584,7 +627,7 @@ export class RdDBaseActor extends Actor {
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    await this.computeEncTotal();
 | 
			
		||||
    await this.computeEncTotal()
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
 | 
			
		||||
    this.html.find('.resonance-add').click(async event =>
 | 
			
		||||
      await DialogSelect.select({
 | 
			
		||||
        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))
 | 
			
		||||
    )
 | 
			
		||||
 
 | 
			
		||||
@@ -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 { RdDItemBlessure } from "../item/blessure.js";
 | 
			
		||||
import { Misc } from "../misc.js";
 | 
			
		||||
import { RdDCarac } from "../rdd-carac.js";
 | 
			
		||||
import { RdDEncaisser } from "../rdd-roll-encaisser.js";
 | 
			
		||||
@@ -16,11 +17,10 @@ export class RdDEntite extends RdDBaseActorReve {
 | 
			
		||||
    return item.type == ITEM_TYPES.competencecreature
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  isEntite(typeentite = []) {
 | 
			
		||||
    return (typeentite.length == 0 || typeentite.includes(this.system.definition.typeentite));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  isNonIncarnee() { return this.isEntite([ENTITE_NONINCARNE]) }
 | 
			
		||||
  isEntite() { return true }
 | 
			
		||||
  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 }
 | 
			
		||||
 | 
			
		||||
  getReveActuel() {
 | 
			
		||||
    return Misc.toInt(this.system.carac.reve?.value)
 | 
			
		||||
@@ -49,20 +49,20 @@ export class RdDEntite extends RdDBaseActorReve {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async remiseANeuf() {
 | 
			
		||||
    await this.removeEffects(e => true);
 | 
			
		||||
    if (!this.isNonIncarnee()) {
 | 
			
		||||
    if (!this.isEntiteNonIncarnee()) {
 | 
			
		||||
      await this.update({
 | 
			
		||||
        'system.sante.endurance.value': this.system.sante.endurance.max
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    await this.removeEffects(e => true)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
    if (name == 'endurance' && !this.isNonIncarnee()) {
 | 
			
		||||
    if (name == 'endurance' && !this.isEntiteNonIncarnee()) {
 | 
			
		||||
      const oldValue = this.system.sante.endurance.value;
 | 
			
		||||
      const endurance = Math.max(0,
 | 
			
		||||
        Math.min(oldValue + inc,
 | 
			
		||||
@@ -78,7 +78,7 @@ export class RdDEntite extends RdDBaseActorReve {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async encaisser() {
 | 
			
		||||
    if (this.isNonIncarnee()) {
 | 
			
		||||
    if (this.isEntiteNonIncarnee()) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    await RdDEncaisser.encaisser(this)
 | 
			
		||||
@@ -89,15 +89,19 @@ export class RdDEntite extends RdDBaseActorReve {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async onAppliquerJetEncaissement(encaissement, attackerToken) {
 | 
			
		||||
    if (this.isEntiteNonIncarnee()) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance);
 | 
			
		||||
    foundry.utils.mergeObject(encaissement, {
 | 
			
		||||
      resteEndurance: perteEndurance.newValue,
 | 
			
		||||
      endurance: perteEndurance.perte
 | 
			
		||||
    });
 | 
			
		||||
      endurance: perteEndurance.perte,
 | 
			
		||||
      blessure: RdDItemBlessure.prepareBlessure(encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken)
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  isEntiteAccordee(attacker) {
 | 
			
		||||
    if (this.isEntite([ENTITE_INCARNE])) {
 | 
			
		||||
    if (this.isEntiteIncarnee()) {
 | 
			
		||||
      let resonnance = this.system.sante.resonnance
 | 
			
		||||
      return (resonnance.actors.find(it => it == attacker.id))
 | 
			
		||||
    }
 | 
			
		||||
@@ -106,7 +110,7 @@ export class RdDEntite extends RdDBaseActorReve {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async setEntiteReveAccordee(actor) {
 | 
			
		||||
    if (this.isEntite([ENTITE_INCARNE])) {
 | 
			
		||||
    if (this.isEntiteIncarnee()) {
 | 
			
		||||
      if (this.system.sante.resonnance.actors.find(it => it == actor.id)) {
 | 
			
		||||
        // déjà accordé
 | 
			
		||||
        return
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@ export class ExperienceLog {
 | 
			
		||||
    };
 | 
			
		||||
    console.log('ExperienceLog.add', 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) {
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@ import { Grammar } from "../../grammar.js"
 | 
			
		||||
import { EMPOIGNADE, RdDItemArme } from "../../item/arme.js"
 | 
			
		||||
import { RdDItemCompetence } from "../../item-competence.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 { RdDTimestamp } from "../../time/rdd-timestamp.js"
 | 
			
		||||
import { RdDBonus } from "../../rdd-bonus.js"
 | 
			
		||||
@@ -160,7 +160,7 @@ export class Mapping {
 | 
			
		||||
      return undefined
 | 
			
		||||
    }
 | 
			
		||||
    const categorie = Mapping.complementCategorie(arme, maniement)
 | 
			
		||||
    const dommages = Mapping.dommagesArme(actor, arme, maniement)
 | 
			
		||||
    const dommages = Mapping.dommages(actor, arme, maniement)
 | 
			
		||||
    return {
 | 
			
		||||
      name: arme.name + categorie,
 | 
			
		||||
      niveau: Misc.toSignedString(competence.system.niveau),
 | 
			
		||||
@@ -170,12 +170,13 @@ export class Mapping {
 | 
			
		||||
      arme: arme
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  static dommagesArme(actor, arme, maniement) {
 | 
			
		||||
 | 
			
		||||
  static dommages(actor, arme, maniement) {
 | 
			
		||||
    const dmgArme = RdDItemArme.dommagesReels(arme, maniement)
 | 
			
		||||
    const dommages = Misc.toSignedString(dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme))
 | 
			
		||||
    switch (arme.system.mortalite) {
 | 
			
		||||
      case 'non-mortel': return `(${dommages})`
 | 
			
		||||
      case EMPOIGNADE: return '-'
 | 
			
		||||
      case RDD_CONFIG.encaissement.nonmortel: return `(${dommages})`
 | 
			
		||||
      case RDD_CONFIG.encaissement.empoignade: return '-'
 | 
			
		||||
    }
 | 
			
		||||
    return dommages
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -20,14 +20,15 @@ const PATHS = [
 | 
			
		||||
const RANDOM_VALUES = {
 | 
			
		||||
  'system.sexe': { 'masculin': 1, 'féminin': 1 },
 | 
			
		||||
  '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.yeux': { 'noirs': 2, 'noisettes': 3, 'bruns vert': 4, 'verts': 3, 'bleus clair': 3, 'bleus gris': 2, 'gris': 1, 'mauves': 1, 'indigos': 1 },
 | 
			
		||||
  '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, 'noisette': 3, 'brun-vert': 4, 'verts': 3, 'bleu clair': 3, 'bleu gris': 2, 'gris': 1, 'mauves': 1, 'indigos': 1 },
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export class AppPersonnageAleatoire extends FormApplication {
 | 
			
		||||
  static preloadHandlebars() {
 | 
			
		||||
    foundry.applications.handlebars.loadTemplates([
 | 
			
		||||
      '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.checked = {
 | 
			
		||||
      'name': false,
 | 
			
		||||
      'system.sexe': true,
 | 
			
		||||
      'system.age': true,
 | 
			
		||||
      'system.taille': true,
 | 
			
		||||
      'system.poids': true,
 | 
			
		||||
      'system.main': true,
 | 
			
		||||
      'system.heure': true,
 | 
			
		||||
      'system.cheveux': true,
 | 
			
		||||
      'system.yeux': true
 | 
			
		||||
      'system.sexe': (this.actor.system.sexe ?? '') == '',
 | 
			
		||||
      'system.age': this.actor.system.age == 0,
 | 
			
		||||
      'system.taille': (this.actor.system.taille ?? '') == '',
 | 
			
		||||
      'system.poids': (this.actor.system.poids ?? '') == '',
 | 
			
		||||
      'system.main': (this.actor.system.main ?? '') == '',
 | 
			
		||||
      'system.heure': (this.actor.system.heure ?? '') == '',
 | 
			
		||||
      'system.cheveux': (this.actor.system.cheveux ?? '') == '',
 | 
			
		||||
      '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("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('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.reset").click(async event => await this.onReset(event))
 | 
			
		||||
    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")
 | 
			
		||||
    return fields[0].attributes['data-path'].value
 | 
			
		||||
  }
 | 
			
		||||
  async onSexe(sexe) {
 | 
			
		||||
    this.current['system.sexe'] = sexe
 | 
			
		||||
    this.render()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async onChange(event) {
 | 
			
		||||
    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 total = await RdDDice.rollTotal(`2d${variation} + ${base}`)
 | 
			
		||||
    const cm = total % 100
 | 
			
		||||
    const dm = cm < 10 ? '0' : ''
 | 
			
		||||
    const m = (total - cm) / 100
 | 
			
		||||
    return `${m}m${cm}`
 | 
			
		||||
    return `${m}m${dm}${cm}`
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -106,6 +106,25 @@ export class ChatUtility {
 | 
			
		||||
    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) {
 | 
			
		||||
    return document ? game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) : [game.user]
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -13,53 +13,65 @@ export const renderTemplate = foundry.applications.handlebars.renderTemplate
 | 
			
		||||
 | 
			
		||||
export const RDD_CONFIG = {
 | 
			
		||||
  niveauEthylisme: [
 | 
			
		||||
    { value: "1", label: "Aucun" },
 | 
			
		||||
    { value: "0", label: "Eméché (0)" },
 | 
			
		||||
    { value: "-1", label: "Gris (-1)" },
 | 
			
		||||
    { value: "-2", label: "Pinté (-2)" },
 | 
			
		||||
    { value: "-3", label: "Pas Frais (-3)" },
 | 
			
		||||
    { value: "-4", label: "Ivre (-4)" },
 | 
			
		||||
    { value: "-5", label: "Bu (-5)" },
 | 
			
		||||
    { value: "-6", label: "Complètement fait (-6)" },
 | 
			
		||||
    { value: "-7", label: "Ivre mort (-7)" }
 | 
			
		||||
    { value: '1', label: 'Aucun' },
 | 
			
		||||
    { value: '0', label: 'Eméché (0)' },
 | 
			
		||||
    { value: '-1', label: 'Gris (-1)' },
 | 
			
		||||
    { value: '-2', label: 'Pinté (-2)' },
 | 
			
		||||
    { value: '-3', label: 'Pas Frais (-3)' },
 | 
			
		||||
    { value: '-4', label: 'Ivre (-4)' },
 | 
			
		||||
    { value: '-5', label: 'Bu (-5)' },
 | 
			
		||||
    { value: '-6', label: 'Complètement fait (-6)' },
 | 
			
		||||
    { value: '-7', label: 'Ivre mort (-7)' }
 | 
			
		||||
  ],
 | 
			
		||||
  categorieEntite: {
 | 
			
		||||
    "cauchemar": "Cauchemar",
 | 
			
		||||
    "reve": "Rêve"
 | 
			
		||||
    'cauchemar': 'Cauchemar',
 | 
			
		||||
    'reve': 'Rêve'
 | 
			
		||||
  },
 | 
			
		||||
  typeEntite: {
 | 
			
		||||
    "incarne": "Incarnée",
 | 
			
		||||
    "nonincarne": "Non Incarnée",
 | 
			
		||||
    "blurette": "Blurette"
 | 
			
		||||
    [ENTITE_INCARNE]: 'Incarnée',
 | 
			
		||||
    [ENTITE_NONINCARNE]: 'Non Incarnée',
 | 
			
		||||
    [ENTITE_BLURETTE]: 'Blurette'
 | 
			
		||||
  },
 | 
			
		||||
  heuresRdD: [
 | 
			
		||||
    { 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: "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: "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: "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: "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: "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: '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: '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: '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: '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: '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: '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' }
 | 
			
		||||
  ],
 | 
			
		||||
  raretes: [
 | 
			
		||||
    { value: "Commune", label: "Commune" },
 | 
			
		||||
    { value: "Frequente", label: "Fréquente" },
 | 
			
		||||
    { value: "Rare", label: "Rare" },
 | 
			
		||||
    { value: "Rarissime", label: "Rarissime" }
 | 
			
		||||
    { value: 'Commune', label: 'Commune' },
 | 
			
		||||
    { value: 'Frequente', label: 'Fréquente' },
 | 
			
		||||
    { value: 'Rare', label: 'Rare' },
 | 
			
		||||
    { value: 'Rarissime', label: 'Rarissime' }
 | 
			
		||||
  ],
 | 
			
		||||
  particuliere: {
 | 
			
		||||
    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'},
 | 
			
		||||
    rapidite: { key: 'finesse', descr: 'en rapidité', img: 'systems/foundryvtt-reve-de-dragon/assets/ui/part-rapidite.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' },
 | 
			
		||||
    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 = {
 | 
			
		||||
  personnage: 'personnage',
 | 
			
		||||
  creature: 'creature',
 | 
			
		||||
 
 | 
			
		||||
@@ -58,6 +58,7 @@ export class RdDInitiative {
 | 
			
		||||
    return {
 | 
			
		||||
      roll: roll,
 | 
			
		||||
      value: value,
 | 
			
		||||
      rang: formule.phase.rang,
 | 
			
		||||
      init: formule.phase.rang + value / 100,
 | 
			
		||||
      label: formule.phase.label
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -32,6 +32,7 @@ export class RdDItemCompetenceCreature extends RdDItem {
 | 
			
		||||
            initiative: initative,
 | 
			
		||||
            mortalite: this.system.mortalite,
 | 
			
		||||
            dommages: this.system.dommages,
 | 
			
		||||
            forceRequise: 0,
 | 
			
		||||
            equipe: true,
 | 
			
		||||
            resistance: 100,
 | 
			
		||||
            penetration: 0,
 | 
			
		||||
@@ -43,7 +44,8 @@ export class RdDItemCompetenceCreature extends RdDItem {
 | 
			
		||||
        carac: { key: this.name, value: this.system.carac_value },
 | 
			
		||||
        equipe: true,
 | 
			
		||||
        mortalite: this.system.mortalite,
 | 
			
		||||
        dmg: this.system.dommages,
 | 
			
		||||
        dommages: this.system.dommages,
 | 
			
		||||
        //dmg: this.system.dommages,
 | 
			
		||||
        initiative: initative
 | 
			
		||||
      };
 | 
			
		||||
      return attaque
 | 
			
		||||
 
 | 
			
		||||
@@ -260,7 +260,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  /** @override */
 | 
			
		||||
  _updateObject(event, formData) {
 | 
			
		||||
  async _updateObject(event, formData) {
 | 
			
		||||
    switch (this.item.type) {
 | 
			
		||||
      case ITEM_TYPES.sort:
 | 
			
		||||
        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']
 | 
			
		||||
        break
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this.item.update(formData)
 | 
			
		||||
    return await super._updateObject(event, formData)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
 
 | 
			
		||||
@@ -148,10 +148,17 @@ export class RdDItemSort extends Item {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  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)) {
 | 
			
		||||
      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 bonus = Number(existing?.bonus ?? 0) + 1
 | 
			
		||||
    if (existing) {
 | 
			
		||||
@@ -160,11 +167,9 @@ export class RdDItemSort extends Item {
 | 
			
		||||
    else {
 | 
			
		||||
      list.push({ case: coord, bonus: 1 })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': RdDItemSort.bonuscasesToString(list) }]);
 | 
			
		||||
    return RdDItemSort.bonuscasesToString(list)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static getCaseBonus(sort, coord) {
 | 
			
		||||
    const search = TMRUtility.isFleuve(coord)
 | 
			
		||||
@@ -189,4 +194,22 @@ export class RdDItemSort extends Item {
 | 
			
		||||
      .map(it => it.split(':'))
 | 
			
		||||
      .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
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -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 { ITEM_ACTIONS, DEFAULT_ACTIONS, COMMON_ACTIONS } from "./item/item-actions.js";
 | 
			
		||||
 | 
			
		||||
@@ -629,7 +629,7 @@ export class RdDItem extends Item {
 | 
			
		||||
  _armeChatData() {
 | 
			
		||||
    return [
 | 
			
		||||
      `<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>Resistance</b>: ${this.system.resistance}`,
 | 
			
		||||
      ...this._inventaireTemplateChatData()
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { ITEM_TYPES } from "../constants.js";
 | 
			
		||||
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js";
 | 
			
		||||
import { RdDItem } from "../item.js";
 | 
			
		||||
import { BASE_CORPS_A_CORPS } from "./base-items.js";
 | 
			
		||||
import { Grammar } from "../grammar.js";
 | 
			
		||||
@@ -27,10 +27,11 @@ export const ATTAQUE_TYPE = {
 | 
			
		||||
  TIR: '(tir)',
 | 
			
		||||
  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 PUGILAT = 'pugilat'
 | 
			
		||||
export const EMPOIGNADE = 'empoignade'
 | 
			
		||||
export const EMPOIGNADE = RDD_CONFIG.encaissement.empoignade
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------- */
 | 
			
		||||
export class RdDItemArme extends RdDItem {
 | 
			
		||||
@@ -254,15 +255,23 @@ export class RdDItemArme extends RdDItem {
 | 
			
		||||
    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) {
 | 
			
		||||
    return RdDItemArme.$corpsACorps(actor, 'Pugilat', PUGILAT)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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 melee = actor ? actor.system.carac['melee'].value : 0
 | 
			
		||||
    return new RdDItemArme({
 | 
			
		||||
@@ -277,10 +286,10 @@ export class RdDItemArme extends RdDItem {
 | 
			
		||||
        force: 0,
 | 
			
		||||
        dommages: "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,
 | 
			
		||||
        resistance: 1,
 | 
			
		||||
        baseInit: cac == EMPOIGNADE ? 3 : 4,
 | 
			
		||||
        baseInit: cac == RDD_CONFIG.encaissement.empoignade ? 3 : 4,
 | 
			
		||||
        cac: cac,
 | 
			
		||||
        deuxmains: true,
 | 
			
		||||
        categorie_parade: 'sans-armes'
 | 
			
		||||
 
 | 
			
		||||
@@ -71,21 +71,25 @@ export class RdDItemBlessure extends RdDItem {
 | 
			
		||||
    return 0
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static async createBlessure(actor, gravite, localisation = '', attackerToken) {
 | 
			
		||||
    const definition = RdDItemBlessure.getDefinition(gravite)
 | 
			
		||||
    const blessure = {
 | 
			
		||||
  static async createBlessure(actor, gravite, localisation = '', attackerToken = undefined) {
 | 
			
		||||
    const blessure = RdDItemBlessure.prepareBlessure(gravite, localisation, attackerToken);
 | 
			
		||||
    const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
 | 
			
		||||
    return blessures[0]
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static prepareBlessure(gravite, localisation, attackerToken) {
 | 
			
		||||
    const definition = RdDItemBlessure.getDefinition(gravite);
 | 
			
		||||
    return {
 | 
			
		||||
      name: definition.label,
 | 
			
		||||
      type: 'blessure',
 | 
			
		||||
      img: definition.icon,
 | 
			
		||||
      system: {
 | 
			
		||||
        gravite: gravite,
 | 
			
		||||
        difficulte: - gravite,
 | 
			
		||||
        difficulte: -gravite,
 | 
			
		||||
        localisation: localisation,
 | 
			
		||||
        origine: attackerToken?.name ?? ""
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
 | 
			
		||||
    return blessures[0]
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static async createTacheSoinBlessure(actor, gravite) {
 | 
			
		||||
 
 | 
			
		||||
@@ -12,12 +12,13 @@ const _SPACEHOLDER = { placeholder: true }
 | 
			
		||||
 | 
			
		||||
const _VENDRE = {
 | 
			
		||||
  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()
 | 
			
		||||
}
 | 
			
		||||
const _ACHETER = {
 | 
			
		||||
  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)
 | 
			
		||||
}
 | 
			
		||||
const _MONTRER = {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
import { RDD_CONFIG } from "./constants.js";
 | 
			
		||||
import { RdDItemArme } from "./item/arme.js";
 | 
			
		||||
import { RdDPossession } from "./rdd-possession.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 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
 | 
			
		||||
@@ -47,19 +48,19 @@ export class RdDBonus {
 | 
			
		||||
      penetration: RdDBonus._peneration(rollData),
 | 
			
		||||
      dmgTactique: RdDBonus.dmgBonus(rollData.tactique),
 | 
			
		||||
      dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
 | 
			
		||||
      dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris.used),
 | 
			
		||||
      mortalite: RdDBonus._calculMortalite(rollData, isEntiteIncarnee),
 | 
			
		||||
      dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris?.used),
 | 
			
		||||
      mortalite: RdDBonus.mortalite(rollData.dmg?.mortalite, rollData.arme?.system.mortalite),
 | 
			
		||||
      dmgActor: RdDBonus.bonusDmg(actor, rollData.selectedCarac?.label.toLowerCase(), dmgArme),
 | 
			
		||||
      dmgForceInsuffisante: Math.min(0, actor.getForce() - forceRequise)
 | 
			
		||||
    }
 | 
			
		||||
    dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere + dmg.dmgForceInsuffisante
 | 
			
		||||
    return dmg;
 | 
			
		||||
    return dmg
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static dmgRollV2(rollData, attaque) {
 | 
			
		||||
    const actor = rollData.active.actor
 | 
			
		||||
    const arme = attaque.arme
 | 
			
		||||
    const dmgArme = RdDBonus.dmgArme(arme, attaque.dommagesArme)
 | 
			
		||||
    const dmgArme = RdDBonus.dmgArme(arme, attaque.dommages)
 | 
			
		||||
    const dmg = {
 | 
			
		||||
      total: 0,
 | 
			
		||||
      dmgArme: dmgArme,
 | 
			
		||||
@@ -68,11 +69,12 @@ export class RdDBonus {
 | 
			
		||||
      dmgTactique: attaque.tactique?.dmg ?? 0,
 | 
			
		||||
      dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
 | 
			
		||||
      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),
 | 
			
		||||
      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
 | 
			
		||||
    }
 | 
			
		||||
    dmg.isEmpoignade = dmg.mortalite == RDD_CONFIG.encaissement.empoignade
 | 
			
		||||
    dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere + dmg.dmgForceInsuffisante + dmg.dmgDiffLibre
 | 
			
		||||
    return dmg
 | 
			
		||||
  }
 | 
			
		||||
@@ -93,21 +95,14 @@ export class RdDBonus {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static _calculMortalite(rollData, isEntiteIncarnee) {
 | 
			
		||||
    return RdDBonus.mortalite(rollData.dmg?.mortalite, rollData.arme?.system.mortalite, isEntiteIncarnee)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static mortalite(mortaliteSelect, mortaliteArme, isEntiteIncarnee) {
 | 
			
		||||
    return isEntiteIncarnee ? "entiteincarnee"
 | 
			
		||||
      : mortaliteSelect
 | 
			
		||||
      ?? mortaliteArme
 | 
			
		||||
      ?? "mortel";
 | 
			
		||||
  static mortalite(mortaliteSelect, mortaliteArme) {
 | 
			
		||||
    return mortaliteSelect ?? mortaliteArme ?? RDD_CONFIG.encaissement.mortel
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static dmgArme(arme, dommagesMain) {
 | 
			
		||||
  static dmgArme(arme, dommages) {
 | 
			
		||||
    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)
 | 
			
		||||
      return dmgBase + Math.min(dmgBase, arme.system.magique ? arme.system.ecaille_efficacite : 0);
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
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 { Misc } from "./misc.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 RollDialog from "./roll/roll-dialog.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 { 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 { 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() {
 | 
			
		||||
    await this.finDeRound();
 | 
			
		||||
@@ -380,7 +385,7 @@ export class RdDCombat {
 | 
			
		||||
    if (defenderToken && Misc.isFirstConnectedGM()) {
 | 
			
		||||
      const rddCombat = RdDCombat.rddCombatForAttackerAndDefender(msg.attackerId, msg.attackerToken.id, msg.defenderToken.id)
 | 
			
		||||
      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)
 | 
			
		||||
        rddCombat?._chatMessageDefenseV2(msg.paramChatDefense)
 | 
			
		||||
      } else {
 | 
			
		||||
@@ -403,7 +408,6 @@ export class RdDCombat {
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static registerChatCallbacks(html) {
 | 
			
		||||
    for (let button of [
 | 
			
		||||
      '.button-defense',
 | 
			
		||||
      '.button-parade',
 | 
			
		||||
      '.button-esquive',
 | 
			
		||||
      '.button-encaisser',
 | 
			
		||||
@@ -475,8 +479,6 @@ export class RdDCombat {
 | 
			
		||||
 | 
			
		||||
    switch (button) {
 | 
			
		||||
      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-esquive': return this.esquive(attackerRoll, compId, competence);
 | 
			
		||||
      case '.button-encaisser': return this.encaisser(attackerRoll, defenderRoll);
 | 
			
		||||
@@ -561,7 +563,7 @@ export class RdDCombat {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  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 en défense, pas de changement à la règle de base
 | 
			
		||||
      return rollData.rolled.isETotal
 | 
			
		||||
@@ -575,7 +577,7 @@ export class RdDCombat {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static isParticuliere(rollData) {
 | 
			
		||||
    if (rollData.ids /* roll V2*/) {
 | 
			
		||||
    if (rollData.v2 /* roll V2*/) {
 | 
			
		||||
      return rollData.rolled.isPart
 | 
			
		||||
    }
 | 
			
		||||
    if (rollData.attackerRoll || !rollData.ajustements.surprise.used) {
 | 
			
		||||
@@ -586,7 +588,7 @@ export class RdDCombat {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static isReussite(rollData) {
 | 
			
		||||
    if (rollData.ids /* roll V2*/) {
 | 
			
		||||
    if (rollData.v2 /* roll V2*/) {
 | 
			
		||||
      return rollData.rolled.isSuccess
 | 
			
		||||
    }
 | 
			
		||||
    if (!rollData.ajustements.surprise.used) {
 | 
			
		||||
@@ -602,7 +604,7 @@ export class RdDCombat {
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  async proposerAjustementTirLancer(rollData) {
 | 
			
		||||
    if (['tir', 'lancer'].includes(rollData.competence.system.categorie)) {
 | 
			
		||||
      if (this.defender.isEntite([ENTITE_BLURETTE])) {
 | 
			
		||||
      if (this.defender.isEntiteBlurette()) {
 | 
			
		||||
        ChatMessage.create({
 | 
			
		||||
          content: `<strong>La cible est une blurette, l'arme à distance sera perdue dans le blurêve`,
 | 
			
		||||
          whisper: ChatUtility.getGMs()
 | 
			
		||||
@@ -686,11 +688,7 @@ export class RdDCombat {
 | 
			
		||||
  async doRollAttaque(rollData, callbacks = []) {
 | 
			
		||||
    // TODO V2 await this.proposerAjustementTirLancer(rollData)
 | 
			
		||||
    await RollDialog.create(rollData, {
 | 
			
		||||
      onRollDone: (dialog) => {
 | 
			
		||||
        if (!OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST))
 | 
			
		||||
          dialog.close()
 | 
			
		||||
      },
 | 
			
		||||
      customChatMessage: true,
 | 
			
		||||
      onRollDone: RollDialog.onRollDoneClose,
 | 
			
		||||
      callbacks: [
 | 
			
		||||
        async (roll) => await this.onAttaqueV2(roll),
 | 
			
		||||
        ...callbacks
 | 
			
		||||
@@ -730,26 +728,24 @@ export class RdDCombat {
 | 
			
		||||
  async _chatMessageDefenseV2(paramDemandeDefense) {
 | 
			
		||||
    const attackerRoll = paramDemandeDefense.attackerRoll;
 | 
			
		||||
    RollBasicParts.loadSurprises(attackerRoll)
 | 
			
		||||
    attackerRoll.passeArme = attackerRoll.passeArme ?? foundry.utils.randomID(16)
 | 
			
		||||
    attackerRoll.dmg = RdDBonus.dmgRollV2(attackerRoll, attackerRoll.current.attaque)
 | 
			
		||||
    // attackerRoll.current.attaque.dmg = attackerRoll.dmg
 | 
			
		||||
    // attaque.dmg = attackerRoll.current.attaque.dmg
 | 
			
		||||
    const attaque = RollDialog.saveParts(attackerRoll)
 | 
			
		||||
    const defense = {
 | 
			
		||||
      attackerRoll: attaque,
 | 
			
		||||
      ids: RollBasicParts.reverseIds(attaque),
 | 
			
		||||
      passeArme: attaque.passeArme ?? foundry.utils.randomID(16)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const defenseData = RollBasicParts.prepareDefense(attackerRoll)
 | 
			
		||||
 | 
			
		||||
    const choixDefense = await ChatMessage.create({
 | 
			
		||||
      // message privé: du défenseur à lui même (et aux GMs)
 | 
			
		||||
      speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
 | 
			
		||||
      alias: this.attacker?.getAlias(),
 | 
			
		||||
      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
 | 
			
		||||
    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: {}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (this.attacker.isCreatureEntite()) {
 | 
			
		||||
    if (this.attacker.isCreatureOuEntite()) {
 | 
			
		||||
      MappingCreatureArme.setRollDataCreature(rollData);
 | 
			
		||||
    }
 | 
			
		||||
    else if (arme) {
 | 
			
		||||
@@ -873,7 +869,7 @@ export class RdDCombat {
 | 
			
		||||
  async _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: {} }
 | 
			
		||||
    attackerRoll.show = {
 | 
			
		||||
      cible: this.defender?.getAlias() ?? 'la cible',
 | 
			
		||||
@@ -892,7 +888,10 @@ export class RdDCombat {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  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);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async defenseV2(attackerRoll) {
 | 
			
		||||
  async defenseV2(attackerRoll, callbacks = []) {
 | 
			
		||||
    // this._prepareParade(attackerRoll, arme, competence);
 | 
			
		||||
    RollDialog.loadRollData(attackerRoll)
 | 
			
		||||
    await this.doRollDefense({
 | 
			
		||||
@@ -1067,15 +1066,14 @@ export class RdDCombat {
 | 
			
		||||
        opponentId: this.attackerId,
 | 
			
		||||
      },
 | 
			
		||||
      type: { allowed: [ROLL_TYPE_DEFENSE], current: ROLL_TYPE_DEFENSE },
 | 
			
		||||
      attackerRoll: RollDialogAdapter.mapActionAttaque(attackerRoll),
 | 
			
		||||
      attackerRoll: attackerRoll,
 | 
			
		||||
      passeArme: attackerRoll.passeArme,
 | 
			
		||||
    })
 | 
			
		||||
    }, callbacks)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async doRollDefense(rollData, callbacks = []) {
 | 
			
		||||
    await RollDialog.create(rollData, {
 | 
			
		||||
      onRollDone: RollDialog.onRollDoneClose,
 | 
			
		||||
      customChatMessage: true,
 | 
			
		||||
      callbacks: [
 | 
			
		||||
        async (roll) => {
 | 
			
		||||
          this.removeChatMessageActionsPasseArme(roll.passeArme);
 | 
			
		||||
@@ -1109,7 +1107,7 @@ export class RdDCombat {
 | 
			
		||||
      show: {}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (this.defender.isCreatureEntite()) {
 | 
			
		||||
    if (this.defender.isCreatureOuEntite()) {
 | 
			
		||||
      MappingCreatureArme.setRollDataCreature(defenderRoll);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -1236,7 +1234,7 @@ export class RdDCombat {
 | 
			
		||||
      show: {}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    if (this.defender.isCreatureEntite()) {
 | 
			
		||||
    if (this.defender.isCreatureOuEntite()) {
 | 
			
		||||
      MappingCreatureArme.setRollDataCreature(rollData);
 | 
			
		||||
    }
 | 
			
		||||
    return rollData;
 | 
			
		||||
 
 | 
			
		||||
@@ -461,12 +461,7 @@ export class RdDCommands {
 | 
			
		||||
 | 
			
		||||
  async supprimerSignesDraconiquesEphemeres() {
 | 
			
		||||
    if (game.user.isGM) {
 | 
			
		||||
      game.actors.forEach(actor => {
 | 
			
		||||
        const ephemeres = actor.items.filter(item => item.type = 'signedraconique' && item.system.ephemere);
 | 
			
		||||
        if (ephemeres.length > 0) {
 | 
			
		||||
          actor.deleteEmbeddedDocuments("Item", ephemeres.map(item => item.id));
 | 
			
		||||
        }
 | 
			
		||||
      });
 | 
			
		||||
      game.actors.forEach(actor => actor.supprimerSignesDraconiques(it => it.system.ephemere))
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      ui.notifications.warn("Seul le MJ est autorisé à utiliser la commande /signe");
 | 
			
		||||
 
 | 
			
		||||
@@ -4,6 +4,8 @@ import { ChatUtility } from "./chat-utility.js";
 | 
			
		||||
import { RdDRollResult } from "./rdd-roll-result.js";
 | 
			
		||||
import { RdDRoll } from "./rdd-roll.js";
 | 
			
		||||
import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs";
 | 
			
		||||
import { MAP_PHASE } from "./initiative.mjs";
 | 
			
		||||
import { RdDCombatManager } from "./rdd-combat.js";
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------- */
 | 
			
		||||
export class RdDEmpoignade {
 | 
			
		||||
@@ -12,6 +14,49 @@ export class RdDEmpoignade {
 | 
			
		||||
  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) {
 | 
			
		||||
    $(html).on("click", '.defense-empoignade-cac', event => {
 | 
			
		||||
@@ -184,7 +229,7 @@ export class RdDEmpoignade {
 | 
			
		||||
      selectedCarac: attacker.system.carac.melee,
 | 
			
		||||
      malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
 | 
			
		||||
    }
 | 
			
		||||
    if (attacker.isCreatureEntite()) {
 | 
			
		||||
    if (attacker.isCreatureOuEntite()) {
 | 
			
		||||
      MappingCreatureArme.setRollDataCreature(rollData)
 | 
			
		||||
    }
 | 
			
		||||
    if (empoignade.system.pointsemp >= 2) {
 | 
			
		||||
@@ -237,10 +282,7 @@ export class RdDEmpoignade {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    if (rollData.rolled.isSuccess && isNouvelle) {
 | 
			
		||||
      const objectEmpoignade = rollData.empoignade.toObject();
 | 
			
		||||
      // Creer l'empoignade sur attaquant/defenseur
 | 
			
		||||
      attacker.creerObjetParMJ(objectEmpoignade);
 | 
			
		||||
      defender.creerObjetParMJ(objectEmpoignade);
 | 
			
		||||
      RdDEmpoignade.$createEtatEmpoignade(rollData.empoignade)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    rollData.empoignade.isSuccess = rollData.rolled.isSuccess;
 | 
			
		||||
@@ -259,7 +301,7 @@ export class RdDEmpoignade {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let empoignade = this.getEmpoignade(attacker, defender)
 | 
			
		||||
    let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
 | 
			
		||||
 | 
			
		||||
    if (!empoignade) {
 | 
			
		||||
      ui.notifications.warn("Une erreur s'est produite : Aucune empoignade trouvée !!")
 | 
			
		||||
@@ -317,18 +359,33 @@ export class RdDEmpoignade {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static async $updateEtatEmpoignade(empoignade) {
 | 
			
		||||
    console.log("UPDATE Empoignade", empoignade)
 | 
			
		||||
  static async $createEtatEmpoignade(empoignade) {
 | 
			
		||||
    console.log("CREATE Empoignade", empoignade)
 | 
			
		||||
 | 
			
		||||
    let defender = game.actors.get(empoignade.system.empoigneid)
 | 
			
		||||
    let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
 | 
			
		||||
    let update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
 | 
			
		||||
    await defender.updateEmbeddedDocuments('Item', [update])
 | 
			
		||||
 | 
			
		||||
    let attacker = game.actors.get(empoignade.system.empoigneurid)
 | 
			
		||||
    emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
 | 
			
		||||
    update = { _id: emp._id, "system.pointsemp": empoignade.system.pointsemp, "system.ausol": empoignade.system.ausol }
 | 
			
		||||
    await attacker.updateEmbeddedDocuments('Item', [update])
 | 
			
		||||
 | 
			
		||||
    // Creer l'empoignade sur attaquant/defenseur
 | 
			
		||||
    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)) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    let empoignade = this.getEmpoignade(attacker, defender)
 | 
			
		||||
    let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
 | 
			
		||||
 | 
			
		||||
    empoignade.system.ausol = true
 | 
			
		||||
    await this.$updateEtatEmpoignade(empoignade)
 | 
			
		||||
@@ -366,7 +423,7 @@ export class RdDEmpoignade {
 | 
			
		||||
    if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    let empoignade = this.getEmpoignade(attacker, defender)
 | 
			
		||||
    let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
 | 
			
		||||
 | 
			
		||||
    await defender.setEffect(STATUSES.StatusProne, true);
 | 
			
		||||
    await this.$deleteEmpoignade(empoignade)
 | 
			
		||||
@@ -382,7 +439,7 @@ export class RdDEmpoignade {
 | 
			
		||||
    if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
    let empoignade = this.getEmpoignade(attacker, defender)
 | 
			
		||||
    let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
 | 
			
		||||
 | 
			
		||||
    //console.log("Perte d'endurance :!!!", perteMode)
 | 
			
		||||
    let endValue = defender.system.sante.endurance.value
 | 
			
		||||
@@ -423,9 +480,17 @@ export class RdDEmpoignade {
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static async createEmpoignade(attacker, defender) {
 | 
			
		||||
    return await Item.create({
 | 
			
		||||
      name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name,
 | 
			
		||||
      type: 'empoignade',
 | 
			
		||||
      system: { description: "", empoignadeid: foundry.utils.randomID(16), compteempoigne: 0, empoigneurid: attacker.id, empoigneid: defender.id, ptsemp: 0, empoigneurname: attacker.name, empoignename: defender.name }
 | 
			
		||||
      name: "Empoignade de " + attacker.name + ' sur ' + defender.name,
 | 
			
		||||
      type: ITEM_TYPES.empoignade,
 | 
			
		||||
      system: {
 | 
			
		||||
        description: "",
 | 
			
		||||
        empoignadeid: foundry.utils.randomID(16),
 | 
			
		||||
        empoigneurid: attacker.id,
 | 
			
		||||
        empoigneid: defender.id,
 | 
			
		||||
        pointsemp: 0,
 | 
			
		||||
        empoigneurname: attacker.name,
 | 
			
		||||
        empoignename: defender.name
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
      {
 | 
			
		||||
        temporary: true
 | 
			
		||||
 
 | 
			
		||||
@@ -95,7 +95,7 @@ export class RdDPossession {
 | 
			
		||||
 | 
			
		||||
  static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
 | 
			
		||||
    rollData.competence = rollingActor.getDraconicOuPossession();
 | 
			
		||||
    if (rollingActor.isCreatureEntite()) {
 | 
			
		||||
    if (rollingActor.isCreatureOuEntite()) {
 | 
			
		||||
      const carac = rollingActor.system.carac
 | 
			
		||||
      rollData.carac = carac
 | 
			
		||||
      rollData.competence.system.defaut_carac = 'reve'
 | 
			
		||||
 
 | 
			
		||||
@@ -16,17 +16,20 @@ const levelDown = [
 | 
			
		||||
];
 | 
			
		||||
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 = [
 | 
			
		||||
  { 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: "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) },
 | 
			
		||||
  { 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) },
 | 
			
		||||
  reussiteNormale,
 | 
			
		||||
  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: "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;
 | 
			
		||||
/* -------------------------------------------- */
 | 
			
		||||
@@ -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) {
 | 
			
		||||
    chances.roll = Math.min(chances.part + 1, chances.sign)
 | 
			
		||||
@@ -192,6 +200,7 @@ export class RdDResolutionTable {
 | 
			
		||||
      if (chances.norm < roll * diviseur) {
 | 
			
		||||
        return reussiteInsuffisante
 | 
			
		||||
      }
 | 
			
		||||
      return reussiteSignificative
 | 
			
		||||
    }
 | 
			
		||||
    return reussite
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -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";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -16,34 +16,29 @@ export class RdDEncaisser extends Dialog {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  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",
 | 
			
		||||
      content: html,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!actor.isEntite()) {
 | 
			
		||||
      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") }
 | 
			
		||||
      default: RDD_CONFIG.encaissement.mortel,
 | 
			
		||||
      buttons: {
 | 
			
		||||
        [RDD_CONFIG.encaissement.mortel]: { label: "Mortel", callback: html => this.performEncaisser(RDD_CONFIG.encaissement.mortel) },
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    let dialogOptions = {
 | 
			
		||||
      classes: ["rdd-roll-dialog"],
 | 
			
		||||
      width: 320,
 | 
			
		||||
      height: 'fit-content'
 | 
			
		||||
    if (!actor.isEntite()) {
 | 
			
		||||
      dialogConf.buttons[RDD_CONFIG.encaissement.nonmortel] = { label: "Non-mortel", callback: html => this.performEncaisser(RDD_CONFIG.encaissement.nonmortel) }
 | 
			
		||||
      dialogConf.buttons["sonne"] = { label: "Sonné", callback: html => this.actor.setSonne() }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // 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.modifier = 0;
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ export class RdDRollDialogEthylisme extends Dialog {
 | 
			
		||||
  activateListeners(html) {
 | 
			
		||||
    super.activateListeners(html);
 | 
			
		||||
    this.html = html;
 | 
			
		||||
    this.bringToTop();
 | 
			
		||||
    this.bringToFront();
 | 
			
		||||
 | 
			
		||||
    this.html.find(".force-alcool").change((event) => {
 | 
			
		||||
      this.rollData.forceAlcool = Misc.toInt(event.currentTarget.value);
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ export class RdDRollResolutionTable extends Dialog {
 | 
			
		||||
      RdDRollResolutionTable.resolutionTable.render(true);
 | 
			
		||||
    }
 | 
			
		||||
    else{
 | 
			
		||||
      RdDRollResolutionTable.resolutionTable.bringToTop();
 | 
			
		||||
      RdDRollResolutionTable.resolutionTable.bringToFront();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -70,7 +70,7 @@ export class RdDRollResolutionTable extends Dialog {
 | 
			
		||||
  activateListeners(html) {
 | 
			
		||||
    super.activateListeners(html);
 | 
			
		||||
    this.html = html;
 | 
			
		||||
    this.bringToTop();
 | 
			
		||||
    this.bringToFront();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    this.html.find("[name='diffLibre']").val(Misc.toInt(this.rollData.diffLibre));
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ import { RdDCarac } from "./rdd-carac.js";
 | 
			
		||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
 | 
			
		||||
import { ReglesOptionnelles } from "./settings/regles-optionnelles.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";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
@@ -128,7 +128,7 @@ export class RdDRoll extends Dialog {
 | 
			
		||||
  activateListeners(html) {
 | 
			
		||||
    super.activateListeners(html);
 | 
			
		||||
    this.html = html;
 | 
			
		||||
    this.bringToTop();
 | 
			
		||||
    this.bringToFront();
 | 
			
		||||
 | 
			
		||||
    console.log('RdDRoll.activateListeners', this.rollData);
 | 
			
		||||
 | 
			
		||||
@@ -206,7 +206,7 @@ export class RdDRoll extends Dialog {
 | 
			
		||||
      this.updateRollResult(html);
 | 
			
		||||
    });
 | 
			
		||||
    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.html.find('.cuisine-proportions').change((event) => {
 | 
			
		||||
@@ -333,8 +333,8 @@ export class RdDRoll extends Dialog {
 | 
			
		||||
 | 
			
		||||
    // Mise à jour valeurs
 | 
			
		||||
    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("label.dmg-arme-actor").text(rollData.dmg.mortalite == EMPOIGNADE ? EMPOIGNADE : Misc.toSignedString(rollData.dmg.total));
 | 
			
		||||
    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.isEmpoignade ? EMPOIGNADE : Misc.toSignedString(rollData.dmg.total));
 | 
			
		||||
    this.html.find("label.arme-mortalite").text(rollData.dmg.mortalite);
 | 
			
		||||
    this.html.find("div.placeholder-ajustements").empty().append(adjustements);
 | 
			
		||||
    this.html.find("div.placeholder-resolution").empty().append(resolutionTable)
 | 
			
		||||
 
 | 
			
		||||
@@ -82,7 +82,7 @@ export class RdDTMRDialog extends Dialog {
 | 
			
		||||
    this.subdialog = undefined
 | 
			
		||||
    this.displaySize = undefined
 | 
			
		||||
    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 = [];
 | 
			
		||||
    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(".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
 | 
			
		||||
    this.html.find('.lancer-sort').click(event => this.lancerUnSort());
 | 
			
		||||
@@ -169,26 +173,26 @@ export class RdDTMRDialog extends Dialog {
 | 
			
		||||
 | 
			
		||||
  async forceTMRDisplay() {
 | 
			
		||||
    if (this.rendered) {
 | 
			
		||||
      this.bringToTop()
 | 
			
		||||
      this.bringSubDialogToTop();
 | 
			
		||||
      this.bringToFront()
 | 
			
		||||
      this.bringSubDialogToFront();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bringSubDialogToTop() {
 | 
			
		||||
    if (this.subdialog?.bringToTop && this.subdialog?.element && this.subdialog?.element[0]) {
 | 
			
		||||
      this.subdialog.bringToTop();
 | 
			
		||||
  bringSubDialogToFront() {
 | 
			
		||||
    if (this.subdialog?.bringToFront && this.subdialog?.element && this.subdialog?.element[0]) {
 | 
			
		||||
      this.subdialog.bringToFront();
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async restoreTMRAfterAction() {
 | 
			
		||||
    this.subdialog = undefined
 | 
			
		||||
    await this.maximize()
 | 
			
		||||
    this.bringToTop()
 | 
			
		||||
    this.bringToFront()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  forceTMRContinueAction() {
 | 
			
		||||
    ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR');
 | 
			
		||||
    this.bringSubDialogToTop();
 | 
			
		||||
    this.bringSubDialogToFront();
 | 
			
		||||
    return false
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -343,19 +347,8 @@ export class RdDTMRDialog extends Dialog {
 | 
			
		||||
      this.forceTMRContinueAction()
 | 
			
		||||
      return false
 | 
			
		||||
    }
 | 
			
		||||
    this.descenteTMR = true;
 | 
			
		||||
    if (this.actor.tmrApp) {
 | 
			
		||||
      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.descenteTMR = true
 | 
			
		||||
    await await this.actor.quitterTMR(message, this.viewOnly, this.cumulFatigue)
 | 
			
		||||
    this.pixiTMR.close();
 | 
			
		||||
    this.pixiTMR = undefined
 | 
			
		||||
    await super.close();
 | 
			
		||||
@@ -412,7 +405,7 @@ export class RdDTMRDialog extends Dialog {
 | 
			
		||||
  async $ignorerRencontre() {
 | 
			
		||||
    if (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()
 | 
			
		||||
      this.updateTokens();
 | 
			
		||||
      this.$updateValuesDisplay();
 | 
			
		||||
@@ -578,29 +571,6 @@ export class RdDTMRDialog extends Dialog {
 | 
			
		||||
    }, 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) {
 | 
			
		||||
    if (this.viewOnly) {
 | 
			
		||||
@@ -676,14 +646,14 @@ export class RdDTMRDialog extends Dialog {
 | 
			
		||||
      ? TMRUtility.getTMRType(tmr.coord) + " ??"
 | 
			
		||||
      : tmr.label + " (" + tmr.coord + ")");
 | 
			
		||||
 | 
			
		||||
    this.setTMRPendingAction({ bringToTop: () => { } })
 | 
			
		||||
    this.setTMRPendingAction({ bringToFront: () => { } })
 | 
			
		||||
    const myRoll = await RdDDice.rollTotal("1dt", { showDice: SHOW_DICE });
 | 
			
		||||
    this.restoreTMRAfterAction()
 | 
			
		||||
    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())
 | 
			
		||||
    } else {
 | 
			
		||||
      this._tellToUser(myRoll + ": Pas de rencontre en " + coordTMR);
 | 
			
		||||
      ChatUtility.tellToUser(myRoll + ": Pas de rencontre en " + coordTMR);
 | 
			
		||||
      return undefined;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -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 definitionsEncaissement = {
 | 
			
		||||
  "mortel": [
 | 
			
		||||
    { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
 | 
			
		||||
    { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
 | 
			
		||||
    { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 },
 | 
			
		||||
    { minimum: 16, maximum: 19, endurance: "2d6", vie: "2", gravite: 4 },
 | 
			
		||||
    { minimum: 20, maximum: undefined, endurance: "100", vie: "4 + @over20", gravite: 6 },
 | 
			
		||||
  ],
 | 
			
		||||
  "non-mortel": [
 | 
			
		||||
    { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
 | 
			
		||||
    { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
 | 
			
		||||
    { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
 | 
			
		||||
    { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 2 },
 | 
			
		||||
    { minimum: 20, maximum: undefined, endurance: "100", vie: "0", gravite: 2 },
 | 
			
		||||
  ],
 | 
			
		||||
  "entiteincarnee": [
 | 
			
		||||
    { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
 | 
			
		||||
    { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
 | 
			
		||||
    { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
 | 
			
		||||
    { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 0 },
 | 
			
		||||
    { minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 0 },
 | 
			
		||||
  ]
 | 
			
		||||
};
 | 
			
		||||
const TABLE_ENCAISSEMENT_MORTEL = [
 | 
			
		||||
  { minimum: undefined, maximum: 0, endurance: "0", vie: "0", gravite: -1 },
 | 
			
		||||
  { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
 | 
			
		||||
  { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 },
 | 
			
		||||
  { 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 },
 | 
			
		||||
  { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
 | 
			
		||||
  { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 0 },
 | 
			
		||||
  { 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 },
 | 
			
		||||
  { minimum: 1, maximum: 10, endurance: "1d4", vie: "0", gravite: 0 },
 | 
			
		||||
  { minimum: 11, maximum: 15, endurance: "1d6", vie: "0", gravite: 2 },
 | 
			
		||||
  { minimum: 16, maximum: 19, endurance: "2d6", vie: "0", gravite: 4 },
 | 
			
		||||
  { minimum: 20, maximum: undefined, endurance: "3d6 + @over20", vie: "0", gravite: 6 },
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------- */
 | 
			
		||||
export class RdDUtility {
 | 
			
		||||
@@ -278,7 +275,7 @@ export class RdDUtility {
 | 
			
		||||
 | 
			
		||||
    Handlebars.registerHelper('plusMoins', diff => parseInt(diff) ? (diff > 0 ? '+' : '') + Math.round(diff) : diff)
 | 
			
		||||
    Handlebars.registerHelper('fractionOneN', n => new Handlebars.SafeString(Misc.getFractionOneN(n)))
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // Handle v12 removal of this helper
 | 
			
		||||
    Handlebars.registerHelper('select', function (selected, options) {
 | 
			
		||||
      const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
 | 
			
		||||
@@ -286,7 +283,7 @@ export class RdDUtility {
 | 
			
		||||
      const html = options.fn(this);
 | 
			
		||||
      return html.replace(rgx, "$& selected");
 | 
			
		||||
    })
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // logic
 | 
			
		||||
    Handlebars.registerHelper('either', (a, b) => a ?? b);
 | 
			
		||||
    // string manipulation
 | 
			
		||||
@@ -299,7 +296,7 @@ export class RdDUtility {
 | 
			
		||||
    Handlebars.registerHelper('grammar-un', str => Grammar.articleIndetermine(str));
 | 
			
		||||
    Handlebars.registerHelper('grammar-accord', (genre, ...args) => Grammar.accord(genre, args));
 | 
			
		||||
    Handlebars.registerHelper('json-stringify', object => JSON.stringify(object))
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    // math
 | 
			
		||||
    Handlebars.registerHelper('math-sum', (...values) => values.slice(0, -1).reduce(Misc.sum(), 0))
 | 
			
		||||
    Handlebars.registerHelper('math-abs', diff => Math.abs(parseInt(diff)))
 | 
			
		||||
@@ -613,20 +610,20 @@ export class RdDUtility {
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static async getLocalisation(type = 'personnage') {
 | 
			
		||||
    const loc = { result:  await RdDDice.rollTotal("1d20")};
 | 
			
		||||
    const loc = { result: await RdDDice.rollTotal("1d20") };
 | 
			
		||||
    if (type == 'personnage') {
 | 
			
		||||
      if (loc.result <= 3) loc.txt =  "Jambe, genou, pied, jarret";
 | 
			
		||||
      else if (loc.result <= 7) loc.txt =  "Hanche, cuisse, fesse";
 | 
			
		||||
      else if (loc.result <= 9) loc.txt =  "Ventre, reins";
 | 
			
		||||
      else if (loc.result <= 12) loc.txt =  "Poitrine, dos";
 | 
			
		||||
      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 == 19) loc.txt =  "Tête";
 | 
			
		||||
      else if (loc.result == 20) loc.txt =  "Tête (visage)";
 | 
			
		||||
      if (loc.result <= 3) loc.txt = "Jambe, genou, pied, jarret";
 | 
			
		||||
      else if (loc.result <= 7) loc.txt = "Hanche, cuisse, fesse";
 | 
			
		||||
      else if (loc.result <= 9) loc.txt = "Ventre, reins";
 | 
			
		||||
      else if (loc.result <= 12) loc.txt = "Poitrine, dos";
 | 
			
		||||
      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 == 19) loc.txt = "Tête";
 | 
			
		||||
      else if (loc.result == 20) loc.txt = "Tête (visage)";
 | 
			
		||||
    } else {
 | 
			
		||||
      if (loc.result <= 7) loc.txt =  "Jambes/Pattes";
 | 
			
		||||
      else if (loc.result <= 18) loc.txt =  "Corps";
 | 
			
		||||
      else if (loc.result <= 20) loc.txt =  "Tête";
 | 
			
		||||
      if (loc.result <= 7) loc.txt = "Jambes/Pattes";
 | 
			
		||||
      else if (loc.result <= 18) loc.txt = "Corps";
 | 
			
		||||
      else if (loc.result <= 20) loc.txt = "Tête";
 | 
			
		||||
    }
 | 
			
		||||
    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 encaissement = RdDUtility._selectEncaissement(jetTotal, dmg.mortalite);
 | 
			
		||||
    const over20 = Math.max(jetTotal - 20, 0);
 | 
			
		||||
    const encaissement = RdDUtility.$selectEncaissement(targetActor, jetTotal, dmg.mortalite)
 | 
			
		||||
    const over20 = Math.max(jetTotal - 20, 0)
 | 
			
		||||
    encaissement.dmg = dmg
 | 
			
		||||
    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;'
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
@@ -693,15 +690,21 @@ export class RdDUtility {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
  static _selectEncaissement(degats, mortalite) {
 | 
			
		||||
    const table = definitionsEncaissement[mortalite] === undefined ? definitionsEncaissement["mortel"] : definitionsEncaissement[mortalite];
 | 
			
		||||
    for (let encaissement of table) {
 | 
			
		||||
      if ((encaissement.minimum === undefined || encaissement.minimum <= degats)
 | 
			
		||||
        && (encaissement.maximum === undefined || degats <= encaissement.maximum)) {
 | 
			
		||||
        return foundry.utils.duplicate(encaissement);
 | 
			
		||||
      }
 | 
			
		||||
  static $selectEncaissement(targetActor, degats, mortalite) {
 | 
			
		||||
    const table = RdDUtility.$getTableEncaissement(targetActor, mortalite)
 | 
			
		||||
    const encaissement = table.find(it => ((it.minimum ?? degats) <= degats && degats <= (it.maximum ?? degats)))
 | 
			
		||||
    return foundry.utils.duplicate(encaissement ?? table[0])
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* -------------------------------------------- */
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +1,17 @@
 | 
			
		||||
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 { RdDCombat } from "../rdd-combat.js"
 | 
			
		||||
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
 | 
			
		||||
import { RdDResolutionTable } from "../rdd-resolution-table.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 {
 | 
			
		||||
  static init() {
 | 
			
		||||
@@ -18,8 +22,11 @@ export default class ChatRollResult {
 | 
			
		||||
 | 
			
		||||
  static onReady() {
 | 
			
		||||
    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-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-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',
 | 
			
		||||
@@ -38,7 +45,7 @@ export default class ChatRollResult {
 | 
			
		||||
    )
 | 
			
		||||
    const save = RollDialog.saveParts(roll, impacts)
 | 
			
		||||
 | 
			
		||||
    ChatUtility.setMessageData(chatMessage, 'rollData', save)
 | 
			
		||||
    await this.saveChatMessageRoll(chatMessage, save)
 | 
			
		||||
    return chatMessage
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -48,7 +55,7 @@ export default class ChatRollResult {
 | 
			
		||||
    roll.show.chance = this.isAppelChancePossible(roll)
 | 
			
		||||
    roll.show.encaissement = this.isShowEncaissement(roll)
 | 
			
		||||
    roll.show.recul = this.getRecul(roll)
 | 
			
		||||
    //roll.show.particuliere = roll.show.particuliere ?? []
 | 
			
		||||
    roll.show.maladresse = this.getMaladresse(roll)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  isAppelChancePossible(roll) {
 | 
			
		||||
@@ -60,11 +67,28 @@ export default class ChatRollResult {
 | 
			
		||||
  isShowEncaissement(roll) {
 | 
			
		||||
    switch (roll.type.current) {
 | 
			
		||||
      case ROLL_TYPE_DEFENSE:
 | 
			
		||||
        return roll.rolled.isEchec && roll.attackerRoll?.dmg.mortalite != EMPOIGNADE
 | 
			
		||||
        return roll.rolled.isEchec
 | 
			
		||||
    }
 | 
			
		||||
    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) {
 | 
			
		||||
    switch (roll.type.current) {
 | 
			
		||||
@@ -100,7 +124,7 @@ export default class ChatRollResult {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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
 | 
			
		||||
    const html = await renderTemplate(template, roll)
 | 
			
		||||
    return await RdDTextEditor.enrichHTML(html, undefined, { showLink: false })
 | 
			
		||||
  }
 | 
			
		||||
@@ -108,11 +132,14 @@ export default class ChatRollResult {
 | 
			
		||||
  async chatListeners(html) {
 | 
			
		||||
    $(html).on("click", '.appel-chance', event => this.onClickAppelChance(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", '.resister-recul', event => this.onClickRecul(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) {
 | 
			
		||||
@@ -120,15 +147,24 @@ export default class ChatRollResult {
 | 
			
		||||
      case ROLL_TYPE_DEFENSE:
 | 
			
		||||
        return RdDCombat.rddCombatForAttackerAndDefender(roll.ids.opponentId, roll.ids.opponentTokenId, roll.ids.actorTokenId)
 | 
			
		||||
      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
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async saveChatMessageRoll(chatMessage, savedRoll) {
 | 
			
		||||
    await ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  loadChatMessageRoll(chatMessage) {
 | 
			
		||||
    return ChatUtility.getMessageData(chatMessage, 'rollData')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async updateChatMessage(chatMessage, savedRoll) {
 | 
			
		||||
    ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll)
 | 
			
		||||
    await this.saveChatMessageRoll(chatMessage, savedRoll)
 | 
			
		||||
    const copy = foundry.utils.duplicate(savedRoll)
 | 
			
		||||
    RollDialog.loadRollData(copy)
 | 
			
		||||
    savedRoll.dmg = copy.current.attaque?.dmg
 | 
			
		||||
    this.prepareDisplay(copy)
 | 
			
		||||
    chatMessage.update({ content: await this.buildRollHtml(copy) })
 | 
			
		||||
    chatMessage.render(true)
 | 
			
		||||
@@ -136,7 +172,7 @@ export default class ChatRollResult {
 | 
			
		||||
 | 
			
		||||
  onClickAppelChance(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)
 | 
			
		||||
    actor.rollAppelChance(
 | 
			
		||||
      () => this.onAppelChanceSuccess(savedRoll, chatMessage),
 | 
			
		||||
@@ -144,11 +180,13 @@ export default class ChatRollResult {
 | 
			
		||||
    event.preventDefault()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onAppelChanceSuccess(savedRoll, chatMessage) {
 | 
			
		||||
  async onAppelChanceSuccess(savedRoll, chatMessage) {
 | 
			
		||||
    const reRoll = foundry.utils.duplicate(savedRoll)
 | 
			
		||||
    console.log('onAppelChanceSuccess savedRoll', savedRoll)
 | 
			
		||||
    reRoll.type.retry = true
 | 
			
		||||
    await this.updateChatMessage(chatMessage, reRoll)
 | 
			
		||||
    const callbacks = [r => ChatUtility.removeChatMessageId(chatMessage.id)]
 | 
			
		||||
 | 
			
		||||
    // TODO: annuler les effets
 | 
			
		||||
    switch (reRoll.type.current) {
 | 
			
		||||
      case ROLL_TYPE_DEFENSE:
 | 
			
		||||
@@ -171,7 +209,7 @@ export default class ChatRollResult {
 | 
			
		||||
 | 
			
		||||
  onClickAppelDestinee(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)
 | 
			
		||||
 | 
			
		||||
    actor.appelDestinee(async () => {
 | 
			
		||||
@@ -182,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) {
 | 
			
		||||
    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 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 attackerToken = savedRoll.ids.opponentTokenId ? canvas.tokens.get(savedRoll.ids.opponentTokenId) : undefined
 | 
			
		||||
    await defender?.encaisserDommages(attaque.dmg, attacker, undefined, attackerToken, defenderToken)
 | 
			
		||||
 | 
			
		||||
    savedRoll.done.encaissement = true
 | 
			
		||||
    await this.updateChatMessage(chatMessage, savedRoll)
 | 
			
		||||
    switch (attaque.dmg.mortalite) {
 | 
			
		||||
      case RDD_CONFIG.encaissement.empoignade:
 | 
			
		||||
        savedRoll.done = savedRoll.done ?? {}
 | 
			
		||||
        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) {
 | 
			
		||||
    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 attacker = game.actors.get(savedRoll.ids.opponentId)
 | 
			
		||||
    savedRoll.done.recul = await defender.encaisserRecul(attacker.getForce(), savedRoll.attackerRoll.dmg.dmgArme)
 | 
			
		||||
@@ -209,15 +270,37 @@ export default class ChatRollResult {
 | 
			
		||||
  async onClickChoixParticuliere(event) {
 | 
			
		||||
    const choix = event.currentTarget.attributes['data-particuliere'].value
 | 
			
		||||
    const chatMessage = ChatUtility.getChatMessage(event)
 | 
			
		||||
    const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
 | 
			
		||||
    const savedRoll = this.loadChatMessageRoll(chatMessage)
 | 
			
		||||
    savedRoll.particuliere = choix
 | 
			
		||||
    savedRoll.particulieres = [RDD_CONFIG.particuliere[choix]]
 | 
			
		||||
    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 = ChatUtility.getMessageData(chatMessage, 'rollData')
 | 
			
		||||
    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)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -26,7 +26,7 @@ export class RollBasicParts {
 | 
			
		||||
  static loadSurprise(who, forceRequise) {
 | 
			
		||||
    if (who?.actor) {
 | 
			
		||||
      foundry.utils.mergeObject(who,
 | 
			
		||||
        StatusEffects.getActorEffetSurprise(who.actor, forceRequise),
 | 
			
		||||
        StatusEffects.getActorEffetSurprise(who.actor),
 | 
			
		||||
        { overwrite: true, inPlace: true })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -54,13 +54,27 @@ export class RollBasicParts {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
    return {
 | 
			
		||||
      sceneId: rollData.ids.sceneId,
 | 
			
		||||
      actorId: rollData.ids.opponentId,
 | 
			
		||||
      actorTokenId: rollData.ids.opponentTokenId,
 | 
			
		||||
      opponentId: rollData.ids.actorId,
 | 
			
		||||
      opponentTokenId: rollData.actorTokenId
 | 
			
		||||
      opponentTokenId: rollData.ids.actorTokenId
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -12,8 +12,7 @@ export const ROLL_TYPE_TACHE = 'tache'
 | 
			
		||||
export const ATTAQUE_ROLL_TYPES = [ROLL_TYPE_ATTAQUE]
 | 
			
		||||
export const COMBAT_ROLL_TYPES = [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE]
 | 
			
		||||
export const DEMIREVE_ROLL_TYPES = [ROLL_TYPE_SORT]
 | 
			
		||||
export const DEFAULT_ROLL_TYPES = [ROLL_TYPE_COMP, 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 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 DIFF = {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,7 +8,7 @@ import { RdDItemArme } from "../item/arme.js";
 | 
			
		||||
import { RdDBonus } from "../rdd-bonus.js";
 | 
			
		||||
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js";
 | 
			
		||||
import { CARACS } from "../rdd-carac.js";
 | 
			
		||||
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_OEUVRE } 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";
 | 
			
		||||
 | 
			
		||||
/* -------------------------------------------- */
 | 
			
		||||
@@ -27,7 +27,8 @@ export class RollDialogAdapter {
 | 
			
		||||
    RollDialogAdapter.setRollDataRolled(rollData, rolled, rollTitle)
 | 
			
		||||
    RollDialogAdapter.adjustRollDataForV1(rollData)
 | 
			
		||||
    RollDialogAdapter.adjustAttaqueParticuliere(rollData)
 | 
			
		||||
 | 
			
		||||
    RollDialogAdapter.adjustAttaqueDmg(rollData)
 | 
			
		||||
    RollDialogAdapter.adjustDemiSurprise(rollData)
 | 
			
		||||
    return rolled
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -95,16 +96,27 @@ export class RollDialogAdapter {
 | 
			
		||||
      rolled.niveauNecessaire = RdDResolutionTable.findNiveauNecessaire(rollData.selectedCarac.value, rolled.roll)
 | 
			
		||||
      rolled.ajustementNecessaire = rolled.niveauNecessaire - diff
 | 
			
		||||
    }
 | 
			
		||||
    rollData.ajustements = rollData.ajustements.map(aj => {
 | 
			
		||||
      return {
 | 
			
		||||
        used: true,
 | 
			
		||||
        label: aj.label,
 | 
			
		||||
        value: aj.diff,
 | 
			
		||||
        descr: aj.diff == undefined ? aj.label : undefined
 | 
			
		||||
      }
 | 
			
		||||
    })
 | 
			
		||||
    rollData.ajustements = rollData.ajustements.map(a => { return { label: a.label, value: a.value } })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  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) {
 | 
			
		||||
    if (rollData.type.current != ROLL_TYPE_ATTAQUE || !rollData.rolled.isPart) {
 | 
			
		||||
      return
 | 
			
		||||
@@ -112,7 +124,7 @@ export class RollDialogAdapter {
 | 
			
		||||
 | 
			
		||||
    const attaque = rollData.current.attaque;
 | 
			
		||||
    const choix = []
 | 
			
		||||
    const isEmpoignade = attaque.dmg.mortalite == 'empoignade';
 | 
			
		||||
    const isEmpoignade = attaque.dmg.isEmpoignade
 | 
			
		||||
    const isCharge = attaque.tactique == 'charge'
 | 
			
		||||
    /* TODO: cas de créatures faisant des lancers, Glou, Glipzouk */
 | 
			
		||||
    const isMeleeDiffNegative = (attaque.comp.type == ITEM_TYPES.competencecreature || rollData.current.carac.key == CARACS.MELEE)
 | 
			
		||||
@@ -153,8 +165,6 @@ export class RollDialogAdapter {
 | 
			
		||||
      comp: attackerRoll.competence,
 | 
			
		||||
      main: RdDItemArme.getMainAttaque(attackerRoll.competence),
 | 
			
		||||
      equipe: attackerRoll.arme.system.equipe,
 | 
			
		||||
      // carac: { key: caracCode, value: caracValue },
 | 
			
		||||
      // dommagesArme: dommagesArme,
 | 
			
		||||
      diff: attackerRoll.diffLibre,
 | 
			
		||||
      particuliere: attackerRoll.particuliere,
 | 
			
		||||
      tactique: RdDBonus.find(attackerRoll.tactique),
 | 
			
		||||
 
 | 
			
		||||
@@ -44,11 +44,13 @@ import { RollTypeCuisine } from "./roll-type-cuisine.mjs";
 | 
			
		||||
import { RollPartCuisine } from "./roll-part-cuisine.mjs";
 | 
			
		||||
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 ALL_ROLL_TYPES = [
 | 
			
		||||
export const ALL_ROLL_TYPES = [
 | 
			
		||||
  new RollTypeComp(),
 | 
			
		||||
  new RollTypeTache(),
 | 
			
		||||
  new RollTypeAttaque(),
 | 
			
		||||
@@ -85,6 +87,8 @@ const ROLL_PARTS = [
 | 
			
		||||
  new RollPartConditions(),
 | 
			
		||||
  new RollPartEthylisme(),
 | 
			
		||||
  new RollPartMalusArmure(),
 | 
			
		||||
  new RollPartEmpoignadeTaille(),
 | 
			
		||||
  new RollPartEmpoignade(),
 | 
			
		||||
  new RollPartEncTotal(),
 | 
			
		||||
  new RollPartSurEnc(),
 | 
			
		||||
  new RollPartAppelMoral(),
 | 
			
		||||
@@ -173,15 +177,16 @@ const ROLL_PARTS = [
 | 
			
		||||
/* -------------------------------------------- */
 | 
			
		||||
export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2)
 | 
			
		||||
{
 | 
			
		||||
  static onRollDoneDoNothing(dialog) {
 | 
			
		||||
  static onCloseDoNothing() {
 | 
			
		||||
  }
 | 
			
		||||
  static onRollDoneDoNothing(dialog, roll) {
 | 
			
		||||
    dialog.render()
 | 
			
		||||
  }
 | 
			
		||||
  static onRollDoneClose(dialog) {
 | 
			
		||||
    if (!OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST))
 | 
			
		||||
  static onRollDoneClose(dialog, roll) {
 | 
			
		||||
    if (roll.type.retry || !OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST))
 | 
			
		||||
      dialog.close()
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  static init() {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -198,7 +203,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
 | 
			
		||||
 | 
			
		||||
    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))
 | 
			
		||||
    ROLL_PARTS.forEach(p => p.onReady())
 | 
			
		||||
 | 
			
		||||
@@ -236,6 +241,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
 | 
			
		||||
  static async create(rollData, rollOptions = {}) {
 | 
			
		||||
    const rollDialog = new RollDialog(rollData, rollOptions)
 | 
			
		||||
    rollDialog.render(true)
 | 
			
		||||
    return rollDialog
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static get PARTS() {
 | 
			
		||||
@@ -314,6 +320,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
 | 
			
		||||
  constructor(rollData, rollOptions) {
 | 
			
		||||
    super()
 | 
			
		||||
 | 
			
		||||
    this.hooks = []
 | 
			
		||||
    this.rollData = RollDialog.$prepareRollData(rollData)
 | 
			
		||||
    this.rollOptions = {
 | 
			
		||||
      callbacks: [
 | 
			
		||||
@@ -321,13 +328,28 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
 | 
			
		||||
        async r => await r.active.actor.appliquerAppelMoral(r),
 | 
			
		||||
        ...(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.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() {
 | 
			
		||||
    const selectedType = this.getSelectedType();
 | 
			
		||||
    this.rollData.type.label = selectedType.title(this.rollData)
 | 
			
		||||
@@ -383,7 +405,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
 | 
			
		||||
    return RollDialog.getActiveParts(rollData)
 | 
			
		||||
      .map(p => p.getAjustements(rollData))
 | 
			
		||||
      .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) {
 | 
			
		||||
@@ -405,7 +427,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
 | 
			
		||||
 | 
			
		||||
    visibleRollParts.forEach(p => p.prepareContext(rollData))
 | 
			
		||||
 | 
			
		||||
    RollDialog.calculAjustements(rollData)
 | 
			
		||||
    RollDialog.calculAjustement(rollData)
 | 
			
		||||
 | 
			
		||||
    const templates = RollDialog.getActiveParts(rollData).map(p => p.toTemplateData())
 | 
			
		||||
    const context = await super._prepareContext()
 | 
			
		||||
@@ -427,12 +449,11 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static calculAjustements(rollData) {
 | 
			
		||||
  static calculAjustement(rollData) {
 | 
			
		||||
    rollData.ajustements = RollDialog.getAjustements(rollData)
 | 
			
		||||
    rollData.ajustements.forEach(it => it.isDiff = it.diff != undefined)
 | 
			
		||||
    rollData.current.totaldiff = rollData.ajustements
 | 
			
		||||
      .map(adj => adj.diff)
 | 
			
		||||
      .filter(d => d != undefined)
 | 
			
		||||
      .filter(a => a.value != undefined)
 | 
			
		||||
      .map(a => a.value)
 | 
			
		||||
      .reduce(Misc.sum(), 0)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -440,20 +461,25 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
 | 
			
		||||
    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() {
 | 
			
		||||
 | 
			
		||||
    const roll = RollDialog.saveParts(this.rollData)
 | 
			
		||||
    this.loadRollData(roll)
 | 
			
		||||
    RollDialog.loadRollData(roll)
 | 
			
		||||
    const selectedRollType = this.getSelectedType(roll);
 | 
			
		||||
    selectedRollType.onSelect(roll)
 | 
			
		||||
    roll.current.resultat = this.rollData.current[PART_TRICHER]?.resultat ?? -1
 | 
			
		||||
    roll.choix = {}
 | 
			
		||||
    roll.rolled = await RollDialogAdapter.rollDice(roll, this.rollTitle(roll))
 | 
			
		||||
 | 
			
		||||
    const impacts = {
 | 
			
		||||
      active: new ActorImpacts(roll.active),
 | 
			
		||||
      opponent: roll.opponent ? new ActorImpacts(roll.opponent) : undefined
 | 
			
		||||
    }
 | 
			
		||||
    const impacts = new ActorImpacts(roll.active)
 | 
			
		||||
 | 
			
		||||
    roll.result = selectedRollType.getResult(roll, impacts)
 | 
			
		||||
 | 
			
		||||
@@ -465,17 +491,17 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
 | 
			
		||||
 | 
			
		||||
    await Promise.all(callbacks.map(async callback => await callback(roll)))
 | 
			
		||||
 | 
			
		||||
    await impacts.active?.applyImpacts()
 | 
			
		||||
    await impacts.opponent?.applyImpacts()
 | 
			
		||||
    await impacts.applyImpacts()
 | 
			
		||||
    selectedRollType.onApplyImpacts(roll, impacts)
 | 
			
		||||
    await this.chatRollResult.display(roll, impacts)
 | 
			
		||||
    this.rollOptions.onRollDone(this)
 | 
			
		||||
    this.rollOptions.onRollDone(this, roll)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  loadRollData(roll) {
 | 
			
		||||
  static loadRollData(roll) {
 | 
			
		||||
    RollDialog.$prepareRollData(roll)
 | 
			
		||||
    RollDialog.calculAjustements(roll)
 | 
			
		||||
    RollDialog.calculAjustement(roll)
 | 
			
		||||
    roll.v2 = true
 | 
			
		||||
    return roll
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async defaultCallback(roll, rolled) {
 | 
			
		||||
 
 | 
			
		||||
@@ -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 { 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_COMP } from "./roll-part-comp.mjs"
 | 
			
		||||
import { PART_DIFF } from "./roll-part-diff.mjs"
 | 
			
		||||
import { RollPartSelect } from "./roll-part-select.mjs"
 | 
			
		||||
import { PART_SIGN } from "./roll-part-sign.mjs"
 | 
			
		||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
 | 
			
		||||
 | 
			
		||||
export const PART_ATTAQUE = 'attaque'
 | 
			
		||||
 | 
			
		||||
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 {
 | 
			
		||||
 | 
			
		||||
  get code() { return PART_ATTAQUE }
 | 
			
		||||
@@ -20,7 +30,8 @@ export class RollPartAttaque extends RollPartSelect {
 | 
			
		||||
  loadRefs(rollData) {
 | 
			
		||||
    const refs = this.getRefs(rollData)
 | 
			
		||||
    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
 | 
			
		||||
    if (refs.attaques.length > 0) {
 | 
			
		||||
      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) {
 | 
			
		||||
    super.store(rollData, targetData)
 | 
			
		||||
    this.getSaved(targetData).dmg = this.getCurrent(rollData).dmg
 | 
			
		||||
@@ -36,7 +51,7 @@ export class RollPartAttaque extends RollPartSelect {
 | 
			
		||||
  restore(rollData) {
 | 
			
		||||
    const saved = this.getSaved(rollData)
 | 
			
		||||
    super.restore(rollData)
 | 
			
		||||
    if (saved.dmg) {
 | 
			
		||||
    if (saved.dmg != undefined) {
 | 
			
		||||
      this.getCurrent(rollData).dmg = this.getSaved(rollData).dmg
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
@@ -50,14 +65,6 @@ export class RollPartAttaque extends RollPartSelect {
 | 
			
		||||
  choices(refs) { return refs.attaques }
 | 
			
		||||
 | 
			
		||||
  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.tactique = TACTIQUES[0]
 | 
			
		||||
    attaque.initialDiff = attaque.comp?.system.default_diffLibre ?? 0
 | 
			
		||||
@@ -65,20 +72,28 @@ export class RollPartAttaque extends RollPartSelect {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  prepareContext(rollData) {
 | 
			
		||||
    this.filterAttaquesEmpoignade(rollData)
 | 
			
		||||
    const current = this.getCurrent(rollData)
 | 
			
		||||
    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) {
 | 
			
		||||
    const current = this.getCurrent(rollData)
 | 
			
		||||
    const ajustements = []
 | 
			
		||||
    if (current.tactique) {
 | 
			
		||||
      ajustements.push({ label: current.tactique.label, diff: current.tactique.attaque })
 | 
			
		||||
    }
 | 
			
		||||
    if (rollData.opponent?.surprise) {
 | 
			
		||||
      ajustements.push({ label: rollData.opponent.surprise.label, diff: rollData.opponent.surprise.attaque })
 | 
			
		||||
    }
 | 
			
		||||
    return ajustements
 | 
			
		||||
    const tactique = current.tactique ? [{ label: current.tactique.label, value: current.tactique.attaque }] : []
 | 
			
		||||
    const surprise = rollData.opponent?.surprise ? [{ label: rollData.opponent.surprise.label, value: rollData.opponent.surprise.attaque }] : []
 | 
			
		||||
    return [...tactique, ...surprise]
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -90,6 +105,7 @@ export class RollPartAttaque extends RollPartSelect {
 | 
			
		||||
    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 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)
 | 
			
		||||
 | 
			
		||||
    selectAttaque.addEventListener("change", e => {
 | 
			
		||||
@@ -107,9 +123,26 @@ export class RollPartAttaque extends RollPartSelect {
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    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()
 | 
			
		||||
    })
 | 
			
		||||
    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) {
 | 
			
		||||
@@ -123,7 +156,9 @@ export class RollPartAttaque extends RollPartSelect {
 | 
			
		||||
            part.setDiff(rollData, { type: DIFF.ATTAQUE, value: current.initialDiff })
 | 
			
		||||
            current.initialDiff = undefined
 | 
			
		||||
          }
 | 
			
		||||
          break
 | 
			
		||||
        }
 | 
			
		||||
        case PART_SIGN: return part.setArme(rollData, false, current.forceRequise)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return undefined
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
import { Grammar } from "../grammar.js"
 | 
			
		||||
import { RollPartSelect } from "./roll-part-select.mjs"
 | 
			
		||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
 | 
			
		||||
 | 
			
		||||
@@ -12,22 +13,36 @@ export class RollPartCarac extends RollPartSelect {
 | 
			
		||||
 | 
			
		||||
  loadRefs(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
 | 
			
		||||
    this.$selectCarac(rollData)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  choices(refs) { return refs.caracs }
 | 
			
		||||
 | 
			
		||||
  $getActorCaracs(rollData) {
 | 
			
		||||
    return Object.entries(rollData.active.actor.getCarac())
 | 
			
		||||
  $getActorCaracs(actor) {
 | 
			
		||||
    return Object.entries(actor.getCarac())
 | 
			
		||||
      .filter(([key, c]) => key != 'taille')
 | 
			
		||||
      /* TODO: filter by context */
 | 
			
		||||
      .map(([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) {
 | 
			
		||||
    return {
 | 
			
		||||
      key: key,
 | 
			
		||||
@@ -40,7 +55,6 @@ export class RollPartCarac extends RollPartSelect {
 | 
			
		||||
    allowed = allowed.filter(it => it != undefined)
 | 
			
		||||
    const refs = this.getRefs(rollData)
 | 
			
		||||
    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
 | 
			
		||||
    this.$selectCarac(rollData)
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ export class RollPartCheckbox extends RollPart {
 | 
			
		||||
  getAjustements(rollData) {
 | 
			
		||||
    const current = this.getCurrent(rollData)
 | 
			
		||||
    if (current.checked) {
 | 
			
		||||
      return [{ label: this.getCheckboxLabelAjustement(rollData), diff: current.value }]
 | 
			
		||||
      return [{ label: this.getCheckboxLabelAjustement(rollData), value: current.value }]
 | 
			
		||||
    }
 | 
			
		||||
    return []
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ export class RollPartCoeur extends RollPartSelect {
 | 
			
		||||
    if (current.key != '') {
 | 
			
		||||
      return [{
 | 
			
		||||
        label: "Coeur pour " + current.label,
 | 
			
		||||
        diff: current.value
 | 
			
		||||
        value: current.value
 | 
			
		||||
      }]
 | 
			
		||||
    }
 | 
			
		||||
    return []
 | 
			
		||||
 
 | 
			
		||||
@@ -18,12 +18,16 @@ export class RollPartComp extends RollPartSelect {
 | 
			
		||||
  loadRefs(rollData) {
 | 
			
		||||
    const refs = this.getRefs(rollData)
 | 
			
		||||
    const selected = this.getSelected(rollData)
 | 
			
		||||
    refs.all = this.$getActorComps(rollData)
 | 
			
		||||
      .filter(comp => !selected.forced ||
 | 
			
		||||
        (selected.key ?
 | 
			
		||||
          Grammar.includesLowerCaseNoAccent(comp.name, selected.key)
 | 
			
		||||
          : comp.key == '')
 | 
			
		||||
      )
 | 
			
		||||
    const all = this.$getActorComps(rollData)
 | 
			
		||||
    if (selected.forced) {
 | 
			
		||||
      refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selected.key))
 | 
			
		||||
      if (refs.all.length == 0) {
 | 
			
		||||
        refs.all = all.filter(comp => Grammar.includesLowerCaseNoAccent(comp.label, selected.key))
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      refs.all = all
 | 
			
		||||
    }
 | 
			
		||||
    refs.comps = refs.all
 | 
			
		||||
    this.$selectComp(rollData)
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -57,7 +57,7 @@ export class RollPartConditions extends RollPart {
 | 
			
		||||
  getAjustements(rollData) {
 | 
			
		||||
    const current = this.getCurrent(rollData)
 | 
			
		||||
    if (current.value != 0) {
 | 
			
		||||
      return [{ label: DESCR_CONDITIONS, diff: current.value }]
 | 
			
		||||
      return [{ label: DESCR_CONDITIONS, value: current.value }]
 | 
			
		||||
    }
 | 
			
		||||
    return []
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,6 @@
 | 
			
		||||
import { ITEM_TYPES } from "../constants.js"
 | 
			
		||||
import { Grammar } from "../grammar.js"
 | 
			
		||||
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js"
 | 
			
		||||
import { ATTAQUE_TYPE, RdDItemArme } from "../item/arme.js"
 | 
			
		||||
import { RdDBonus } from "../rdd-bonus.js"
 | 
			
		||||
import { CARACS } from "../rdd-carac.js"
 | 
			
		||||
import { StatusEffects } from "../settings/status-effects.js"
 | 
			
		||||
import { DIFF, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
 | 
			
		||||
import { PART_CARAC } from "./roll-part-carac.mjs"
 | 
			
		||||
import { PART_COMP } from "./roll-part-comp.mjs"
 | 
			
		||||
@@ -18,6 +15,8 @@ export class RollPartDefense extends RollPartSelect {
 | 
			
		||||
 | 
			
		||||
  get code() { return PART_DEFENSE }
 | 
			
		||||
  get section() { return ROLLDIALOG_SECTION.CHOIX }
 | 
			
		||||
 | 
			
		||||
  isValid(rollData) { return rollData.attackerRoll != undefined }
 | 
			
		||||
  visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) }
 | 
			
		||||
 | 
			
		||||
  static getDiffAttaque(attackerRoll) {
 | 
			
		||||
@@ -30,13 +29,22 @@ export class RollPartDefense extends RollPartSelect {
 | 
			
		||||
    const attackerRoll = rollData.attackerRoll
 | 
			
		||||
    const defenseur = rollData.active.actor
 | 
			
		||||
    refs.isDistance = [ATTAQUE_TYPE.TIR, ATTAQUE_TYPE.LANCER].find(it => it == attackerRoll?.main)
 | 
			
		||||
    const esquives = refs.isDistance == ATTAQUE_TYPE.TIR ? [] : defenseur.getCompetencesEsquive()
 | 
			
		||||
      .map(it => RollPartDefense.$extractEsquive(it, defenseur))
 | 
			
		||||
    const isEmpoignade = attackerRoll.dmg.isEmpoignade
 | 
			
		||||
    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()))
 | 
			
		||||
      .map(it => RollPartDefense.$extractParade(it, attackerRoll?.arme, defenseur))
 | 
			
		||||
    const esquives = (refs.isDistance == ATTAQUE_TYPE.TIR || isEmpoignadeEnCours)
 | 
			
		||||
      ? []
 | 
			
		||||
      : 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)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -104,7 +112,7 @@ export class RollPartDefense extends RollPartSelect {
 | 
			
		||||
        case PART_CARAC: return part.filterCaracs(rollData, [current.carac])
 | 
			
		||||
        case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
 | 
			
		||||
        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
 | 
			
		||||
@@ -113,7 +121,7 @@ export class RollPartDefense extends RollPartSelect {
 | 
			
		||||
  isArmeDisparate(rollData) {
 | 
			
		||||
    const armeDefense = this.getCurrent(rollData).arme
 | 
			
		||||
    if (armeDefense) {
 | 
			
		||||
      const armeAttaque = rollData.attackerRoll?.arme
 | 
			
		||||
      const armeAttaque = rollData.attackerRoll?.current.attaque.arme
 | 
			
		||||
      return RdDItemArme.defenseArmeParade(armeAttaque, armeDefense) == 'sign'
 | 
			
		||||
    }
 | 
			
		||||
    return false
 | 
			
		||||
@@ -126,7 +134,11 @@ export class RollPartDefense extends RollPartSelect {
 | 
			
		||||
      return { diff: 0, type: DIFF.LIBRE }
 | 
			
		||||
    }
 | 
			
		||||
    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 }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ export class RollPartDiff extends RollPart {
 | 
			
		||||
    const current = this.getCurrent(rollData)
 | 
			
		||||
    return [{
 | 
			
		||||
      label: current.label,
 | 
			
		||||
      diff: current.value
 | 
			
		||||
      value: current.value
 | 
			
		||||
    }]
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										40
									
								
								module/roll/roll-part-empoignade-taille.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								module/roll/roll-part-empoignade-taille.mjs
									
									
									
									
									
										Normal 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)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										30
									
								
								module/roll/roll-part-empoignade.mjs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								module/roll/roll-part-empoignade.mjs
									
									
									
									
									
										Normal 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 }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
import { RDD_CONFIG } from "../constants.js"
 | 
			
		||||
import { RdDItemCompetence } from "../item-competence.js"
 | 
			
		||||
import { RdDCarac } from "../rdd-carac.js"
 | 
			
		||||
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" }
 | 
			
		||||
  getCheckboxValue(rollData) { return - rollData.active.actor.getEncTotal() }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -81,7 +81,9 @@ export class RollPartJeu extends RollPartSelect {
 | 
			
		||||
 | 
			
		||||
  $selectJeu(rollData, key) {
 | 
			
		||||
    this.selectByKey(rollData, key, 0)
 | 
			
		||||
    RollPartJeu.forceCompJeu(rollData)
 | 
			
		||||
    if (rollData.type.current == ROLL_TYPE_JEU) {
 | 
			
		||||
      RollPartJeu.forceCompJeu(rollData)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static forceCompJeu(rollData) {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,10 @@
 | 
			
		||||
import { ITEM_TYPES } from "../constants.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 { TMRUtility } from "../tmr-utility.js"
 | 
			
		||||
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 { RollPartSelect } from "./roll-part-select.mjs"
 | 
			
		||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
 | 
			
		||||
@@ -34,8 +34,9 @@ export class RollPartMeditation extends RollPartSelect {
 | 
			
		||||
 | 
			
		||||
  loadRefs(rollData) {
 | 
			
		||||
    const refs = this.getRefs(rollData)
 | 
			
		||||
    refs.meditations = rollData.active.actor.itemTypes[ITEM_TYPES.meditation]
 | 
			
		||||
      .map(it => RollPartMeditation.$extractMeditation(it, rollData.active.actor))
 | 
			
		||||
    const actor = rollData.active.actor
 | 
			
		||||
    refs.meditations = actor.itemTypes[ITEM_TYPES.meditation]
 | 
			
		||||
      .map(it => RollPartMeditation.$extractMeditation(it, actor))
 | 
			
		||||
 | 
			
		||||
    if (refs.meditations.length > 0) {
 | 
			
		||||
      this.$selectMeditation(rollData)
 | 
			
		||||
@@ -72,9 +73,10 @@ export class RollPartMeditation extends RollPartSelect {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getAjustements(rollData) {
 | 
			
		||||
    const malusEchecs = { label: "Méditation", diff: this.getMalusEchecs(rollData) }
 | 
			
		||||
    const malusConditions = { label: "Conditions", diff: this.getMalusConditions(rollData) }
 | 
			
		||||
    return [malusConditions, ...(malusEchecs.diff == 0 ? [] : [malusEchecs])]
 | 
			
		||||
    const malus = this.getMalusEchecs(rollData)
 | 
			
		||||
    const malusEchecs = malus == 0 ? [] : [{ label: "Méditation", value: malus }]
 | 
			
		||||
    const malusConditions = { label: "Conditions", value: this.getMalusConditions(rollData) }
 | 
			
		||||
    return [malusConditions, ...malusEchecs]
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $selectMeditation(rollData, key) {
 | 
			
		||||
 
 | 
			
		||||
@@ -16,7 +16,7 @@ export class RollPartSelect extends RollPart {
 | 
			
		||||
  getAjustements(rollData) {
 | 
			
		||||
    const current = this.getCurrent(rollData)
 | 
			
		||||
    if (current) {
 | 
			
		||||
      return [{ label: current.label, diff: current.value }]
 | 
			
		||||
      return [{ label: current.label, value: current.value }]
 | 
			
		||||
    }
 | 
			
		||||
    return []
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,7 @@
 | 
			
		||||
import { RDD_CONFIG } from "../constants.js"
 | 
			
		||||
import { Misc } from "../misc.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 { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
 | 
			
		||||
 | 
			
		||||
@@ -39,29 +40,30 @@ export class RollPartSign extends RollPart {
 | 
			
		||||
    const isCombat = this.isCombat(rollData)
 | 
			
		||||
    const current = this.getCurrent(rollData)
 | 
			
		||||
    current.armeDisparate = isCombat && current.armeDisparate
 | 
			
		||||
    current.surprise = actor.getSurprise(isCombat) // TODO: could be from rollData.active.surprise??
 | 
			
		||||
    current.reasons = actor.getEffects(it => StatusEffects.niveauSurprise(it) > 0).map(it => it.name)
 | 
			
		||||
    current.surprise = actor.getSurprise(isCombat, current.forceRequise ?? 0) 
 | 
			
		||||
    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
 | 
			
		||||
    if (current.surprise == 'demi') {
 | 
			
		||||
      current.diviseur *= 2
 | 
			
		||||
    }
 | 
			
		||||
    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)) {
 | 
			
		||||
      current.diviseur *= 2
 | 
			
		||||
      current.reasons.push('Armes disparates')
 | 
			
		||||
      current.reasons.push({ img: RDD_CONFIG.icons.armesDisparates, label: 'Armes disparates' })
 | 
			
		||||
    }
 | 
			
		||||
    if (this.isAttaqueFinesse(rollData)) {
 | 
			
		||||
      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')) {
 | 
			
		||||
      current.diviseur = Math.min(current.diviseur, 4);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    current.reason = current.reasons.join(', ')
 | 
			
		||||
    current.reason = current.reasons.map(it => it.label).join(', ')
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  isAttaqueFinesse(rollData) {
 | 
			
		||||
@@ -76,8 +78,16 @@ export class RollPartSign extends RollPart {
 | 
			
		||||
    const current = this.getCurrent(rollData)
 | 
			
		||||
    if (current.surprise == 'demi') {
 | 
			
		||||
      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 []
 | 
			
		||||
@@ -92,7 +102,9 @@ export class RollPartSign extends RollPart {
 | 
			
		||||
    })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setArmeDisparate(rollData, armeDisparate) {
 | 
			
		||||
    this.getCurrent(rollData).armeDisparate = armeDisparate
 | 
			
		||||
  setArme(rollData, armeDisparate, forceRequise) {
 | 
			
		||||
    const current = this.getCurrent(rollData)
 | 
			
		||||
    current.armeDisparate = armeDisparate
 | 
			
		||||
    current.forceRequise = forceRequise
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -22,9 +22,27 @@ export class RollPartSort extends RollPartSelect {
 | 
			
		||||
  isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() }
 | 
			
		||||
  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) {
 | 
			
		||||
    const refs = this.getRefs(rollData)
 | 
			
		||||
    const coord = rollData.active.actor.system.reve.tmrpos.coord
 | 
			
		||||
    const coord = this.getCoord(rollData)
 | 
			
		||||
    const draconics = rollData.active.actor.getDraconics()
 | 
			
		||||
    const sorts = rollData.active.actor.itemTypes[ITEM_TYPES.sort]
 | 
			
		||||
      .map(s => RollPartSort.$extractSort(s, coord, draconics))
 | 
			
		||||
@@ -33,7 +51,7 @@ export class RollPartSort extends RollPartSelect {
 | 
			
		||||
      {
 | 
			
		||||
        coord: coord,
 | 
			
		||||
        tmr: TMRUtility.getTMR(coord),
 | 
			
		||||
        reve: rollData.active.actor.system.reve.reve.value,
 | 
			
		||||
        reve: this.getReveActuel(rollData),
 | 
			
		||||
        draconics: draconics,
 | 
			
		||||
        all: sorts,
 | 
			
		||||
        sorts: sorts.filter(it => RdDItemSort.isSortOnCoord(it.sort, coord))
 | 
			
		||||
@@ -41,10 +59,18 @@ export class RollPartSort extends RollPartSelect {
 | 
			
		||||
      { inplace: true }
 | 
			
		||||
    )
 | 
			
		||||
    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 }
 | 
			
		||||
 | 
			
		||||
  static $extractSort(sort, coord, draconics) {
 | 
			
		||||
@@ -56,37 +82,35 @@ export class RollPartSort extends RollPartSelect {
 | 
			
		||||
      value: isDiffVariable ? -7 : parseInt(sort.system.difficulte),
 | 
			
		||||
      ptreve: isReveVariable ? 1 : sort.system.ptreve,
 | 
			
		||||
      caseTMR: RdDItemSort.getCaseTMR(sort),
 | 
			
		||||
      bonusCase: RdDItemSort.getCaseBonus(sort, coord),
 | 
			
		||||
      isDiffVariable: isDiffVariable,
 | 
			
		||||
      isReveVariable: isReveVariable,
 | 
			
		||||
      isReserve: false,
 | 
			
		||||
      sort: sort,
 | 
			
		||||
      draconics: RdDItemSort.getDraconicsSort(draconics, sort).map(it => it.name)
 | 
			
		||||
      draconics: RdDItemSort.getDraconicsSort(draconics, sort).map(it => it.name),
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getAjustements(rollData) {
 | 
			
		||||
    const current = this.getCurrent(rollData)
 | 
			
		||||
    if (current) {
 | 
			
		||||
      const reserve = current.isReserve ?
 | 
			
		||||
        [{ label: `Mise en réserve en ${current.coord}` }] : []
 | 
			
		||||
      const bonusCase = current.bonusCase ?
 | 
			
		||||
        [{ label: `Bonus case +${current.bonusCase}%` }] : []
 | 
			
		||||
      return [
 | 
			
		||||
        { label: current.label, diff: current.value },
 | 
			
		||||
        { label: `r${current.ptreve}` },
 | 
			
		||||
        ...bonusCase,
 | 
			
		||||
        ...reserve
 | 
			
		||||
      ]
 | 
			
		||||
      const sort = { label: current.label, value: current.value }
 | 
			
		||||
      const reserve = current.isReserve ? [{ label: `Mise en réserve en ${this.getCoord(rollData)}` }] : []
 | 
			
		||||
      const bonusCase = current.bonusCase ? [{ label: `Bonus case +${current.bonusCase}%` }] : []
 | 
			
		||||
      const reve = { label: `Rêve ${current.ptreve}` }
 | 
			
		||||
      return [sort, ...bonusCase, reve, ...reserve]
 | 
			
		||||
    }
 | 
			
		||||
    return []
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $selectSort(rollData, key) {
 | 
			
		||||
    const previous = this.getCurrent(rollData)
 | 
			
		||||
    const current = this.selectByKey(rollData, key, -7)
 | 
			
		||||
    if (current.key != previous.key) { }
 | 
			
		||||
    current.bonusCase = RdDItemSort.getCaseBonus(current.sort,
 | 
			
		||||
      rollData.active.actor.system.reve.tmrpos.coord)
 | 
			
		||||
  $selectSort(rollData, values) {
 | 
			
		||||
    const current = this.selectByKey(rollData, values.key)
 | 
			
		||||
    if (values.ptreve) {
 | 
			
		||||
      current.ptreve = values.ptreve
 | 
			
		||||
    }
 | 
			
		||||
    if (values.isReserve != undefined) {
 | 
			
		||||
      current.isReserve = values.isReserve
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async _onRender(rollDialog, context, options) {
 | 
			
		||||
@@ -99,7 +123,7 @@ export class RollPartSort extends RollPartSelect {
 | 
			
		||||
    selectSort.addEventListener("change", e => {
 | 
			
		||||
      const selectOptions = e.currentTarget.options
 | 
			
		||||
      const index = selectOptions.selectedIndex
 | 
			
		||||
      this.$selectSort(rollDialog.rollData, selectOptions[index]?.value)
 | 
			
		||||
      this.$selectSort(rollDialog.rollData, { key: selectOptions[index]?.value })
 | 
			
		||||
      rollDialog.render()
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,4 @@
 | 
			
		||||
import { RDD_CONFIG } from "../constants.js"
 | 
			
		||||
import { RdDCarac } from "../rdd-carac.js"
 | 
			
		||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
 | 
			
		||||
 | 
			
		||||
@@ -10,7 +11,7 @@ export class RollPartSurEnc extends RollPartCheckbox {
 | 
			
		||||
  visible(rollData) {
 | 
			
		||||
    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." }
 | 
			
		||||
  getCheckboxValue(rollData) { return rollData.active.actor.computeMalusSurEncombrement() }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -18,10 +18,12 @@ export class RollPartTache extends RollPartSelect {
 | 
			
		||||
  loadRefs(rollData) {
 | 
			
		||||
    const refs = this.getRefs(rollData)
 | 
			
		||||
    const selected = this.getSelected(rollData)
 | 
			
		||||
    refs.forced = selected.forced
 | 
			
		||||
    refs.all = rollData.active.actor.itemTypes[ITEM_TYPES.tache]
 | 
			
		||||
      .filter(tache => !selected.forced || tache.id == selected.key)
 | 
			
		||||
      .filter(tache => tache.system.points_de_tache_courant < tache.system.points_de_tache)
 | 
			
		||||
      .map(tache => RollPartTache.$extractTache(tache, rollData.active.actor))
 | 
			
		||||
 | 
			
		||||
    refs.taches = refs.all
 | 
			
		||||
    if (refs.taches.length > 0) {
 | 
			
		||||
      this.$selectTache(rollData)
 | 
			
		||||
@@ -46,6 +48,8 @@ export class RollPartTache extends RollPartSelect {
 | 
			
		||||
 | 
			
		||||
  async _onRender(rollDialog, context, options) {
 | 
			
		||||
    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 => {
 | 
			
		||||
      const selectOptions = e.currentTarget.options
 | 
			
		||||
@@ -53,14 +57,43 @@ export class RollPartTache extends RollPartSelect {
 | 
			
		||||
      this.$selectTache(rollDialog.rollData, selectOptions[index]?.value)
 | 
			
		||||
      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) {
 | 
			
		||||
    if (this.visible(rollData)) {
 | 
			
		||||
      const current = this.getCurrent(rollData)
 | 
			
		||||
      switch (part.code) {
 | 
			
		||||
        case PART_CARAC: return part.filterCaracs(rollData, [current?.tache.system.carac])
 | 
			
		||||
        case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
 | 
			
		||||
      if (current.tache) {
 | 
			
		||||
        switch (part.code) {
 | 
			
		||||
          case PART_CARAC: return part.filterCaracs(rollData, [current?.tache.system.carac])
 | 
			
		||||
          case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return undefined
 | 
			
		||||
 
 | 
			
		||||
@@ -15,10 +15,6 @@ export class RollPartTricher extends RollPart {
 | 
			
		||||
    current.resultat = Misc.inRange(current.resultat == undefined ? -1 : current.resultat, -1, 100)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getAjustements(rollData) {
 | 
			
		||||
    return []
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async _onRender(rollDialog, context, options) {
 | 
			
		||||
    const input = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`)
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,8 @@ export const ROLLDIALOG_SECTION = {
 | 
			
		||||
  CONDITIONS: 'conditions',
 | 
			
		||||
  AJUSTEMENTS: 'ajustements',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
export class RollPart {
 | 
			
		||||
  static settingKey(rollPart, key) { return `roll-part-${rollPart.code}.${key}` }
 | 
			
		||||
 | 
			
		||||
@@ -28,7 +30,8 @@ export class RollPart {
 | 
			
		||||
      rollData.selected[this.code] = {}
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** l'acteur actif du jet */
 | 
			
		||||
  getActor(rollData) { return rollData.active.actor }
 | 
			
		||||
  /** le conteneur de données du RollPart */
 | 
			
		||||
  getRefs(rollData) {
 | 
			
		||||
    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 }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getAjustements(rollData) {
 | 
			
		||||
    return []
 | 
			
		||||
  }
 | 
			
		||||
  getAjustements(rollData) { return [] }
 | 
			
		||||
 | 
			
		||||
  async _onRender(rollDialog, context, options) { }
 | 
			
		||||
 | 
			
		||||
  getHooks() { return [] }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,5 +1,4 @@
 | 
			
		||||
import { DIFF, ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
 | 
			
		||||
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
 | 
			
		||||
import { RollType } from "./roll-type.mjs"
 | 
			
		||||
 | 
			
		||||
export class RollTypeAttaque extends RollType {
 | 
			
		||||
 
 | 
			
		||||
@@ -32,17 +32,17 @@ export class RollTypeCuisine extends RollType {
 | 
			
		||||
    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.active.addCreatedItem(plat)
 | 
			
		||||
      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.active.addDeletedItem(current.ingredient)
 | 
			
		||||
        impacts.addDeleted('Item', current.ingredient)
 | 
			
		||||
        result.messages.push(`Il n'y a plus de ${ingredient.name}`)
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        impacts.active.addItemDelta(current.ingredient, 'system.quantite', -current.proportions)
 | 
			
		||||
        impacts.addDelta('Item', current.ingredient, 'system.quantite', -current.proportions)
 | 
			
		||||
        result.messages.push(`${current.proportions} ${current.ingredient.name} ont été utilisés`)
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
@@ -51,7 +51,7 @@ export class RollTypeCuisine extends RollType {
 | 
			
		||||
  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.active.itemCreates.find(it => it.id = roll.result.plat.id)?.createdId
 | 
			
		||||
      roll.result.plat.id = impacts.findCreatedId('Item', roll.result.plat.id)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,5 @@
 | 
			
		||||
import { RdDItemSigneDraconique } from "../item/signedraconique.js"
 | 
			
		||||
import { RollBasicParts } from "./roll-basic-parts.mjs"
 | 
			
		||||
import { DIFF, ROLL_TYPE_MEDITATION } from "./roll-constants.mjs"
 | 
			
		||||
import { PART_MEDITATION } from "./roll-part-meditation.mjs"
 | 
			
		||||
import { RollType } from "./roll-type.mjs"
 | 
			
		||||
@@ -26,7 +27,7 @@ export class RollTypeMeditation extends RollType {
 | 
			
		||||
    const rolled = rollData.rolled
 | 
			
		||||
    if (meditation && rolled) {
 | 
			
		||||
      if (rolled.isSuccess) {
 | 
			
		||||
        await actor.createEmbeddedDocuments("Item", [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditation, rolled)])
 | 
			
		||||
        await actor.createEmbeddedDocuments('Item', [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditation, rolled)])
 | 
			
		||||
      }
 | 
			
		||||
      if (rolled.isEPart) {
 | 
			
		||||
        await actor.updateEmbeddedDocuments('Item', [{ _id: meditation._id, 'system.malus': meditation.system.malus - 1 }])
 | 
			
		||||
@@ -34,4 +35,9 @@ export class RollTypeMeditation extends RollType {
 | 
			
		||||
      await actor.santeIncDec("fatigue", 2)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async onMonteeTMR(savedRoll, mode){
 | 
			
		||||
    const actor = RollBasicParts.getTokenActor(savedRoll).actor
 | 
			
		||||
    return actor?.displayTMR(mode)
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,4 +1,9 @@
 | 
			
		||||
import { RdDItemCompetence } from "../item-competence.js"
 | 
			
		||||
import { RdDItemSort } from "../item-sort.js"
 | 
			
		||||
import { RdDResolutionTable } from "../rdd-resolution-table.js"
 | 
			
		||||
import { DIFF, ROLL_TYPE_SORT } from "./roll-constants.mjs"
 | 
			
		||||
import { PART_COMP } from "./roll-part-comp.mjs"
 | 
			
		||||
import { PART_SORT } from "./roll-part-sort.mjs"
 | 
			
		||||
import { RollType } from "./roll-type.mjs"
 | 
			
		||||
 | 
			
		||||
export class RollTypeSort extends RollType {
 | 
			
		||||
@@ -11,4 +16,69 @@ export class RollTypeSort extends RollType {
 | 
			
		||||
  onSelect(rollData) {
 | 
			
		||||
    this.setDiffType(rollData, DIFF.AUCUN)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  getResult(rollData, impacts) {
 | 
			
		||||
    const rolled = rollData.rolled
 | 
			
		||||
    const actor = rollData.active.actor
 | 
			
		||||
    const coord = actor.system.reve.tmrpos.coord
 | 
			
		||||
    const reveActuel = parseInt(actor.system.reve.reve.value)
 | 
			
		||||
    const draconic = rollData.current[PART_COMP].comp
 | 
			
		||||
 | 
			
		||||
    const current = rollData.current[PART_SORT]
 | 
			
		||||
    const sort = current.sort
 | 
			
		||||
    const isReserve = current.isReserve
 | 
			
		||||
    const reveSort = current.ptreve
 | 
			
		||||
    const isThanatos = RdDItemCompetence.isThanatos(draconic)
 | 
			
		||||
 | 
			
		||||
    actor.tmrApp?.restoreTMRAfterAction()
 | 
			
		||||
 | 
			
		||||
    current.depenseReve = reveSort
 | 
			
		||||
    if (isThanatos) { // Si Thanatos
 | 
			
		||||
      impacts.addActorUpdate("system.reve.reve.thanatosused", true)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (rolled.isSuccess) { // Réussite du sort !
 | 
			
		||||
      if (rolled.isPart) {
 | 
			
		||||
        current.depenseReve = Math.max(Math.floor(current.depenseReve / 2), 1)
 | 
			
		||||
      }
 | 
			
		||||
      if (isReserve) {
 | 
			
		||||
        current.depenseReve++
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (reveActuel > current.depenseReve) {
 | 
			
		||||
        // Incrémenter/gére le bonus de case
 | 
			
		||||
        impacts.addUpdate('Item', sort, 'system.bonuscase', RdDItemSort.calculBonuscase(sort, coord))
 | 
			
		||||
 | 
			
		||||
        if (isReserve) {
 | 
			
		||||
          impacts.addCreated('Item', RdDItemSort.prepareSortEnReserve(sort, draconic, reveSort, coord))
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
          rollData.closeTMR = true
 | 
			
		||||
          if (sort.system.isrituel) {
 | 
			
		||||
            impacts.addUpdate('Item', sort, 'system.lancements', RdDItemSort.prepareSortAddLancement(sort, reveSort))
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        current.depenseReve = 0;
 | 
			
		||||
        rollData.show.reveInsuffisant = true
 | 
			
		||||
        foundry.utils.mergeObject(rollData.rolled, RdDResolutionTable.getResultat("echec"), { overwrite: true })
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      rollData.closeTMR = true
 | 
			
		||||
      if (rolled.isETotal) { // Echec total !
 | 
			
		||||
        current.depenseReve = Math.min(reveActuel, Math.floor(current.depenseReve * 1.5))
 | 
			
		||||
        // TODO: mise en réserve d'un échec total...
 | 
			
		||||
      } else {
 | 
			
		||||
        current.depenseReve = 0
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    impacts.addActorDelta("system.reve.reve.value", - Math.min(current.depenseReve, reveActuel))
 | 
			
		||||
    
 | 
			
		||||
    if (current.depenseReve >= reveActuel) { // 0 points de reve
 | 
			
		||||
      rollData.show.zeroReve = true
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
@@ -12,7 +12,7 @@ export class RollTypeTache extends RollType {
 | 
			
		||||
  title(rollData) {
 | 
			
		||||
    const current = rollData.current[PART_TACHE]
 | 
			
		||||
    const tache = current?.tache
 | 
			
		||||
    return `travaille à sa tâche: ${tache.name ?? ''}`
 | 
			
		||||
    return tache ? `travaille à sa tâche: ${tache.name}` : `n'a pas de tâches à travailler`
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  onSelect(rollData) {
 | 
			
		||||
 
 | 
			
		||||
@@ -47,6 +47,7 @@ export class RollType {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  setDiffType(rollData, type) {
 | 
			
		||||
    type = rollData.selected[PART_DIFF].type ?? type
 | 
			
		||||
    rollData.current[PART_DIFF].type = type
 | 
			
		||||
    this.setRollDataType(rollData)
 | 
			
		||||
  }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
import { SYSTEM_RDD } from "../constants.js";
 | 
			
		||||
import { RDD_CONFIG, SYSTEM_RDD } from "../constants.js";
 | 
			
		||||
import { Misc } from "../misc.js";
 | 
			
		||||
import { RdDBonus } from "../rdd-bonus.js";
 | 
			
		||||
 | 
			
		||||
@@ -14,14 +14,17 @@ export const STATUSES = {
 | 
			
		||||
  StatusBleeding: 'bleeding',
 | 
			
		||||
  StatusDead: 'dead',
 | 
			
		||||
  StatusDemiReve: 'demi-reve',
 | 
			
		||||
  StatusSurEnc: 'sur-encombrement',
 | 
			
		||||
  StatusForceWeak: 'force insuffisante',
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const forceWeakStatusEffect = { rdd: true, id: STATUSES.StatusForceWeak, name: 'EFFECT.StatusForceWeak', img: 'systems/foundryvtt-reve-de-dragon/assets/actions/weak.svg' };
 | 
			
		||||
const demiReveStatusEffect = { rdd: true, id: STATUSES.StatusDemiReve, name: 'EFFECT.StatusDemiReve', img: 'systems/foundryvtt-reve-de-dragon/assets/actions/sort.svg' };
 | 
			
		||||
export const forceWeakStatusEffect = { rdd: true, id: STATUSES.StatusForceWeak, name: 'EFFECT.StatusForceWeak', img: RDD_CONFIG.icons.forceWeak };
 | 
			
		||||
export const surEncEffect = { rdd: true, id: STATUSES.StatusSurEnc, name: 'EFFECT.StatusSurEnc', img: RDD_CONFIG.icons.surenc };
 | 
			
		||||
export const demiReveStatusEffect = { rdd: true, id: STATUSES.StatusDemiReve, name: 'EFFECT.StatusDemiReve', img: RDD_CONFIG.icons.demiReve };
 | 
			
		||||
 | 
			
		||||
const rddStatusEffects = [
 | 
			
		||||
  { rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', name: 'EFFECT.StatusGrappling', img: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.webp' },
 | 
			
		||||
  { rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', name: 'EFFECT.StatusGrappled', img: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.webp' },
 | 
			
		||||
  { rdd: true, id: STATUSES.StatusGrappling, name: 'EFFECT.StatusGrappling', img: RDD_CONFIG.icons.empoignade },
 | 
			
		||||
  { rdd: true, id: STATUSES.StatusGrappled, tint: '#d5633d', name: 'EFFECT.StatusGrappled', img: RDD_CONFIG.icons.empoignade },
 | 
			
		||||
 | 
			
		||||
  { rdd: true, id: STATUSES.StatusRestrained, name: 'EFFECT.StatusRestrained', img: 'icons/svg/net.svg' },
 | 
			
		||||
  { rdd: true, id: STATUSES.StatusStunned, name: 'EFFECT.StatusStunned', img: 'icons/svg/stoned.svg', "duration.rounds": 1 },
 | 
			
		||||
@@ -34,7 +37,8 @@ const rddStatusEffects = [
 | 
			
		||||
  { rdd: true, id: STATUSES.StatusBleeding, name: 'EFFECT.StatusBleeding', img: 'icons/svg/blood.svg' },
 | 
			
		||||
  { rdd: true, id: STATUSES.StatusDead, name: 'EFFECT.StatusDead', img: 'icons/svg/skull.svg' },
 | 
			
		||||
  demiReveStatusEffect,
 | 
			
		||||
  forceWeakStatusEffect
 | 
			
		||||
  forceWeakStatusEffect,
 | 
			
		||||
  surEncEffect,
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const statusDemiSurprise = new Set([STATUSES.StatusStunned, STATUSES.StatusProne, STATUSES.StatusRestrained, STATUSES.StatusForceWeak])
 | 
			
		||||
@@ -43,8 +47,9 @@ const statusSurpriseTotale = new Set([STATUSES.StatusUnconscious, STATUSES.Statu
 | 
			
		||||
export class StatusEffects extends FormApplication {
 | 
			
		||||
 | 
			
		||||
  static onReady() {
 | 
			
		||||
    const rddEffectIds = rddStatusEffects.map(it => it.id);
 | 
			
		||||
    const rddEffectIds = rddStatusEffects.map(it => it.id)
 | 
			
		||||
    rddStatusEffects.forEach(it => {
 | 
			
		||||
      it.name = game.i18n.localize(it.name)
 | 
			
		||||
      it.statuses = new Set([it.id])
 | 
			
		||||
    })
 | 
			
		||||
    const defaultStatusEffectIds = CONFIG.statusEffects.map(it => it.id);
 | 
			
		||||
@@ -82,8 +87,8 @@ export class StatusEffects extends FormApplication {
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static getActorEffetSurprise(actor, forceRequise) {
 | 
			
		||||
    const effets = actor?.getEffects(StatusEffects.isSurprise, forceRequise) ?? []
 | 
			
		||||
  static getActorEffetSurprise(actor) {
 | 
			
		||||
    const effets = actor?.getEffects(StatusEffects.isSurprise) ?? []
 | 
			
		||||
    return {
 | 
			
		||||
      effets: effets,
 | 
			
		||||
      surprise: effets.length > 0
 | 
			
		||||
@@ -133,7 +138,7 @@ export class StatusEffects extends FormApplication {
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static prepareActiveEffect(effectId) {
 | 
			
		||||
    let status = rddStatusEffects.find(it => it.id == effectId)
 | 
			
		||||
    let status = rddStatusEffects.find(it => it.statuses? it.statuses.has(effectId) : it.id == effectId)
 | 
			
		||||
    if (status) {
 | 
			
		||||
      status = foundry.utils.duplicate(status)
 | 
			
		||||
      status.statuses = new Set([effectId])
 | 
			
		||||
 
 | 
			
		||||
@@ -1,15 +1,25 @@
 | 
			
		||||
 | 
			
		||||
const ACTOR_EMBEDDED_DOCTYPES = ['Item', 'ActiveEffect']
 | 
			
		||||
/**
 | 
			
		||||
 * class designed to store actor modification instructions, to apply them in a single operation, and have the ability to revert these
 | 
			
		||||
 */
 | 
			
		||||
export class ActorImpacts {
 | 
			
		||||
  static $newDocumentImpacts(docType) {
 | 
			
		||||
    return { creates: [], deletes: [], updates: [], docType: docType }
 | 
			
		||||
  }
 | 
			
		||||
  static $checkDocType(docType) {
 | 
			
		||||
    if (!ACTOR_EMBEDDED_DOCTYPES.includes(docType)) {
 | 
			
		||||
      throw `Unsupported document type ${docType}`
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  constructor(actorToken) {
 | 
			
		||||
    this.actorToken = actorToken
 | 
			
		||||
    this.updates = []
 | 
			
		||||
    this.deltas = []
 | 
			
		||||
    this.itemCreates = []
 | 
			
		||||
    this.itemUpdates = []
 | 
			
		||||
    this.itemDeletes = []
 | 
			
		||||
    ACTOR_EMBEDDED_DOCTYPES.forEach(
 | 
			
		||||
      docType => this[docType] = ActorImpacts.$newDocumentImpacts(docType)
 | 
			
		||||
    )
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  addActorUpdate(path, value) {
 | 
			
		||||
@@ -27,46 +37,55 @@ export class ActorImpacts {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  addDeletedItem(item) {
 | 
			
		||||
    this.itemDeletes.push(item)
 | 
			
		||||
  }
 | 
			
		||||
  addCreatedItem(item) {
 | 
			
		||||
    this.itemCreates.push(item)
 | 
			
		||||
  addDeleted(docType, document) {
 | 
			
		||||
    ActorImpacts.$checkDocType(docType)
 | 
			
		||||
    this[docType].deletes.push(document)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  addItemUpdate(item, path, value) {
 | 
			
		||||
    const existing = this.itemUpdates.find(it => it.id == item.id)
 | 
			
		||||
  addCreated(docType, document) {
 | 
			
		||||
    ActorImpacts.$checkDocType(docType)
 | 
			
		||||
    this[docType].creates.push(document)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  addUpdate(docType, document, path, value) {
 | 
			
		||||
    ActorImpacts.$checkDocType(docType)
 | 
			
		||||
    const update = [path, value]
 | 
			
		||||
    const existing = this[docType].updates.find(it => it.id == document.id)
 | 
			
		||||
    if (existing) {
 | 
			
		||||
      existing.updates.push(update)
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      this.itemUpdates.push({ id: item.id, updates: [update], deltas: [] })
 | 
			
		||||
      this[docType].updates.push({ id: document.id, updates: [update], deltas: [] })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  addItemDelta(item, path, value) {
 | 
			
		||||
  addDelta(document, path, value) {
 | 
			
		||||
    ActorImpacts.$checkDocType(document)
 | 
			
		||||
    const intValue = Number.parseInt(value)
 | 
			
		||||
    if (Number.isInteger(intValue) && intValue != 0) {
 | 
			
		||||
      const delta = [path, intValue]
 | 
			
		||||
      const existing = this.itemUpdates.find(it => it.id == item.id)
 | 
			
		||||
      const existing = this[docType].updates.find(it => it.id == document.id)
 | 
			
		||||
      if (existing) {
 | 
			
		||||
        existing.deltas.push(delta)
 | 
			
		||||
      }
 | 
			
		||||
      else {
 | 
			
		||||
        this.itemUpdates.push({ id: item.id, updates: [], deltas: [delta] })
 | 
			
		||||
        this[docType].updates.push({ id: document.id, updates: [], deltas: [delta] })
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      console.error('Cannot use non integer value {} for delta update', value)
 | 
			
		||||
      console.error('Cannot use non-integer value {} for delta update', value)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  reverseImpacts() {
 | 
			
		||||
    const reverse = ActorImpacts.$computeReverts(new ActorImpacts(this.actorToken), this, __ => this.actorToken.actor)
 | 
			
		||||
    reverse.itemCreates = this.itemDeletes.map(it => foundry.utils.duplicate(it))
 | 
			
		||||
    reverse.itemDeletes = this.itemCreates.map(it => { return { id: it.id } })
 | 
			
		||||
    reverse.itemUpdates = this.itemUpdates.map(it => ActorImpacts.$computeReverts({ id: it.id }, it, id => this.$getActorItem(id)))
 | 
			
		||||
    ACTOR_EMBEDDED_DOCTYPES.forEach(
 | 
			
		||||
      docType => {
 | 
			
		||||
        reverse[docType].creates = this[docType].deletes.map(it => foundry.utils.duplicate(it))
 | 
			
		||||
        reverse[docType].deletes = this[docType].creates.map(it => { return { id: it.id } })
 | 
			
		||||
        reverse[docType].updates = this[docType].updates.map(it => ActorImpacts.$computeReverts({ id: it.id }, it, id => this.$getEmbeddedDocument(docType, id)))
 | 
			
		||||
      }
 | 
			
		||||
    )
 | 
			
		||||
    return reverse
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@@ -77,40 +96,44 @@ export class ActorImpacts {
 | 
			
		||||
 | 
			
		||||
  async applyImpacts() {
 | 
			
		||||
    const actor = this.actorToken.actor
 | 
			
		||||
    const isItemsDelete = this.itemDeletes.length > 0
 | 
			
		||||
    const isItemsCreate = this.itemCreates.length > 0
 | 
			
		||||
    const isItemsUpdate = this.itemUpdates.length > 0
 | 
			
		||||
    const isActorUpdate = this.updates.length > 0 || this.deltas.length > 0
 | 
			
		||||
    await Promise.all(ACTOR_EMBEDDED_DOCTYPES.map(async docType => await this.$applyDocumentsImpacts(actor, docType)))
 | 
			
		||||
    const updates = ActorImpacts.$computeUpdates(this, id => actor)
 | 
			
		||||
    await actor.update(updates, { render: true })
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
    if (isItemsDelete) {
 | 
			
		||||
      const deletes = this.itemDeletes.map(it => it.id)
 | 
			
		||||
      await actor.deleteEmbeddedDocuments('Item', deletes, { render: !(isItemsCreate || isItemsUpdate || isActorUpdate) })
 | 
			
		||||
 | 
			
		||||
  async $applyDocumentsImpacts(actor, docType) {
 | 
			
		||||
    if (this[docType].deletes.length > 0) {
 | 
			
		||||
      const deletes = this[docType].deletes.map(it => it.id)
 | 
			
		||||
      await actor.deleteEmbeddedDocuments(docType, deletes, { render: false })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isItemsCreate) {
 | 
			
		||||
      const creates = this.itemCreates
 | 
			
		||||
      const created = await actor.createEmbeddedDocuments('Item', creates, { render: !(isItemsUpdate || isActorUpdate)})
 | 
			
		||||
      for (let i=0; i<creates.length; i++){
 | 
			
		||||
    if (this[docType].creates.length > 0) {
 | 
			
		||||
      const creates = this[docType].creates
 | 
			
		||||
      const created = await actor.createEmbeddedDocuments(docType, creates, { render: false })
 | 
			
		||||
      for (let i = 0; i < creates.length; i++) {
 | 
			
		||||
        creates[i].createdId = created[i].id
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isItemsUpdate) {
 | 
			
		||||
      const updates = this.itemUpdates.map(u => ActorImpacts.$computeUpdates(u, id => this.$getActorItem(id)))
 | 
			
		||||
      await actor.updateEmbeddedDocuments('Item', updates, { render: !isActorUpdate })
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (isActorUpdate) {
 | 
			
		||||
      const updates = ActorImpacts.$computeUpdates(this, id => actor)
 | 
			
		||||
      await actor.update(updates, { render: true })
 | 
			
		||||
    if (this[docType].updates.length > 0) {
 | 
			
		||||
      const updates = this[docType].updates.map(u => ActorImpacts.$computeUpdates(u, id => this.$getEmbeddedDocument(docType, id)))
 | 
			
		||||
      await actor.updateEmbeddedDocuments(docType, updates, { render: false })
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $getActorItem(id) {
 | 
			
		||||
    return this.actorToken.actor.items.get(id)
 | 
			
		||||
  findCreatedId(docType, origId){
 | 
			
		||||
     return this[docType].creates.find(it => it.id = origId)?.createdId
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  $getEmbeddedDocument(docType, id) {
 | 
			
		||||
    return this.actorToken.actor.getEmbeddedDocument(docType, id)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  static $computeUpdates(u, getSource) {
 | 
			
		||||
    if (u.updates.length == 0 && u.deltas.length == 0) {
 | 
			
		||||
      return {}
 | 
			
		||||
    }
 | 
			
		||||
    const source = getSource(u.id)
 | 
			
		||||
    const instruction = { _id: u.id }
 | 
			
		||||
    u.updates.forEach(u => instruction[u[0]] = u[1])
 | 
			
		||||
@@ -124,5 +147,4 @@ export class ActorImpacts {
 | 
			
		||||
    target.deltas = u.deltas.map(d => [d[0], -d[1]])
 | 
			
		||||
    return target
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1408,7 +1408,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!1Nng9d8r6lrPHCaJ.MxFDPQmm1900bWin'
 | 
			
		||||
  - _id: bNUVmIoLEROEIOIm
 | 
			
		||||
    name: Cuir / Métal
 | 
			
		||||
    name: Cuir / métal
 | 
			
		||||
    type: armure
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_metal.webp
 | 
			
		||||
    effects: []
 | 
			
		||||
@@ -1447,7 +1447,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!1Nng9d8r6lrPHCaJ.bNUVmIoLEROEIOIm'
 | 
			
		||||
  - _id: OKZvybZ9jJuX8ZDY
 | 
			
		||||
    name: Cuir Epais
 | 
			
		||||
    name: Cuir épais
 | 
			
		||||
    type: armure
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_epais.webp
 | 
			
		||||
    effects: []
 | 
			
		||||
@@ -1485,7 +1485,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!1Nng9d8r6lrPHCaJ.OKZvybZ9jJuX8ZDY'
 | 
			
		||||
  - _id: sgvPgIF2ars8IeHv
 | 
			
		||||
    name: Cuir Souple
 | 
			
		||||
    name: Cuir souple
 | 
			
		||||
    type: armure
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_souple.webp
 | 
			
		||||
    effects: []
 | 
			
		||||
@@ -1553,7 +1553,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!1Nng9d8r6lrPHCaJ.rZxksRn5Ih4Sj4rN'
 | 
			
		||||
  - _id: oKCl27wSt33w6j7O
 | 
			
		||||
    name: Drap Matelassé
 | 
			
		||||
    name: Drap matelassé
 | 
			
		||||
    type: armure
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/drap_matelasse.webp
 | 
			
		||||
    effects: []
 | 
			
		||||
@@ -1625,7 +1625,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!1Nng9d8r6lrPHCaJ.Kv9Lb28qekqLU1F7'
 | 
			
		||||
  - _id: sFm86jqLy1K6q4Px
 | 
			
		||||
    name: Mailles de Fer
 | 
			
		||||
    name: Mailles de fer
 | 
			
		||||
    type: armure
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/mailles.webp
 | 
			
		||||
    effects: []
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!ryUZTa17LzNv25UY.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!ohmz9Jn4jxD88Kll.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
@@ -2028,7 +2028,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!ohmz9Jn4jxD88Kll.c5wursWW03ckpyqn'
 | 
			
		||||
  - _id: i42zzohNKPYS0kMp
 | 
			
		||||
    name: Drap Matelassé
 | 
			
		||||
    name: Drap matelassé
 | 
			
		||||
    type: armure
 | 
			
		||||
    sort: 6900000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/drap_matelasse.webp
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!JARnWt2MQWDyRwQt.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
@@ -2390,7 +2390,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!JARnWt2MQWDyRwQt.RYIOLj7To0rr9RuH'
 | 
			
		||||
  - _id: bycXvPmShoXAnteu
 | 
			
		||||
    name: Cuir Souple
 | 
			
		||||
    name: Cuir souple
 | 
			
		||||
    type: armure
 | 
			
		||||
    sort: 8100000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_souple.webp
 | 
			
		||||
 
 | 
			
		||||
@@ -1551,7 +1551,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!SJb0c8FDcYdd41rB.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/competence_survie_desert.webp
 | 
			
		||||
@@ -2060,7 +2060,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!SJb0c8FDcYdd41rB.EqKsIbamIeYP3GHz'
 | 
			
		||||
  - _id: tei7L0X6H6kNrQaI
 | 
			
		||||
    name: Cuir Souple
 | 
			
		||||
    name: Cuir souple
 | 
			
		||||
    type: armure
 | 
			
		||||
    sort: 7100000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_souple.webp
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!JQCwAOK64Yijwtch.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
@@ -2297,7 +2297,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!JQCwAOK64Yijwtch.9mOVjXVNdvnf7isr'
 | 
			
		||||
  - _id: ISONFNOaWkW2TaE8
 | 
			
		||||
    name: Cuir / Métal
 | 
			
		||||
    name: Cuir / métal
 | 
			
		||||
    type: armure
 | 
			
		||||
    sort: 8400000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_metal.webp
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!CRRP8ucJpljX6tq8.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!51vL4MhEE0asjgF2.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
@@ -2202,7 +2202,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!51vL4MhEE0asjgF2.EqKsIbamIeYP3GHz'
 | 
			
		||||
  - _id: tei7L0X6H6kNrQaI
 | 
			
		||||
    name: Cuir Souple
 | 
			
		||||
    name: Cuir souple
 | 
			
		||||
    type: armure
 | 
			
		||||
    sort: 7100000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/cuir_souple.webp
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!NX1nAqKKIcQlyGua.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!2bRaEDuwZezKAyEq.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
@@ -2028,7 +2028,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!2bRaEDuwZezKAyEq.c5wursWW03ckpyqn'
 | 
			
		||||
  - _id: cMiKr3BxOauOkMIm
 | 
			
		||||
    name: Mailles de Fer
 | 
			
		||||
    name: Mailles de fer
 | 
			
		||||
    type: armure
 | 
			
		||||
    sort: 6900000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/mailles.webp
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!IeKSXignUpfUTU4m.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
@@ -2028,7 +2028,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!IeKSXignUpfUTU4m.c5wursWW03ckpyqn'
 | 
			
		||||
  - _id: cMiKr3BxOauOkMIm
 | 
			
		||||
    name: Mailles de Fer
 | 
			
		||||
    name: Mailles de fer
 | 
			
		||||
    type: armure
 | 
			
		||||
    sort: 6900000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/armes_armures/mailles.webp
 | 
			
		||||
 
 | 
			
		||||
@@ -1552,7 +1552,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!pSM0ku0RJNLvHSvF.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/competence_survie_desert.webp
 | 
			
		||||
 
 | 
			
		||||
@@ -1552,7 +1552,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!5xPFHgrY5AIP9Mnb.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/competence_survie_desert.webp
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!U9NNcXQBJmsI9Ttk.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
 
 | 
			
		||||
@@ -1551,7 +1551,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!oLDROOdwfctyRusH.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/competence_survie_desert.webp
 | 
			
		||||
 
 | 
			
		||||
@@ -1551,7 +1551,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!2KN3nKGZ36Qkn7Mf.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    img: systems/foundryvtt-reve-de-dragon/icons/competence_survie_desert.webp
 | 
			
		||||
 
 | 
			
		||||
@@ -1605,7 +1605,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!V2WOs8deCYdBT2Jo.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
 
 | 
			
		||||
@@ -1605,7 +1605,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!UNs4RBLYiGbfxd1c.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
 
 | 
			
		||||
@@ -1605,7 +1605,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!jfXs7qaHEWQpIHud.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!awZg7bGbTjEGRMiw.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
 
 | 
			
		||||
@@ -1604,7 +1604,7 @@ items:
 | 
			
		||||
      coreVersion: '12.331'
 | 
			
		||||
    _key: '!actors.items!dMdBctaRRdGJgced.oHnSnCw1RAW5t15S'
 | 
			
		||||
  - _id: vDOAyWc2YnuhNnFF
 | 
			
		||||
    name: Survie en Désert
 | 
			
		||||
    name: Survie en désert
 | 
			
		||||
    type: competence
 | 
			
		||||
    sort: 5400000
 | 
			
		||||
    flags: {}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
name: Survie en Désert
 | 
			
		||||
name: Survie en désert
 | 
			
		||||
type: competence
 | 
			
		||||
img: systems/foundryvtt-reve-de-dragon/icons/competence_survie_desert.webp
 | 
			
		||||
_id: vDOAyWc2YnuhNnFF
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user