forked from public/foundryvtt-reve-de-dragon
		
	Compare commits
	
		
			37 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 6e456ca92c | |||
| 482256c218 | |||
| fa1c4ff221 | |||
| b777271657 | |||
| d06a55b615 | |||
| adfbc11eb8 | |||
| 9dd905134b | |||
| f32b6af7b6 | |||
| 9b8a600e22 | |||
| 25db7e0712 | |||
| 776d4ce9ec | |||
| 1de0806e37 | |||
| 03366fdf26 | |||
| 14f324360d | |||
| d60c9f1b28 | |||
| cf514470fd | |||
| b09b095897 | |||
| d81965155c | |||
| 9fa8a2e6f3 | |||
| da7f87fd45 | |||
| 6aba92900c | |||
| 4939e5564e | |||
| 40be65a94e | |||
| 633638a9ab | |||
| 88a3464eed | |||
| 921e470498 | |||
| 0009876a6d | |||
| 54785f0c3a | |||
| df76c4bd78 | |||
| 5f3c678195 | |||
| 89bbe63340 | |||
| 149990e352 | |||
| 3e355784c7 | |||
| b92055d5dd | |||
| 220f8142f5 | |||
| a8bb00ad0b | |||
| 78e30b5503 | 
							
								
								
									
										59
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										59
									
								
								changelog.md
									
									
									
									
									
								
							| @@ -1,9 +1,59 @@ | |||||||
| # 12.0 | # 12.0 | ||||||
|  | ## 12.0.48 - La chèvre d'Astrobazzarh | ||||||
|  | - le Bandersnatch a une protection de 10 | ||||||
|  | - la consistance chèvre est maintenant possible dans les recettes | ||||||
|  |   alchimiques (et toutes les consistances avec accents) | ||||||
|  | - un échec au lancement d'un sort pour le mettre en réserve brise | ||||||
|  |   la concentration du haut-rêvant | ||||||
|  | - Correction: les réussites particulières fonctionnent avec les caractéristiques dérivées | ||||||
|  |  | ||||||
|  | ## 12.0.47 | ||||||
|  | - Correction sur les mise à jour en cascade - | ||||||
|  | - Correction sur le force rendering après un changement de competence | ||||||
|  |    | ||||||
|  | ## 12.0.46 - Le double demi d'Astrobazzarh | ||||||
|  | - correction des raffraîchissement lors du sommeil qui empêchait de dormir | ||||||
|  |   plusieurs heures | ||||||
|  | - Si la fatigue n'est pas utilisée, les rounds dans les TMR font perdre de l'endurance (au lieu d'en gagner) | ||||||
|  | - les TMRs se ferment correctement quand la fatigue maximale est dépassée | ||||||
|  | - le message de lancement de sort en réserve donne la description du sort | ||||||
|  | - suppression de double-messages lors de la fermeture des TMR | ||||||
|  |  | ||||||
|  | ## 12.0.45 - Les errements d'Astrobazzarh, encore | ||||||
|  |  | ||||||
|  | - La difficulté des méditations n'augmente plus en cas de réussite et d'échec normal | ||||||
|  | - Renommage du Bouton pour révéler/masquer le demi-rêve | ||||||
|  |  | ||||||
|  | ## 12.0.44 - Les errements d'Astrobazzarh, suite | ||||||
|  |  | ||||||
|  | - on peut de nouveau dormir et se réveiller reposé | ||||||
|  | - les possessions utilisent maintenant correctement le rêve actuel | ||||||
|  | - les sorts variables ne causent plus de soucis de voie pour le lancement de sorts | ||||||
|  | - les acteurs ayant un sort avec un coût de rêve entier ne sont plus considérés | ||||||
|  |   comme pouvant avoir un rêve variable | ||||||
|  |  | ||||||
|  | ## 12.0.42 - Les errements d'Astrobazzarh | ||||||
|  |  | ||||||
|  | - Correction de différentes automatisations de combat incorrectes | ||||||
|  | - Correction des jets `@roll[vue/-2]` qui tentaient de chercher une compétence -2 (à cause des armes à 1/2 mains) | ||||||
|  |  | ||||||
|  | ## 12.0.41 - La loupe d'Astrobazzarh | ||||||
|  |  | ||||||
|  | - On peut de nouveau effectuer des tirages cachés | ||||||
|  | - Le stress transformé est bien diminué lorsqu'on met le stress dans une compétence | ||||||
|  |  | ||||||
|  | ## 12.0.40 - Les mains d'Astrobazzarh | ||||||
|  |  | ||||||
|  | - correction des attaques particulières en combat | ||||||
|  | - correction de message sur les min/max liés aux modificateurs de races (s'applique uniquement sur la taille) | ||||||
|  |  | ||||||
| ## 12.0.39 - Les mains d'Astrobazzarh | ## 12.0.39 - Les mains d'Astrobazzarh | ||||||
|  |  | ||||||
| - les armes à 1 ou 2 mains fonctionnent dans les liens de jets de dés | - les armes à 1 ou 2 mains fonctionnent dans les liens de jets de dés | ||||||
| - commande `/jet` pour poster une demande de jet de dés | - commande `/jet` pour poster une demande de jet de dés | ||||||
|  |  | ||||||
| ## 12.0.38 - Les prévisions d'Astrobazzarh | ## 12.0.38 - Les prévisions d'Astrobazzarh | ||||||
|  |  | ||||||
| - Correction de modifications de personnages qui ne s'affichaient pas: | - Correction de modifications de personnages qui ne s'affichaient pas: | ||||||
|   - changements d'endurance/vie/fatigue, transformé, ... |   - changements d'endurance/vie/fatigue, transformé, ... | ||||||
| - Migration des compétences "Ecriture" en "Écriture" dans les tâches, livres, oeuvres et méditations | - Migration des compétences "Ecriture" en "Écriture" dans les tâches, livres, oeuvres et méditations | ||||||
| @@ -13,12 +63,14 @@ | |||||||
|   - utilisation de l'extension hbs pour tous les fichiers handlebars |   - utilisation de l'extension hbs pour tous les fichiers handlebars | ||||||
|  |  | ||||||
| ## 12.0.37 - Les enchantements d'Astrobazzarh | ## 12.0.37 - Les enchantements d'Astrobazzarh | ||||||
|  |  | ||||||
| - les potions ont un état, seules les potions liquides sont enchantables | - les potions ont un état, seules les potions liquides sont enchantables | ||||||
| - les lancements de sorts du jour sont conservés jusqu'à chateau dormant | - les lancements de sorts du jour sont conservés jusqu'à chateau dormant | ||||||
| - lorsqu'un joueur souhaite enchanter une potion, les sorts d'enchantements/purification/permanence doivent avoir été lancés auparavant | - lorsqu'un joueur souhaite enchanter une potion, les sorts d'enchantements/purification/permanence doivent avoir été lancés auparavant | ||||||
| - on peut enchanter des gemmes exactement comme des potions | - on peut enchanter des gemmes exactement comme des potions | ||||||
|  |  | ||||||
| ## 12.0.36 - L'alchimie d'Astrobazzarh | ## 12.0.36 - L'alchimie d'Astrobazzarh | ||||||
|  |  | ||||||
| - Nouveautés | - Nouveautés | ||||||
|   - ajout d'un bouton pour enchanter les potions |   - ajout d'un bouton pour enchanter les potions | ||||||
|   - standardisation des boutons d'actions sur les items |   - standardisation des boutons d'actions sur les items | ||||||
| @@ -33,9 +85,11 @@ | |||||||
|   - Corrections de descriptions pour proposer les jet de dés |   - Corrections de descriptions pour proposer les jet de dés | ||||||
|  |  | ||||||
| ## 12.0.35 - La Solution d'Astrobazzarh | ## 12.0.35 - La Solution d'Astrobazzarh | ||||||
|  |  | ||||||
| - Fix problème d'initialisation des feuilles d'items | - Fix problème d'initialisation des feuilles d'items | ||||||
|  |  | ||||||
| ## 12.0.34 - la tête d'Astrobazzarh | ## 12.0.34 - la tête d'Astrobazzarh | ||||||
|  |  | ||||||
| - support de liens "jets de dés" | - support de liens "jets de dés" | ||||||
|   - on peut ajouter des liens "jet de dés" dans les journaux, descriptions, notes, maladresses, ... |   - on peut ajouter des liens "jet de dés" dans les journaux, descriptions, notes, maladresses, ... | ||||||
|   - avec la syntaxe `@roll[...]` on peut ajouter le lien vers: |   - avec la syntaxe `@roll[...]` on peut ajouter le lien vers: | ||||||
| @@ -50,21 +104,26 @@ | |||||||
| - gestion des blocs secrets dans les descriptions | - gestion des blocs secrets dans les descriptions | ||||||
|  |  | ||||||
| ## 12.0.33 - la vieillesse d'Astrobazzarh | ## 12.0.33 - la vieillesse d'Astrobazzarh | ||||||
|  |  | ||||||
| - retour de l'expérience pour les joueurs | - retour de l'expérience pour les joueurs | ||||||
| - suppression du message "Pas de caractéristique" sur les jets d'odorat-goût | - suppression du message "Pas de caractéristique" sur les jets d'odorat-goût | ||||||
|  |  | ||||||
| ## 12.0.32 - les rêveries d'Astrobazzarh | ## 12.0.32 - les rêveries d'Astrobazzarh | ||||||
|  |  | ||||||
| - Ajout des Items Race pour gérer les ajustements liés aux races | - Ajout des Items Race pour gérer les ajustements liés aux races | ||||||
|  |  | ||||||
| ## 12.0.31 - le mausolée d'Astrobazzarh | ## 12.0.31 - le mausolée d'Astrobazzarh | ||||||
|  |  | ||||||
| - Correction: les automatisation de combat jouer-MJ fonctionnentde nouveau | - Correction: les automatisation de combat jouer-MJ fonctionnentde nouveau | ||||||
|  |  | ||||||
| ## 12.0.30 - le cauchemar d'Astrobazzarh | ## 12.0.30 - le cauchemar d'Astrobazzarh | ||||||
|  |  | ||||||
| - calcul automatique du niveau des entités selon leur rêve | - calcul automatique du niveau des entités selon leur rêve | ||||||
| - la description des créatures venimeuses contient un lien vers leur venin | - la description des créatures venimeuses contient un lien vers leur venin | ||||||
| - Correction: les messages de combats ne marchaient plus (Changement combiné Foundry + rêve de Dragon) | - Correction: les messages de combats ne marchaient plus (Changement combiné Foundry + rêve de Dragon) | ||||||
|  |  | ||||||
| ## 12.0.29 - L'indexation d'Astrobazzarh | ## 12.0.29 - L'indexation d'Astrobazzarh | ||||||
|  |  | ||||||
| - les liens dans la descriptions des sorts pointent vers les sorts du compendium | - les liens dans la descriptions des sorts pointent vers les sorts du compendium | ||||||
| - la description du chrasme contient le lien vers son venin plutôt qu'un tableau | - la description du chrasme contient le lien vers son venin plutôt qu'un tableau | ||||||
|  |  | ||||||
|   | |||||||
| @@ -237,7 +237,11 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | |||||||
|  |  | ||||||
|     this.html.find('.carac-xp-augmenter').click(async event => await this.actor.updateCaracXPAuto(event.currentTarget.name.replace("augmenter.", ""))) |     this.html.find('.carac-xp-augmenter').click(async event => await this.actor.updateCaracXPAuto(event.currentTarget.name.replace("augmenter.", ""))) | ||||||
|     this.html.find('.competence-xp-augmenter').click(async event => await this.actor.updateCompetenceXPAuto(RdDSheetUtility.getItemId(event))) |     this.html.find('.competence-xp-augmenter').click(async event => await this.actor.updateCompetenceXPAuto(RdDSheetUtility.getItemId(event))) | ||||||
|     this.html.find('.competence-stress-augmenter').click(async event => await this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event))) |     this.html.find('.competence-stress-augmenter').click(async event =>{ | ||||||
|  |       await this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event)) | ||||||
|  |       this.render(true) | ||||||
|  |     }  | ||||||
|  |   ) | ||||||
|  |  | ||||||
|     if (this.options.vueDetaillee) { |     if (this.options.vueDetaillee) { | ||||||
|       // On carac change |       // On carac change | ||||||
|   | |||||||
							
								
								
									
										189
									
								
								module/actor.js
									
									
									
									
									
								
							
							
						
						
									
										189
									
								
								module/actor.js
									
									
									
									
									
								
							| @@ -243,7 +243,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|     } |     } | ||||||
|     await this.resetInfoSommeil() |     await this.resetInfoSommeil() | ||||||
|     ChatMessage.create(message); |     ChatMessage.create(message); | ||||||
|     this.sheet.render(true); |     setTimeout(() => this.sheet.render(), 20) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async _recuperationSante(message) { |   async _recuperationSante(message) { | ||||||
| @@ -279,30 +279,34 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async dormirChateauDormant() { |   async dormirChateauDormant() { | ||||||
|     if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !this.system.sommeil || this.system.sommeil.nouveaujour) { |     if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !this.system.sommeil || this.system.sommeil.nouveaujour) { | ||||||
|       const message = { |       await this.$dormirChateauDormant(); | ||||||
|         whisper: ChatUtility.getOwners(this), |       setTimeout(() => this.sheet.render(), 20) | ||||||
|         content: "" |  | ||||||
|       }; |  | ||||||
|  |  | ||||||
|       await this._recuperationSante(message) |  | ||||||
|       await this._recupereMoralChateauDormant(message) |  | ||||||
|       await this._recupereChance() |  | ||||||
|       await this.transformerStress() |  | ||||||
|       await this.retourSeuilDeReve(message) |  | ||||||
|       await this.setBonusPotionSoin(0) |  | ||||||
|       await this.retourSust(message) |  | ||||||
|       await this.$perteReveEnchantementsChateauDormants() |  | ||||||
|       await this.$suppressionLancementsSort() |  | ||||||
|       await RdDCoeur.applyCoeurChateauDormant(this, message) |  | ||||||
|       if (message.content != "") { |  | ||||||
|         message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`; |  | ||||||
|         ChatMessage.create(message); |  | ||||||
|       } |  | ||||||
|       await this.resetInfoSommeil(); |  | ||||||
|       this.sheet.render(true); |  | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   async $dormirChateauDormant() { | ||||||
|  |     const message = { | ||||||
|  |       whisper: ChatUtility.getOwners(this), | ||||||
|  |       content: "" | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     await this._recuperationSante(message); | ||||||
|  |     await this._recupereMoralChateauDormant(message); | ||||||
|  |     await this._recupereChance(); | ||||||
|  |     await this.transformerStress(); | ||||||
|  |     await this.retourSeuilDeReve(message); | ||||||
|  |     await this.setBonusPotionSoin(0); | ||||||
|  |     await this.retourSust(message); | ||||||
|  |     await this.$perteReveEnchantementsChateauDormants(); | ||||||
|  |     await this.$suppressionLancementsSort(); | ||||||
|  |     await RdDCoeur.applyCoeurChateauDormant(this, message); | ||||||
|  |     if (message.content != "") { | ||||||
|  |       message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`; | ||||||
|  |       ChatMessage.create(message); | ||||||
|  |     } | ||||||
|  |     await this.resetInfoSommeil(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|   async resetInfoSommeil() { |   async resetInfoSommeil() { | ||||||
|     await this.update({ |     await this.update({ | ||||||
|       'system.sommeil': { |       'system.sommeil': { | ||||||
| @@ -442,10 +446,9 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|       message.content += 'Vous ne trouvez pas le sommeil'; |       message.content += 'Vous ne trouvez pas le sommeil'; | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       let jetsReve = []; |       let dormi = await this.$dormirDesHeures(message, heures, options); | ||||||
|       let dormi = await this.dormirDesHeures(jetsReve, message, heures, options); |       if (dormi.jetsReve.length > 0) { | ||||||
|       if (jetsReve.length > 0) { |         message.content += `Vous récupérez ${dormi.jetsReve.map(it => it < 0 ? '0 (réveil)' : it).reduce(Misc.joining("+"))} Points de rêve. `; | ||||||
|         message.content += `Vous récupérez ${jetsReve.map(it => it < 0 ? '0 (réveil)' : it).reduce(Misc.joining("+"))} Points de rêve. `; |  | ||||||
|       } |       } | ||||||
|       if (dormi.etat == 'eveil') { |       if (dormi.etat == 'eveil') { | ||||||
|         await this.reveilReveDeDragon(message, dormi.heures); |         await this.reveilReveDeDragon(message, dormi.heures); | ||||||
| @@ -458,11 +461,9 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|       ChatMessage.create(message); |       ChatMessage.create(message); | ||||||
|     } |     } | ||||||
|     if (options.chateauDormant) { |     if (options.chateauDormant) { | ||||||
|       await this.dormirChateauDormant(); |       await this.$dormirChateauDormant(); | ||||||
|     } |  | ||||||
|     else { |  | ||||||
|       this.sheet.render(true); |  | ||||||
|     } |     } | ||||||
|  |     setTimeout(() => this.sheet.render(), 20) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async reveilReveDeDragon(message, heures) { |   async reveilReveDeDragon(message, heures) { | ||||||
| @@ -472,18 +473,18 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async dormirDesHeures(jetsReve, message, heures, options) { |   async $dormirDesHeures(message, heures, options) { | ||||||
|     const dormi = { heures: 0, etat: 'dort' }; |     const dormi = { heures: 0, etat: 'dort', jetsReve: [] }; | ||||||
|     for (; dormi.heures < heures && dormi.etat == 'dort'; dormi.heures++) { |     for (; dormi.heures < heures && dormi.etat == 'dort'; dormi.heures++) { | ||||||
|       await this._recupererEthylisme(message); |       await this.$recupererEthylisme(message); | ||||||
|       if (options.grisReve) { |       if (options.grisReve) { | ||||||
|         await this.recupererFatigue(message); |         await this.$recupererFatigue(message); | ||||||
|       } |       } | ||||||
|       else if (!this.system.sommeil?.insomnie) { |       else if (!this.system.sommeil?.insomnie) { | ||||||
|         await this.recupererFatigue(message); |         await this.$recupererFatigue(message); | ||||||
|         dormi.etat = await this.jetRecuperationReve(jetsReve, message); |         await this.$jetRecuperationReve(dormi, message); | ||||||
|         if (dormi.etat == 'dort' && EffetsDraconiques.isDonDoubleReve(this)) { |         if (dormi.etat == 'dort' && EffetsDraconiques.isDonDoubleReve(this)) { | ||||||
|           dormi.etat = await this.jetRecuperationReve(jetsReve, message); |           dormi.etat = await this.$jetRecuperationReve(dormi, message); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
| @@ -491,35 +492,36 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async jetRecuperationReve(jetsReve, message) { |   async $jetRecuperationReve(dormi, message) { | ||||||
|     if (this.getReveActuel() < this.system.reve.seuil.value) { |     if (this.getReveActuel() < this.system.reve.seuil.value) { | ||||||
|       let reve = await RdDDice.rollTotal("1dr"); |       const reve = await RdDDice.rollTotal("1dr") | ||||||
|       if (reve >= 7) { |       if (reve >= 7) { | ||||||
|         // Rêve de Dragon ! |         // Rêve de Dragon ! | ||||||
|         message.content += `Vous faites un <strong>Rêve de Dragon</strong> de ${reve} Points de rêve qui vous réveille! `; |         message.content += `Vous faites un <strong>Rêve de Dragon</strong> de ${reve} Points de rêve qui vous réveille! `; | ||||||
|         await this.combattreReveDeDragon(reve); |         await this.combattreReveDeDragon(reve); | ||||||
|         jetsReve.push(-1); |         dormi.jetsReve.push(-1); | ||||||
|         return 'eveil'; |         dormi.etat = 'eveil' | ||||||
|  |         return | ||||||
|       } |       } | ||||||
|       else { |       else { | ||||||
|         if (!ReglesOptionnelles.isUsing("recuperation-reve")) { |         if (!ReglesOptionnelles.isUsing("recuperation-reve")) { | ||||||
|           ChatMessage.create({ |           ChatMessage.create({ | ||||||
|             whisper: ChatUtility.getOwners(this), |             whisper: ChatUtility.getOwners(this), | ||||||
|             content: `Pas de récupération de rêve (${reve} points ignorés)` |             content: `Pas de récupération de rêve (${reve} points ignorés)` | ||||||
|           }); |           }) | ||||||
|           jetsReve.push(0); |           dormi.jetsReve.push(0) | ||||||
|         } |         } | ||||||
|         else { |         else { | ||||||
|           await this.reveActuelIncDec(reve); |           await this.reveActuelIncDec(reve) | ||||||
|           jetsReve.push(reve); |           dormi.jetsReve.push(reve) | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     return 'dort'; |     dormi.etat = 'dort' | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async _recupererEthylisme(message) { |   async $recupererEthylisme(message) { | ||||||
|     if (!ReglesOptionnelles.isUsing("recuperation-ethylisme")) { return; } |     if (!ReglesOptionnelles.isUsing("recuperation-ethylisme")) { return; } | ||||||
|     let value = Math.min(Number.parseInt(this.system.compteurs.ethylisme.value) + 1, 1); |     let value = Math.min(Number.parseInt(this.system.compteurs.ethylisme.value) + 1, 1); | ||||||
|     if (value <= 0) { |     if (value <= 0) { | ||||||
| @@ -541,7 +543,6 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|       max = Math.floor(max / 2); |       max = Math.floor(max / 2); | ||||||
|     } |     } | ||||||
|     const manquant = max - this.system.sante.endurance.value; |     const manquant = max - this.system.sante.endurance.value; | ||||||
|  |  | ||||||
|     if (manquant > 0) { |     if (manquant > 0) { | ||||||
|       await this.santeIncDec("endurance", manquant); |       await this.santeIncDec("endurance", manquant); | ||||||
|       message.content += `Vous récuperez ${manquant} points d'endurance. `; |       message.content += `Vous récuperez ${manquant} points d'endurance. `; | ||||||
| @@ -549,15 +550,15 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async recupererFatigue(message) { |   async $recupererFatigue(message) { | ||||||
|     if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { |     if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { | ||||||
|       let fatigue = this.system.sante.fatigue.value; |       let fatigue = this.system.sante.fatigue.value | ||||||
|       const fatigueMin = this.getFatigueMin(); |       const fatigueMin = this.getFatigueMin() | ||||||
|       if (fatigue <= fatigueMin) { |       if (fatigue <= fatigueMin) { | ||||||
|         return; |         return | ||||||
|       } |       } | ||||||
|       fatigue = Math.max(fatigueMin, this._calculRecuperationSegment(fatigue)); |       fatigue = Math.max(fatigueMin, this._calculRecuperationSegment(fatigue)) | ||||||
|       await this.update({ "system.sante.fatigue.value": fatigue }); |       await this.update({ 'system.sante.fatigue.value': fatigue }); | ||||||
|       if (fatigue == 0) { |       if (fatigue == 0) { | ||||||
|         message.content += "Vous êtes complêtement reposé. "; |         message.content += "Vous êtes complêtement reposé. "; | ||||||
|       } |       } | ||||||
| @@ -667,19 +668,23 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|     if (!RdDItemRace.checkRacialMax(this, caracName, to)) { |     if (!RdDItemRace.checkRacialMax(this, caracName, to)) { | ||||||
|       return |       return | ||||||
|     } |     } | ||||||
|  |     let updates = {}; | ||||||
|     if (caracName == LIST_CARAC_PERSONNAGE.reve.code) { |     if (caracName == LIST_CARAC_PERSONNAGE.reve.code) { | ||||||
|       if (to > Misc.toInt(this.system.reve.seuil.value)) { |       if (to > Misc.toInt(this.system.reve.seuil.value)) { | ||||||
|         this.setPointsDeSeuil(to); |         updates[`system.reve.seuil.value`] = to; // SFA : Direct and packed changes | ||||||
|  |         //this.setPointsDeSeuil(to); | ||||||
|       }  |       }  | ||||||
|     } |     } | ||||||
|     if (caracName == LIST_CARAC_PERSONNAGE.chance.code) { |     if (caracName == LIST_CARAC_PERSONNAGE.chance.code) { | ||||||
|       if (to > Misc.toInt(this.system.compteurs.chance.value)) { |       if (to > Misc.toInt(this.system.compteurs.chance.value)) { | ||||||
|         this.setPointsDeChance(to); |         updates[`system.compteurs.chance.value`] = to; // SFA : Direct and packed changes | ||||||
|  |         //this.setPointsDeChance(to); | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     let selectedCarac = this.findCaracByName(caracName); |     let selectedCarac = this.findCaracByName(caracName); | ||||||
|     const from = selectedCarac.value |     const from = selectedCarac.value | ||||||
|     await this.update({ [`system.carac.${caracName}.value`]: to }); |     updates[`system.carac.${caracName}.value`] = to; | ||||||
|  |     await this.update(updates); | ||||||
|     await ExperienceLog.add(this, XP_TOPIC.CARAC, from, to, caracName); |     await ExperienceLog.add(this, XP_TOPIC.CARAC, from, to, caracName); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -736,7 +741,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|       await competence.update({ |       await competence.update({ | ||||||
|         "system.xp": toXp, |         "system.xp": toXp, | ||||||
|         "system.niveau": toNiveau, |         "system.niveau": toNiveau, | ||||||
|       }); |       }, { render: false }) | ||||||
|       await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, competence.name); |       await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, competence.name); | ||||||
|       await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name); |       await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name); | ||||||
|     } |     } | ||||||
| @@ -767,7 +772,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|     await competence.update({ |     await competence.update({ | ||||||
|       "system.xp": newXp, |       "system.xp": newXp, | ||||||
|       "system.niveau": toNiveau, |       "system.niveau": toNiveau, | ||||||
|     }); |     }, { render: false }) | ||||||
|     const toXpStress = Math.max(0, fromXpStress - xpUtilise); |     const toXpStress = Math.max(0, fromXpStress - xpUtilise); | ||||||
|     await this.update({ "system.compteurs.experience.value": toXpStress }); |     await this.update({ "system.compteurs.experience.value": toXpStress }); | ||||||
|  |  | ||||||
| @@ -783,7 +788,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|       const toNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie, competence.getCategories()); |       const toNiveau = compValue ?? RdDItemCompetence.getNiveauBase(competence.system.categorie, competence.getCategories()); | ||||||
|       this.notifyCompetencesTronc(competence, toNiveau); |       this.notifyCompetencesTronc(competence, toNiveau); | ||||||
|       const fromNiveau = competence.system.niveau; |       const fromNiveau = competence.system.niveau; | ||||||
|       await competence.update({ 'system.niveau': toNiveau }); |       await competence.update({ 'system.niveau': toNiveau }, { render: true }) | ||||||
|       await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name, true); |       await ExperienceLog.add(this, XP_TOPIC.NIVEAU, fromNiveau, toNiveau, competence.name, true); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -808,7 +813,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|       if (isNaN(toXp) || typeof (toXp) != 'number') toXp = 0; |       if (isNaN(toXp) || typeof (toXp) != 'number') toXp = 0; | ||||||
|       const fromXp = competence.system.xp; |       const fromXp = competence.system.xp; | ||||||
|       this.checkCompetenceXP(idOrName, toXp); |       this.checkCompetenceXP(idOrName, toXp); | ||||||
|       await competence.update({ 'system.xp': toXp }); |       await competence.update({ 'system.xp': toXp }, { render: false }) | ||||||
|       await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, competence.name, true); |       await ExperienceLog.add(this, XP_TOPIC.XP, fromXp, toXp, competence.name, true); | ||||||
|       if (toXp > fromXp) { |       if (toXp > fromXp) { | ||||||
|         RdDUtility.checkThanatosXP(competence) |         RdDUtility.checkThanatosXP(competence) | ||||||
| @@ -822,7 +827,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|     if (competence) { |     if (competence) { | ||||||
|       if (isNaN(toXpSort) || typeof (toXpSort) != 'number') toXpSort = 0; |       if (isNaN(toXpSort) || typeof (toXpSort) != 'number') toXpSort = 0; | ||||||
|       const fromXpSort = competence.system.xp_sort; |       const fromXpSort = competence.system.xp_sort; | ||||||
|       await competence.update({ 'system.xp_sort': toXpSort }); |       await competence.update({ 'system.xp_sort': toXpSort }, { render: false }) | ||||||
|       await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXpSort, toXpSort, competence.name, true); |       await ExperienceLog.add(this, XP_TOPIC.XPSORT, fromXpSort, toXpSort, competence.name, true); | ||||||
|       if (toXpSort > fromXpSort) { |       if (toXpSort > fromXpSort) { | ||||||
|         RdDUtility.checkThanatosXP(competence) |         RdDUtility.checkThanatosXP(competence) | ||||||
| @@ -834,7 +839,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|   async updateCompetenceArchetype(idOrName, compValue) { |   async updateCompetenceArchetype(idOrName, compValue) { | ||||||
|     let competence = this.getCompetence(idOrName) |     let competence = this.getCompetence(idOrName) | ||||||
|     if (competence) { |     if (competence) { | ||||||
|       await competence.update({ 'system.niveau_archetype': Math.max(compValue ?? 0, 0) }); |       await competence.update({ 'system.niveau_archetype': Math.max(compValue ?? 0, 0) }) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -1047,20 +1052,10 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async deleteRencontreTMRAtPosition() { |  | ||||||
|     const rencontreIds = this.itemTypes[ITEM_TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id) |  | ||||||
|     if (rencontreIds.length > 0) { |  | ||||||
|       await this.deleteEmbeddedDocuments('Item', rencontreIds) |  | ||||||
|     } |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   getRencontreTMREnAttente() { |   getRencontreTMREnAttente() { | ||||||
|     return this.itemTypes[ITEM_TYPES.rencontre].find(this.filterRencontreTMRDemiReve()) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   filterRencontreTMRDemiReve() { |  | ||||||
|     const position = this.getDemiReve() |     const position = this.getDemiReve() | ||||||
|     return it => it.system.coord == position |     return this.itemTypes[ITEM_TYPES.rencontre].find(it => it.system.coord == position) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
| @@ -1560,7 +1555,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|     if (!rollData.rolled.isPart || |     if (!rollData.rolled.isPart || | ||||||
|       rollData.finalLevel >= 0 || |       rollData.finalLevel >= 0 || | ||||||
|       game.settings.get("core", "rollMode") == 'selfroll' || |       game.settings.get("core", "rollMode") == 'selfroll' || | ||||||
| 	  !Misc.hasConnectedGM()) { |       !Misc.hasConnectedGM()) { | ||||||
|       return |       return | ||||||
|     } |     } | ||||||
|     hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM) |     hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM) | ||||||
| @@ -1584,7 +1579,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async _appliquerAppelMoral(rollData) { |   async _appliquerAppelMoral(rollData) { | ||||||
|     if (!rollData.use.moral || game.settings.get("core", "rollMode") == 'selfroll'){ |     if (!rollData.use.moral || game.settings.get("core", "rollMode") == 'selfroll') { | ||||||
|       return |       return | ||||||
|     } |     } | ||||||
|     if (rollData.rolled.isEchec || |     if (rollData.rolled.isEchec || | ||||||
| @@ -1770,7 +1765,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|     if (reveActuel == 0) { // 0 points de reve |     if (reveActuel == 0) { // 0 points de reve | ||||||
|       ChatMessage.create({ content: this.name + " est réduit à 0 Points de Rêve, et tombe endormi !" }); |       ChatMessage.create({ content: this.name + " est réduit à 0 Points de Rêve, et tombe endormi !" }); | ||||||
|     } |     } | ||||||
|     if (!rollData.isSortReserve) { |     if (!rollData.isSortReserve || !rolled.isSuccess) { | ||||||
|       this.tmrApp?.close(); |       this.tmrApp?.close(); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -1800,8 +1795,10 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|     }; |     }; | ||||||
|     RollDataAjustements.calcul(rollData, this); |     RollDataAjustements.calcul(rollData, this); | ||||||
|     await RdDResolutionTable.rollData(rollData); |     await RdDResolutionTable.rollData(rollData); | ||||||
|     this.gererExperience(rollData); |  | ||||||
|     await RdDRollResult.displayRollData(rollData, this) |     await RdDRollResult.displayRollData(rollData, this) | ||||||
|  |  | ||||||
|  |     this.gererExperience(rollData); | ||||||
|  |  | ||||||
|     return rollData.rolled; |     return rollData.rolled; | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -1869,7 +1866,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|         competence: competence, |         competence: competence, | ||||||
|         show: { title: options?.title ?? '' } |         show: { title: options?.title ?? '' } | ||||||
|       }, |       }, | ||||||
| 	  // TODO: |       // TODO: | ||||||
|       callbacks: [{ action: r => this.$onRollCompetence(r, options) }] |       callbacks: [{ action: r => this.$onRollCompetence(r, options) }] | ||||||
|     }); |     }); | ||||||
|   } |   } | ||||||
| @@ -1882,7 +1879,7 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|     compData.system.defaut_carac = tacheData.system.carac; // Patch ! |     compData.system.defaut_carac = tacheData.system.carac; // Patch ! | ||||||
|  |  | ||||||
|     await this.openRollDialog({ |     await this.openRollDialog({ | ||||||
|           name: 'jet-competence', |       name: 'jet-competence', | ||||||
|       label: 'Jet de Tâche ' + tacheData.name, |       label: 'Jet de Tâche ' + tacheData.name, | ||||||
|       template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs', |       template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs', | ||||||
|       rollData: { |       rollData: { | ||||||
| @@ -1945,9 +1942,9 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|     } |     } | ||||||
|  |  | ||||||
|     await this.openRollDialog({ |     await this.openRollDialog({ | ||||||
|           name: `jet-${artData.art}`, |       name: `jet-${artData.art}`, | ||||||
|       label: `${artData.verbe} ${oeuvre.name}`, |       label: `${artData.verbe} ${oeuvre.name}`, | ||||||
|           template: `systems/foundryvtt-reve-de-dragon/templates/dialog-roll-${oeuvre.type}.hbs`, |       template: `systems/foundryvtt-reve-de-dragon/templates/dialog-roll-${oeuvre.type}.hbs`, | ||||||
|       rollData: artData, |       rollData: artData, | ||||||
|       callbacks: [{ action: callbackAction }], |       callbacks: [{ action: callbackAction }], | ||||||
|     }) |     }) | ||||||
| @@ -2116,7 +2113,6 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|         label: "Jet de méditation", |         label: "Jet de méditation", | ||||||
|         callbacks: [ |         callbacks: [ | ||||||
|           this.createCallbackExperience(), |           this.createCallbackExperience(), | ||||||
|           { condition: r => r.rolled.isEPart, action: r => this._meditationEPart(r) }, |  | ||||||
|           { action: r => this._meditationResult(r) } |           { action: r => this._meditationResult(r) } | ||||||
|         ] |         ] | ||||||
|       }); |       }); | ||||||
| @@ -2125,21 +2121,16 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async _meditationResult(meditationRoll) { |   async _meditationResult(meditationRoll) { | ||||||
|     this.santeIncDec("fatigue", 2); |  | ||||||
|  |  | ||||||
|     if (meditationRoll.rolled.isSuccess) { |     if (meditationRoll.rolled.isSuccess) { | ||||||
|       await this.createEmbeddedDocuments("Item", [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditationRoll.meditation, meditationRoll.rolled)]); |       await this.createEmbeddedDocuments("Item", [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditationRoll.meditation, meditationRoll.rolled)]); | ||||||
|     } |     } | ||||||
|  |     if (meditationRoll.rolled.isEPart){ | ||||||
|  |       await this.updateEmbeddedDocuments('Item', [{ _id: meditationRoll.meditation._id, 'system.malus': meditationRoll.meditation.system.malus - 1 }]); | ||||||
|  |     } | ||||||
|  |     await this.santeIncDec("fatigue", 2); | ||||||
|     await RdDRollResult.displayRollData(meditationRoll, this.name, 'chat-resultat-meditation.hbs'); |     await RdDRollResult.displayRollData(meditationRoll, this.name, 'chat-resultat-meditation.hbs'); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |  | ||||||
|   _meditationEPart(meditationRoll) { |  | ||||||
|     this.updateEmbeddedDocuments('Item', [{ _id: meditationRoll.meditation._id, 'system.malus': meditationRoll.meditation.system.malus - 1 }]); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   _getSignesDraconiques(coord) { |   _getSignesDraconiques(coord) { | ||||||
|     const type = TMRUtility.getTMRType(coord); |     const type = TMRUtility.getTMRType(coord); | ||||||
| @@ -2527,7 +2518,6 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|       }) |       }) | ||||||
|     } |     } | ||||||
|     const blessure = this.getItem(blessureId, 'blessure') |     const blessure = this.getItem(blessureId, 'blessure') | ||||||
|     console.log('TODO update blessure', this, blessureId, rollData, rollData.tache); |  | ||||||
|     if (blessure && !blessure.system.premierssoins.done) { |     if (blessure && !blessure.system.premierssoins.done) { | ||||||
|       const tache = rollData.tache; |       const tache = rollData.tache; | ||||||
|       if (rollData.rolled.isETotal) { |       if (rollData.rolled.isETotal) { | ||||||
| @@ -2644,12 +2634,13 @@ export class RdDActor extends RdDBaseActorSang { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async incDecItemUse(itemId, inc = 1) { |   async incDecItemUse(itemId, shouldIncrease = true) { | ||||||
|     const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse'); |     if (shouldIncrease) { | ||||||
|     let itemUse = currentItemUse ? foundry.utils.duplicate(currentItemUse) : {}; |       const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse'); | ||||||
|     itemUse[itemId] = (itemUse[itemId] ?? 0) + inc; |       let itemUse = currentItemUse ? foundry.utils.duplicate(currentItemUse) : {}; | ||||||
|     await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse); |       itemUse[itemId] = (itemUse[itemId] ?? 0) + 1; | ||||||
|     console.log("ITEM USE INC", inc, itemUse); |       await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   | |||||||
| @@ -277,14 +277,9 @@ export class RdDBaseActorReve extends RdDBaseActor { | |||||||
|     return dialog |     return dialog | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   createEmptyCallback() { |   createCallbackExperience() { return { action: r => { } } } | ||||||
|     return { |   createCallbackAppelAuMoral() { return { action: r => { } } } | ||||||
|       condition: r => false, |  | ||||||
|       action: r => { } |  | ||||||
|     }; |  | ||||||
|   } |  | ||||||
|   createCallbackExperience() { return this.createEmptyCallback(); } |  | ||||||
|   createCallbackAppelAuMoral() { return this.createEmptyCallback(); } |  | ||||||
|   async _onCloseRollDialog(html) { } |   async _onCloseRollDialog(html) { } | ||||||
|  |  | ||||||
|   async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) { |   async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) { | ||||||
|   | |||||||
| @@ -39,7 +39,12 @@ export class RdDBaseActorSang extends RdDBaseActorReve { | |||||||
|     return 0; |     return 0; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   getFatigueRestante() { return this.getFatigueMax() - this.getFatigueActuelle() } |   isCumulFatigueCauseSommeil(cumulFatigue){ | ||||||
|  |     return ReglesOptionnelles.isUsing("appliquer-fatigue") | ||||||
|  |     ? (this.getFatigueRestante() <= cumulFatigue) | ||||||
|  |     : (this.getEnduranceActuelle() <= cumulFatigue) | ||||||
|  |   } | ||||||
|  |   getFatigueRestante() {return this.getFatigueMax() - this.getFatigueActuelle() } | ||||||
|   getFatigueMin() { return this.system.sante.endurance.max - this.system.sante.endurance.value } |   getFatigueMin() { return this.system.sante.endurance.max - this.system.sante.endurance.value } | ||||||
|  |  | ||||||
|   malusFatigue() { |   malusFatigue() { | ||||||
|   | |||||||
| @@ -244,16 +244,19 @@ export class RdDBaseActor extends Actor { | |||||||
|   async onUpdateActor(update, options, actorId) { } |   async onUpdateActor(update, options, actorId) { } | ||||||
|   async onDeleteItem(item, options, id) { |   async onDeleteItem(item, options, id) { | ||||||
|     if (item.isInventaire()) { |     if (item.isInventaire()) { | ||||||
|       this._removeItemFromConteneur(item) |       await this._removeItemFromConteneur(item) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   _removeItemFromConteneur(item) { |   async _removeItemFromConteneur(item) { | ||||||
|     this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id)) |     const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id)) | ||||||
|       .forEach(conteneur => { |       .map(conteneur => { | ||||||
|         const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id); |         const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id) | ||||||
|         conteneur.update({ 'system.contenu': nouveauContenu }); |         return { _id: conteneur.id, 'system.contenu': nouveauContenu } | ||||||
|       }); |       }) | ||||||
|  |     if (updates.length > 0) { | ||||||
|  |       await this.updateEmbeddedDocuments('Item', updates) | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async onTimeChanging(oldTimestamp, newTimestamp) { |   async onTimeChanging(oldTimestamp, newTimestamp) { | ||||||
| @@ -744,7 +747,7 @@ export class RdDBaseActor extends Actor { | |||||||
|   async jetDeMoral() { this.actionImpossible("jet de moral") } |   async jetDeMoral() { this.actionImpossible("jet de moral") } | ||||||
|  |  | ||||||
|   async resetItemUse() { } |   async resetItemUse() { } | ||||||
|   async incDecItemUse(itemId, inc = 1) { } |   async incDecItemUse(itemId, shouldIncrease = true) { } | ||||||
|   getItemUse(itemId) { return 0; } |   getItemUse(itemId) { return 0; } | ||||||
|  |  | ||||||
|   async finDeRound(options = { terminer: false }) { } |   async finDeRound(options = { terminer: false }) { } | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import { RdDUtility } from "../../rdd-utility.js"; | |||||||
| import { RdDAlchimie } from "../../rdd-alchimie.js"; | import { RdDAlchimie } from "../../rdd-alchimie.js"; | ||||||
| import { TextRollManager } from "./text-roll-formatter.js"; | import { TextRollManager } from "./text-roll-formatter.js"; | ||||||
|  |  | ||||||
| const REGEX_ALCHIMIE_TERMES = "(?<termes>(\\w|-)+)" | const REGEX_ALCHIMIE_TERMES = "(?<termes>([-A-Za-zÀ-ÖØ-öø-ÿ ])+)" | ||||||
| const REGEX_ALCHIMIE_MANIP = "(?<manip>(couleur|consistance))" | const REGEX_ALCHIMIE_MANIP = "(?<manip>(couleur|consistance))" | ||||||
| const XREGEXP_ROLL_ALCHIMIE = XRegExp("@roll\\[" + REGEX_ALCHIMIE_MANIP + "\\s+" + REGEX_ALCHIMIE_TERMES + "\\]", 'giu') | const XREGEXP_ROLL_ALCHIMIE = XRegExp("@roll\\[" + REGEX_ALCHIMIE_MANIP + "\\s+" + REGEX_ALCHIMIE_TERMES + "\\]", 'giu') | ||||||
| const XREGEXP_ROLL_ALCHIMIE_MANIP = XRegExp("@" + REGEX_ALCHIMIE_MANIP + "\\{" + REGEX_ALCHIMIE_TERMES + "\\}", 'giu') | const XREGEXP_ROLL_ALCHIMIE_MANIP = XRegExp("@" + REGEX_ALCHIMIE_MANIP + "\\{" + REGEX_ALCHIMIE_TERMES + "\\}", 'giu') | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ import { RdDUtility } from "../../rdd-utility.js"; | |||||||
| import { TextRollManager } from "./text-roll-formatter.js"; | import { TextRollManager } from "./text-roll-formatter.js"; | ||||||
|  |  | ||||||
| const REGECP_CARAC = "(?<carac>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)" | const REGECP_CARAC = "(?<carac>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)" | ||||||
| const REGEXP_COMP = "(\\/(?<competence>[A-Za-z0-9À-ÖØ-öø-ÿ -]+))?" | const REGEXP_COMP = "(\\/(?<competence>[A-Za-zÀ-ÖØ-öø-ÿ ]+([1-2]?[A-Za-zÀ-ÖØ-öø-ÿ ]+)?))?" | ||||||
| const REGEXP_DIFF = "(/(?<diff>[\\+\\-]?\\d+(d\\d+)?))?" | const REGEXP_DIFF = "(/(?<diff>[\\+\\-]?\\d+(d\\d+)?))?" | ||||||
| const REGEXP_ROLL_CARAC_COMP = REGECP_CARAC + REGEXP_COMP + REGEXP_DIFF | const REGEXP_ROLL_CARAC_COMP = REGECP_CARAC + REGEXP_COMP + REGEXP_DIFF | ||||||
| const XREGEXP_ROLL_CARAC_COMP = XRegExp("@roll\\[" + REGEXP_ROLL_CARAC_COMP + "\\]", 'giu') | const XREGEXP_ROLL_CARAC_COMP = XRegExp("@roll\\[" + REGEXP_ROLL_CARAC_COMP + "\\]", 'giu') | ||||||
|   | |||||||
| @@ -62,7 +62,6 @@ export class ChatUtility { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|  |  | ||||||
|   static removeMessages(socketData) { |   static removeMessages(socketData) { | ||||||
|     if (Misc.isFirstConnectedGM()) { |     if (Misc.isFirstConnectedGM()) { | ||||||
|       ChatUtility.onRemoveMessages(socketData); |       ChatUtility.onRemoveMessages(socketData); | ||||||
| @@ -97,7 +96,7 @@ export class ChatUtility { | |||||||
|         } |         } | ||||||
|         break |         break | ||||||
|       case "gmroll": |       case "gmroll": | ||||||
|         messageData.whisper = ChatUtility.getOwners(actor) |         messageData.whisper = actor ? ChatUtility.getOwners(actor) : ChatUtility.getUserAndGMs() | ||||||
|         break |         break | ||||||
|       case "selfroll": |       case "selfroll": | ||||||
|         messageData.whisper = [game.user] |         messageData.whisper = [game.user] | ||||||
| @@ -108,7 +107,7 @@ export class ChatUtility { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   static getOwners(document) { |   static getOwners(document) { | ||||||
|     return game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) |     return document ? game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) : [game.user] | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   static getUserAndGMs() { |   static getUserAndGMs() { | ||||||
| @@ -199,7 +198,7 @@ export class ChatUtility { | |||||||
|   static async onCreateChatMessage(chatMessage, options, id) { |   static async onCreateChatMessage(chatMessage, options, id) { | ||||||
|     if (chatMessage.isAuthor) { |     if (chatMessage.isAuthor) { | ||||||
|       await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp()); |       await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp()); | ||||||
|       await chatMessage.update({ content: await RdDTextEditor.enrichHTML(chatMessage.content, undefined, {showLink:false}) }) |       await chatMessage.update({ content: await RdDTextEditor.enrichHTML(chatMessage.content, undefined, { showLink: false }) }) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| } | } | ||||||
|   | |||||||
| @@ -123,10 +123,10 @@ export class RdDItemArme extends Item { | |||||||
|     if (defCategory == 'bouclier') { |     if (defCategory == 'bouclier') { | ||||||
|       return 'norm' |       return 'norm' | ||||||
|     } |     } | ||||||
|     if (armeAttaque.system.competence.toLowerCase().match(/(fléau)/)) { |     if (armeAttaque?.system?.competence?.toLowerCase().match(/(fléau)/)) { | ||||||
|       return '' |       return '' | ||||||
|     } |     } | ||||||
|     if (armeParade.system.tir) { |     if (armeParade.system?.tir) { | ||||||
|       return '' |       return '' | ||||||
|     } |     } | ||||||
|     const attCategory = RdDItemArme.getCategorieParade(armeAttaque) |     const attCategory = RdDItemArme.getCategorieParade(armeAttaque) | ||||||
|   | |||||||
| @@ -56,6 +56,10 @@ export class RdDItemSort extends Item { | |||||||
|     return voies.map(voie => RdDItemCompetence.getVoieDraconic(competencesDraconic, voie)) |     return voies.map(voie => RdDItemCompetence.getVoieDraconic(competencesDraconic, voie)) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   static getBestDraconicSort(competencesDraconic, sort) { | ||||||
|  |     return  RdDItemSort.getDraconicsSort(competencesDraconic, sort).sort(Misc.descending(it => it.system.niveau)).find(it=>true) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   static getOrdreCode(code) { |   static getOrdreCode(code) { | ||||||
|     return (VOIES_DRACONIC.find(it => it.code == code)?.ordre ?? '?') |     return (VOIES_DRACONIC.find(it => it.code == code)?.ordre ?? '?') | ||||||
|   } |   } | ||||||
| @@ -92,7 +96,7 @@ export class RdDItemSort extends Item { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   static isCoutVariable(sort) { |   static isCoutVariable(sort) { | ||||||
|     return sort && (sort.system.ptreve.toLowerCase() == "variable" || sort.system.ptreve.indexOf("+") >= 0); |     return sort && !Number.isInteger(sort.system.ptreve) && (sort.system.ptreve.toLowerCase() == "variable" || sort.system.ptreve.indexOf("+") >= 0); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   | |||||||
| @@ -19,10 +19,12 @@ export class RdDItemRace extends RdDItem { | |||||||
|         return false |         return false | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     const carac = RdDCarac.carac(code) |     if (code == LIST_CARAC_PERSONNAGE.taille.code) { | ||||||
|     if (race.isMax(actor, code, value - 1)) { |       const carac = RdDCarac.carac(code) | ||||||
|       ui.notifications.warn(`${value} est supérieure au maximum de ${carac.label}`) |       if (race.isMax(actor, code, value - 1)) { | ||||||
|       return false |         ui.notifications.warn(`${value} est supérieure au maximum de ${carac.label}`) | ||||||
|  |         return false | ||||||
|  |       } | ||||||
|     } |     } | ||||||
|     return true |     return true | ||||||
|   } |   } | ||||||
| @@ -53,13 +55,18 @@ export class RdDItemRace extends RdDItem { | |||||||
|  |  | ||||||
|   isMax(actor, code, value = undefined) { |   isMax(actor, code, value = undefined) { | ||||||
|     const path = RdDCarac.carac(code)?.path |     const path = RdDCarac.carac(code)?.path | ||||||
|  |     if (path == undefined) { | ||||||
|  |       // cas des caractéristiques dérivées, pas de max | ||||||
|  |       return false | ||||||
|  |     } | ||||||
|     if (value == undefined) { |     if (value == undefined) { | ||||||
|       value = path ? foundry.utils.getProperty(actor, path) : 0 |       value = path ? foundry.utils.getProperty(actor, path) : 0 | ||||||
|     } |     } | ||||||
|     if (code == LIST_CARAC_PERSONNAGE.force.code) { |     if (code == LIST_CARAC_PERSONNAGE.force.code) { | ||||||
|       return value >= this.getForceMax(actor) |       return value >= this.getForceMax(actor) | ||||||
|     } |     } | ||||||
|     const max = foundry.utils.getProperty(this, path) ?? -1 |     const pathMax = path.replace(".value", ".max"); | ||||||
|  |     const max = foundry.utils.getProperty(this, pathMax) ?? -1 | ||||||
|     return (max > 0 && value >= max) |     return (max > 0 && value >= max) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -265,7 +265,7 @@ export class Misc { | |||||||
|     const subset = elements.filter(options.preFilter) |     const subset = elements.filter(options.preFilter) | ||||||
|       .filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value)) |       .filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value)) | ||||||
|       .sort(Misc.ascending(it => options.mapper(it))) |       .sort(Misc.ascending(it => options.mapper(it))) | ||||||
|     if (subset.length == 0) { |     if (subset.length == 0 && options?.onMessage) { | ||||||
|       options.onMessage(`Pas de ${options.description} correspondant à ${value}`); |       options.onMessage(`Pas de ${options.description} correspondant à ${value}`); | ||||||
|     } |     } | ||||||
|     return subset; |     return subset; | ||||||
|   | |||||||
| @@ -743,23 +743,13 @@ export class RdDCombat { | |||||||
|           this.attacker.createCallbackExperience(), |           this.attacker.createCallbackExperience(), | ||||||
|           this.attacker.createCallbackAppelAuMoral(), |           this.attacker.createCallbackAppelAuMoral(), | ||||||
|           { action: r => this.removeChatMessageActionsPasseArme(r.passeArme) }, |           { action: r => this.removeChatMessageActionsPasseArme(r.passeArme) }, | ||||||
|           { action: r => this._increaseItemUse(r, arme) }, |           { action: async r => await this.attacker.incDecItemUse(arme._id, arme && !RdDCombat.isParticuliere(r)) }, | ||||||
|           { action: r => this._onAttaqueNormale(r) }, |           { action: r => this._onAttaque(r) }, | ||||||
|           { action: r => this._onAttaqueParticuliere(r) }, |  | ||||||
|           { action: r => this._onAttaqueEchec(r) }, |  | ||||||
|           { action: r => this._onAttaqueEchecTotal(r) }, |  | ||||||
|         ] |         ] | ||||||
|       }); |       }); | ||||||
|     dialog.render(true); |     dialog.render(true); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   _increaseItemUse(rollData, arme) { |  | ||||||
|     if (!arme || RdDCombat.isParticuliere(rollData)) { |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
|     this.attacker.incDecItemUse(arme._id) |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   _prepareAttaque(competence, arme) { |   _prepareAttaque(competence, arme) { | ||||||
|     let rollData = { |     let rollData = { | ||||||
| @@ -776,7 +766,7 @@ export class RdDCombat { | |||||||
|  |  | ||||||
|     if (this.attacker.isCreatureEntite()) { |     if (this.attacker.isCreatureEntite()) { | ||||||
|       RdDItemCompetenceCreature.setRollDataCreature(rollData); |       RdDItemCompetenceCreature.setRollDataCreature(rollData); | ||||||
|   } |     } | ||||||
|     else if (arme) { |     else if (arme) { | ||||||
|       // Usual competence |       // Usual competence | ||||||
|       rollData.arme = RdDItemArme.armeUneOuDeuxMains(arme, RdDItemCompetence.isArmeUneMain(competence)); |       rollData.arme = RdDItemArme.armeUneOuDeuxMains(arme, RdDItemCompetence.isArmeUneMain(competence)); | ||||||
| @@ -790,11 +780,23 @@ export class RdDCombat { | |||||||
|     return rollData; |     return rollData; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   async _onAttaque(attackerRoll) { | ||||||
|  |     if (RdDCombat.isParticuliere(attackerRoll)) { | ||||||
|  |       return await this._onAttaqueParticuliere(attackerRoll) | ||||||
|  |     } | ||||||
|  |     if (RdDCombat.isReussite(attackerRoll)) { | ||||||
|  |       return await this._onAttaqueNormale(attackerRoll) | ||||||
|  |     } | ||||||
|  |     // if (RdDCombat.isParticuliere(attackerRoll) && attackerRoll.particuliere == undefined) { | ||||||
|  |     //   return | ||||||
|  |     // } | ||||||
|  |     if (RdDCombat.isEchecTotal(attackerRoll)) { | ||||||
|  |       return await this._onAttaqueEchecTotal(attackerRoll) | ||||||
|  |     } | ||||||
|  |     return await this._onAttaqueEchec(attackerRoll) | ||||||
|  |   } | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async _onAttaqueParticuliere(rollData) { |   async _onAttaqueParticuliere(rollData) { | ||||||
|     if (!RdDCombat.isParticuliere(rollData)) { |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
|     const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0; |     const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0; | ||||||
|     // force toujours, sauf empoignade |     // force toujours, sauf empoignade | ||||||
|     // finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum |     // finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum | ||||||
| @@ -832,9 +834,6 @@ export class RdDCombat { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async _onAttaqueNormale(attackerRoll) { |   async _onAttaqueNormale(attackerRoll) { | ||||||
|     if (!RdDCombat.isReussite(attackerRoll) || RdDCombat.isParticuliere(attackerRoll)) { |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
|     console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll); |     console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll); | ||||||
|  |  | ||||||
|     attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite()); |     attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite()); | ||||||
| @@ -849,7 +848,7 @@ export class RdDCombat { | |||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     if (this.target) { |     if (this.defender) { | ||||||
|       await this._sendMessageDefense(attackerRoll, defenderRoll); |       await this._sendMessageDefense(attackerRoll, defenderRoll); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
| @@ -951,9 +950,6 @@ export class RdDCombat { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async _onAttaqueEchecTotal(attackerRoll) { |   async _onAttaqueEchecTotal(attackerRoll) { | ||||||
|     if (!RdDCombat.isEchecTotal(attackerRoll)) { |  | ||||||
|       return |  | ||||||
|     } |  | ||||||
|     const choixEchecTotal = await ChatMessage.create({ |     const choixEchecTotal = await ChatMessage.create({ | ||||||
|       whisper: ChatUtility.getOwners(this.attacker), |       whisper: ChatUtility.getOwners(this.attacker), | ||||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.hbs', { |       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.hbs', { | ||||||
| @@ -980,26 +976,20 @@ export class RdDCombat { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async _onAttaqueEchec(rollData) { |   async _onAttaqueEchec(attackerRoll) { | ||||||
|     if (!RdDCombat.isEchec(rollData)) { |     console.log("RdDCombat.onAttaqueEchec >>>", attackerRoll); | ||||||
|       return |     await RdDRollResult.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.hbs'); | ||||||
|     } |  | ||||||
|     console.log("RdDCombat.onAttaqueEchec >>>", rollData); |  | ||||||
|     await RdDRollResult.displayRollData(rollData, this.attacker, 'chat-resultat-attaque.hbs'); |  | ||||||
|  |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async choixParticuliere(rollData, choix) { |   async choixParticuliere(rollData, choix) { | ||||||
|     console.log("RdDCombat.choixParticuliere >>>", rollData, choix); |     console.log("RdDCombat.choixParticuliere >>>", rollData, choix); | ||||||
|  |  | ||||||
|     if (choix != "rapidite") { |     await this.attacker.incDecItemUse(rollData.arme.id, choix != "rapidite") | ||||||
|       this.attacker.incDecItemUse(rollData.arme.id); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     this.removeChatMessageActionsPasseArme(rollData.passeArme); |     this.removeChatMessageActionsPasseArme(rollData.passeArme); | ||||||
|     rollData.particuliere = choix; |     rollData.particuliere = choix; | ||||||
|     await this._onAttaqueNormale(rollData); |     await this._onAttaqueNormale(rollData) | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
| @@ -1023,10 +1013,8 @@ export class RdDCombat { | |||||||
|           this.defender.createCallbackExperience(), |           this.defender.createCallbackExperience(), | ||||||
|           this.defender.createCallbackAppelAuMoral(), |           this.defender.createCallbackAppelAuMoral(), | ||||||
|           { action: r => this.removeChatMessageActionsPasseArme(r.passeArme) }, |           { action: r => this.removeChatMessageActionsPasseArme(r.passeArme) }, | ||||||
|           { condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(armeParadeId) }, |           { action: async r => await this.defender.incDecItemUse(armeParadeId, !RdDCombat.isParticuliere(r)) }, | ||||||
|           { condition: RdDCombat.isReussite, action: r => this._onParadeNormale(r) }, |           { action: r => this._onParade(r) }, | ||||||
|           { condition: RdDCombat.isParticuliere, action: r => this._onParadeParticuliere(r) }, |  | ||||||
|           { condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) }, |  | ||||||
|         ] |         ] | ||||||
|       }); |       }); | ||||||
|     dialog.render(true); |     dialog.render(true); | ||||||
| @@ -1057,8 +1045,19 @@ export class RdDCombat { | |||||||
|     return defenderRoll; |     return defenderRoll; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |  | ||||||
|  |   async _onParade(defenderRoll) { | ||||||
|  |     if (RdDCombat.isParticuliere(defenderRoll)) { | ||||||
|  |       return await this._onParadeParticuliere(defenderRoll) | ||||||
|  |     } | ||||||
|  |     if (RdDCombat.isReussite(defenderRoll)) { | ||||||
|  |       return await this._onParadeNormale(defenderRoll) | ||||||
|  |     } | ||||||
|  |     await this._onParadeEchec(defenderRoll) | ||||||
|  |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   _onParadeParticuliere(defenderRoll) { |   async _onParadeParticuliere(defenderRoll) { | ||||||
|     console.log("RdDCombat._onParadeParticuliere >>>", defenderRoll); |     console.log("RdDCombat._onParadeParticuliere >>>", defenderRoll); | ||||||
|     if (!defenderRoll.attackerRoll.isPart) { |     if (!defenderRoll.attackerRoll.isPart) { | ||||||
|       // TODO: attaquant doit jouer résistance et peut être désarmé p132 |       // TODO: attaquant doit jouer résistance et peut être désarmé p132 | ||||||
| @@ -1067,7 +1066,6 @@ export class RdDCombat { | |||||||
|         this.defender) |         this.defender) | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async _onParadeNormale(defenderRoll) { |   async _onParadeNormale(defenderRoll) { | ||||||
|     console.log("RdDCombat._onParadeNormale >>>", defenderRoll); |     console.log("RdDCombat._onParadeNormale >>>", defenderRoll); | ||||||
| @@ -1106,11 +1104,9 @@ export class RdDCombat { | |||||||
|         callbacks: [ |         callbacks: [ | ||||||
|           this.defender.createCallbackExperience(), |           this.defender.createCallbackExperience(), | ||||||
|           this.defender.createCallbackAppelAuMoral(), |           this.defender.createCallbackAppelAuMoral(), | ||||||
|           { condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(esquive._id) }, |           { action: async r => await this.defender.incDecItemUse(esquive._id, !RdDCombat.isParticuliere(r)) }, | ||||||
|           { action: r => this.removeChatMessageActionsPasseArme(r.passeArme) }, |           { action: r => this.removeChatMessageActionsPasseArme(r.passeArme) }, | ||||||
|           { condition: RdDCombat.isReussite, action: r => this._onEsquiveNormale(r) }, |           { action: r => this._onEsquive(r) }, | ||||||
|           { condition: RdDCombat.isParticuliere, action: r => this._onEsquiveParticuliere(r) }, |  | ||||||
|           { condition: RdDCombat.isEchec, action: r => this._onEsquiveEchec(r) }, |  | ||||||
|         ] |         ] | ||||||
|       }); |       }); | ||||||
|     dialog.render(true); |     dialog.render(true); | ||||||
| @@ -1138,9 +1134,18 @@ export class RdDCombat { | |||||||
|     return rollData; |     return rollData; | ||||||
|   } |   } | ||||||
|  |  | ||||||
|  |   async _onEsquive(defenderRoll) { | ||||||
|  |     if (RdDCombat.isParticuliere(defenderRoll)) { | ||||||
|  |       return await this._onEsquiveParticuliere(defenderRoll) | ||||||
|  |     } | ||||||
|  |     if (RdDCombat.isReussite(defenderRoll)) { | ||||||
|  |       return await this._onEsquiveNormale(defenderRoll) | ||||||
|  |     } | ||||||
|  |     return await this._onEsquiveEchec(defenderRoll) | ||||||
|  |   } | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   _onEsquiveParticuliere(rollData) { |   async _onEsquiveParticuliere(defenderRoll) { | ||||||
|     console.log("RdDCombat._onEsquiveParticuliere >>>", rollData); |     console.log("RdDCombat._onEsquiveParticuliere >>>", defenderRoll); | ||||||
|     ChatUtility.createChatWithRollMode( |     ChatUtility.createChatWithRollMode( | ||||||
|       { content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" }, |       { content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" }, | ||||||
|       this.defender); |       this.defender); | ||||||
|   | |||||||
| @@ -104,8 +104,8 @@ export class RdDPossession { | |||||||
|       rollData.selectedCarac = carac.reve |       rollData.selectedCarac = carac.reve | ||||||
|     } |     } | ||||||
|     else { |     else { | ||||||
|       rollData.selectedCarac = rollingActor.system.carac.reve |  | ||||||
|       rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } } |       rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } } | ||||||
|  |       rollData.selectedCarac = rollData.forceCarac['reve-actuel'] | ||||||
|       rollData.competence.system.defaut_carac = 'reve-actuel' |       rollData.competence.system.defaut_carac = 'reve-actuel' | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|   | |||||||
| @@ -1,4 +1,3 @@ | |||||||
| import { ChatUtility } from "./chat-utility.js"; |  | ||||||
| import { Misc } from "./misc.js"; | import { Misc } from "./misc.js"; | ||||||
| import { RdDDice } from "./rdd-dice.js"; | import { RdDDice } from "./rdd-dice.js"; | ||||||
| import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; | import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; | ||||||
|   | |||||||
| @@ -279,7 +279,7 @@ export class RdDRoll extends Dialog { | |||||||
|  |  | ||||||
|   async setSelectedSort(sort) { |   async setSelectedSort(sort) { | ||||||
|     this.rollData.selectedSort = sort; // Update the selectedCarac |     this.rollData.selectedSort = sort; // Update the selectedCarac | ||||||
|     this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.system.draconic); |     this.rollData.competence = RdDItemSort.getBestDraconicSort(this.rollData.draconicList, sort) | ||||||
|     this.rollData.bonus = RdDItemSort.getCaseBonus(sort, this.rollData.tmr.coord); |     this.rollData.bonus = RdDItemSort.getCaseBonus(sort, this.rollData.tmr.coord); | ||||||
|     this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7); |     this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7); | ||||||
|     RdDItemSort.setCoutReveReel(sort); |     RdDItemSort.setCoutReveReel(sort); | ||||||
|   | |||||||
| @@ -15,7 +15,6 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; | |||||||
| import { RdDDice } from "./rdd-dice.js"; | import { RdDDice } from "./rdd-dice.js"; | ||||||
| import { STATUSES } from "./settings/status-effects.js"; | import { STATUSES } from "./settings/status-effects.js"; | ||||||
| import { RdDRencontre } from "./item/rencontre.js"; | import { RdDRencontre } from "./item/rencontre.js"; | ||||||
| import { RdDTimestamp } from "./time/rdd-timestamp.js"; |  | ||||||
| import { ITEM_TYPES } from "./constants.js"; | import { ITEM_TYPES } from "./constants.js"; | ||||||
| import { Misc } from "./misc.js"; | import { Misc } from "./misc.js"; | ||||||
|  |  | ||||||
| @@ -83,7 +82,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|     this.subdialog = undefined |     this.subdialog = undefined | ||||||
|     this.displaySize = undefined |     this.displaySize = undefined | ||||||
|     if (!this.viewOnly && !game.user.isGM) { |     if (!this.viewOnly && !game.user.isGM) { | ||||||
|       this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); |       this.$tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); | ||||||
|     } |     } | ||||||
|     this.callbacksOnAnimate = []; |     this.callbacksOnAnimate = []; | ||||||
|     const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def); |     const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def); | ||||||
| @@ -139,7 +138,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|     this.cumulFatigue += this.fatigueParCase; |     this.cumulFatigue += this.fatigueParCase; | ||||||
|  |  | ||||||
|     // Le reste... |     // Le reste... | ||||||
|     this.updateValuesDisplay(); |     this.$updateValuesDisplay(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   lancerUnSort() { |   lancerUnSort() { | ||||||
| @@ -190,7 +189,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|   forceTMRContinueAction() { |   forceTMRContinueAction() { | ||||||
|     ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR'); |     ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR'); | ||||||
|     this.bringSubDialogToTop(); |     this.bringSubDialogToTop(); | ||||||
|     return; |     return false | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   setTMRPendingAction(dialog) { |   setTMRPendingAction(dialog) { | ||||||
| @@ -297,7 +296,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|     const coordOrig = this._getCoordActor(); |     const coordOrig = this._getCoordActor(); | ||||||
|     const coordTarget = TMRUtility.deplacement(coordOrig, move); |     const coordTarget = TMRUtility.deplacement(coordOrig, move); | ||||||
|     await this._deplacerDemiReve(coordTarget, 'normal'); |     await this._deplacerDemiReve(coordTarget, 'normal'); | ||||||
|     this.checkQuitterTMR(); |     await this.$checkQuitterTMR(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   calculCoutMonteeTMR() { |   calculCoutMonteeTMR() { | ||||||
| @@ -305,7 +304,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async updateValuesDisplay() { |   async $updateValuesDisplay() { | ||||||
|     if (this.viewOnly || !this.rendered) { |     if (this.viewOnly || !this.rendered) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
| @@ -336,22 +335,30 @@ export class RdDTMRDialog extends Dialog { | |||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async close() { |   async close() { | ||||||
|  |     await this.$forceClose(this.actor.name + " a quitté les terres médianes") | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   async $forceClose(message) { | ||||||
|     if (this.subdialog) { |     if (this.subdialog) { | ||||||
|       return this.forceTMRContinueAction() |       this.forceTMRContinueAction() | ||||||
|  |       return false | ||||||
|     } |     } | ||||||
|     this.descenteTMR = true; |     this.descenteTMR = true; | ||||||
|     if (this.actor.tmrApp) { |     if (this.actor.tmrApp) { | ||||||
|       this.actor.tmrApp = undefined; // Cleanup reference |       this.actor.tmrApp = undefined; // Cleanup reference | ||||||
|       if (!this.viewOnly) { |       if (!this.viewOnly) { | ||||||
|         await this.actor.setEffect(STATUSES.StatusDemiReve, false) |         await this.actor.setEffect(STATUSES.StatusDemiReve, false); | ||||||
|         this._tellToGM(this.actor.name + " a quitté les terres médianes"); |         this.$tellToUserAndGM(message) | ||||||
|       } |       } | ||||||
|       await this.actor.santeIncDec((ReglesOptionnelles.isUsing("appliquer-fatigue") ? "fatigue" : "endurance"), |       const appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue"); | ||||||
|         this.cumulFatigue) |       await this.actor.santeIncDec( | ||||||
|  |         appliquerFatigue ? "fatigue" : "endurance", | ||||||
|  |         (appliquerFatigue ? 1 : -1) * this.cumulFatigue); | ||||||
|     } |     } | ||||||
|     await super.close(); |     this.pixiTMR.close(); | ||||||
|     this.pixiTMR.close() |  | ||||||
|     this.pixiTMR = undefined |     this.pixiTMR = undefined | ||||||
|  |     await super.close(); | ||||||
|  |     return true | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
| @@ -363,48 +370,53 @@ export class RdDTMRDialog extends Dialog { | |||||||
|     } |     } | ||||||
|     switch (action) { |     switch (action) { | ||||||
|       case 'derober': |       case 'derober': | ||||||
|         await this.derober(); |         await this.$derober() | ||||||
|         this.restoreTMRAfterAction(); |         this.restoreTMRAfterAction() | ||||||
|         return; |         return | ||||||
|       case 'refouler': |       case 'refouler': | ||||||
|         await this.refouler(); |         await this.$refouler() | ||||||
|         break; |         break | ||||||
|       case 'maitriser': |       case 'maitriser': | ||||||
|         await this.maitriserRencontre(); |         await this.$maitriserRencontre() | ||||||
|         break; |         break | ||||||
|       case 'ignorer': |       case 'ignorer': | ||||||
|         await this.ignorerRencontre(); |         await this.$ignorerRencontre() | ||||||
|         break; |         break | ||||||
|     } |     } | ||||||
|     await this.postRencontre(tmr); |     await this.postRencontre(tmr); | ||||||
|     this.restoreTMRAfterAction(); |     this.restoreTMRAfterAction(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   async derober() { |   async $derober() { | ||||||
|     console.log("-> derober", this.currentRencontre); |     if (this.currentRencontre) { | ||||||
|     await this.actor.addTMRRencontre(this.currentRencontre); |       console.log("-> derober", this.currentRencontre); | ||||||
|     this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR."); |       await this.actor.addTMRRencontre(this.currentRencontre); | ||||||
|     this.close(); |       this.$forceClose(`${this.actor.name} s'est dérobé face à la rencontre ${this.currentRencontre.name}, et quitte les TMR.`) | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async refouler() { |   async $refouler() { | ||||||
|     console.log("-> refouler", this.currentRencontre); |     if (this.currentRencontre) { | ||||||
|     await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`); |       console.log("-> refouler", this.currentRencontre); | ||||||
|     await this.actor.deleteRencontreTMRAtPosition() |       await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`); | ||||||
|     this.updateTokens(); |       await this.$deleteRencontreTMRAtPosition() | ||||||
|     this.updateValuesDisplay(); |       this.updateTokens(); | ||||||
|     this.nettoyerRencontre(); |       this.$updateValuesDisplay(); | ||||||
|  |       this.$nettoyerRencontre(); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async ignorerRencontre() { |   async $ignorerRencontre() { | ||||||
|     console.log("-> ignorer", this.currentRencontre); |     if (this.currentRencontre) { | ||||||
|     this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name); |       console.log("-> ignorer", this.currentRencontre); | ||||||
|     await this.actor.deleteRencontreTMRAtPosition() |       this.$tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name); | ||||||
|     this.updateTokens(); |       await this.$deleteRencontreTMRAtPosition() | ||||||
|     this.updateValuesDisplay(); |       this.updateTokens(); | ||||||
|     this.nettoyerRencontre(); |       this.$updateValuesDisplay(); | ||||||
|  |       this.$nettoyerRencontre(); | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
| @@ -421,41 +433,29 @@ export class RdDTMRDialog extends Dialog { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   checkQuitterTMR() { |   async $checkQuitterTMR() { | ||||||
|     if (this.actor.isDead()) { |     const reason = this.actor.isDead() | ||||||
|       this._tellToGM("Vous êtes mort : vous quittez les Terres médianes !"); |       ? "est mort" | ||||||
|       this.close(); |       : this.actor.isCumulFatigueCauseSommeil(this.cumulFatigue) | ||||||
|       return true; |         ? "s'écroule de fatigue" | ||||||
|  |         : (this.actor.getReveActuel() == 0) | ||||||
|  |           ? "tombe à 0 Points de Rêve" | ||||||
|  |           : undefined | ||||||
|  |     if (reason) { | ||||||
|  |       if (!this.actor.isDead()) { | ||||||
|  |         await this.$refouler() | ||||||
|  |       } | ||||||
|  |       this.$forceClose(`${this.actor.name} ${reason} et quitte les Terres médianes !`) | ||||||
|  |       return true | ||||||
|     } |     } | ||||||
|  |     return false | ||||||
|     if (ReglesOptionnelles.isUsing("appliquer-fatigue") |  | ||||||
|       ? (this.actor.getFatigueRestante() <= this.cumulFatigue) |  | ||||||
|       : (this.actor.getEnduranceActuelle() <= this.cumulFatigue) |  | ||||||
|     ) { |  | ||||||
|       this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !"); |  | ||||||
|       this.quitterLesTMRInconscient(); |  | ||||||
|       return true; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (this.actor.getReveActuel() == 0) { |  | ||||||
|       this._tellToGM("Vos Points de Rêve sont à 0 : vous quittez les Terres médianes !"); |  | ||||||
|       this.quitterLesTMRInconscient(); |  | ||||||
|       return true; |  | ||||||
|     } |  | ||||||
|     return false; |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async quitterLesTMRInconscient() { |   async $maitriserRencontre() { | ||||||
|     await this.refouler(); |  | ||||||
|     this.close(); |  | ||||||
|   } |  | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |  | ||||||
|   async maitriserRencontre() { |  | ||||||
|     console.log("-> maitriser", this.currentRencontre); |     console.log("-> maitriser", this.currentRencontre); | ||||||
|  |  | ||||||
|     await this.actor.deleteRencontreTMRAtPosition() |     await this.$deleteRencontreTMRAtPosition(); | ||||||
|     this.updateTokens(); |     this.updateTokens(); | ||||||
|  |  | ||||||
|     let rencontreData = { |     let rencontreData = { | ||||||
| @@ -470,11 +470,21 @@ export class RdDTMRDialog extends Dialog { | |||||||
|       tmr: TMRUtility.getTMR(this._getCoordActor()) |       tmr: TMRUtility.getTMR(this._getCoordActor()) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     await this._tentativeMaitrise(rencontreData); |     await this.$tentativeMaitrise(rencontreData); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   async $deleteRencontreTMRAtPosition() { | ||||||
|  |     const position = this.actor.getDemiReve() | ||||||
|  |     const rencontreIds = this.actor.itemTypes[ITEM_TYPES.rencontre] | ||||||
|  |       .filter(it => it.system.coord == position) | ||||||
|  |       .map(it => it.id) | ||||||
|  |     if (rencontreIds.length > 0) { | ||||||
|  |       await this.actor.deleteEmbeddedDocuments('Item', rencontreIds) | ||||||
|  |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async _tentativeMaitrise(rencData) { |   async $tentativeMaitrise(rencData) { | ||||||
|     this.rencontreState = 'normal'; |     this.rencontreState = 'normal'; | ||||||
|  |  | ||||||
|     rencData.reve = this.actor.getReveActuel(); |     rencData.reve = this.actor.getReveActuel(); | ||||||
| @@ -483,7 +493,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|     RollDataAjustements.calcul(rencData, this.actor); |     RollDataAjustements.calcul(rencData, this.actor); | ||||||
|  |  | ||||||
|     rencData.rolled = rencData.presentCite |     rencData.rolled = rencData.presentCite | ||||||
|       ? this._rollPresentCite(rencData) |       ? this.$rollPresentCite(rencData) | ||||||
|       : await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements)); |       : await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements)); | ||||||
|  |  | ||||||
|     const result = rencData.rolled.isSuccess |     const result = rencData.rolled.isSuccess | ||||||
| @@ -493,38 +503,41 @@ export class RdDTMRDialog extends Dialog { | |||||||
|     await RdDRencontre.appliquer(result.effets, this, rencData); |     await RdDRencontre.appliquer(result.effets, this, rencData); | ||||||
|  |  | ||||||
|     rencData.poesie = { extrait: result.poesie, reference: result.reference }; |     rencData.poesie = { extrait: result.poesie, reference: result.reference }; | ||||||
|     rencData.message = this.formatMessageRencontre(rencData, result.message); |     rencData.message = this.$formatMessageRencontre(rencData, result.message); | ||||||
|  |  | ||||||
|     ChatMessage.create({ |     ChatMessage.create({ | ||||||
|       whisper: ChatUtility.getOwners(this.actor), |       whisper: ChatUtility.getOwners(this.actor), | ||||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.hbs`, rencData) |       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.hbs`, rencData) | ||||||
|     }); |     }); | ||||||
|  |  | ||||||
|     this.updateValuesDisplay(); |     this.$updateValuesDisplay(); | ||||||
|     if (this.checkQuitterTMR()) { |     if (await this.$checkQuitterTMR()) { | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     if (this.rencontreState == 'persistant') { |     if (this.rencontreState == 'persistant') { | ||||||
|       this._nouvelleTentativeMaitrise(rencData); |       this.$nouvelleTentativeMaitrise(rencData); | ||||||
|     } |     } | ||||||
|     else if (!this.isRencontreDeplacement()) { |     else if (!this.isRencontreDeplacement()) { | ||||||
|       this.nettoyerRencontre(); |       this.$nettoyerRencontre(); | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   _nouvelleTentativeMaitrise(rencData) { |   $nouvelleTentativeMaitrise(rencData) { | ||||||
|     setTimeout(() => { |     setTimeout(() => { | ||||||
|       // TODO: remplacer par une boucle while(this.currentRencontre) ? |       /** | ||||||
|  |        * TODO: remplacer par une boucle while(this.currentRencontre) ? | ||||||
|  |        * ajouter un moyen d'attendre la saisie de l'utilisateur (jet obligatoire)? | ||||||
|  |        */ | ||||||
|       rencData.nbRounds++; |       rencData.nbRounds++; | ||||||
|       if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { |       if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { | ||||||
|         this.cumulFatigue += this.fatigueParCase; |         this.cumulFatigue += this.fatigueParCase; | ||||||
|       } |       } | ||||||
|       this._tentativeMaitrise(rencData); |       this.$tentativeMaitrise(rencData); | ||||||
|       this._deleteTmrMessages(rencData.actor, rencData.nbRounds); |       this.$deleteTmrMessages(rencData.actor, rencData.nbRounds); | ||||||
|     }, 2000); |     }, 2000); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   formatMessageRencontre(rencData, template) { |   $formatMessageRencontre(rencData, template) { | ||||||
|     let messageDuree = '' |     let messageDuree = '' | ||||||
|     if (rencData.nbRounds > 1) { |     if (rencData.nbRounds > 1) { | ||||||
|       if (rencData.rolled.isSuccess) { |       if (rencData.rolled.isSuccess) { | ||||||
| @@ -543,7 +556,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   _rollPresentCite(rencData) { |   $rollPresentCite(rencData) { | ||||||
|     let rolled = RdDResolutionTable.computeChances(rencData.reve, 0); |     let rolled = RdDResolutionTable.computeChances(rencData.reve, 0); | ||||||
|     foundry.utils.mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score }); |     foundry.utils.mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score }); | ||||||
|     RdDResolutionTable.succesRequis(rolled); |     RdDResolutionTable.succesRequis(rolled); | ||||||
| @@ -551,7 +564,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   _deleteTmrMessages(actor, nbRounds = -1) { |   $deleteTmrMessages(actor, nbRounds = -1) { | ||||||
|     setTimeout(() => { |     setTimeout(() => { | ||||||
|       if (nbRounds < 0) { |       if (nbRounds < 0) { | ||||||
|         ChatUtility.removeChatMessageContaining(`<h4 data-categorie="tmr" data-actor-id="${actor._id}"`); |         ChatUtility.removeChatMessageContaining(`<h4 data-categorie="tmr" data-actor-id="${actor._id}"`); | ||||||
| @@ -570,7 +583,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   _tellToGM(message) { |   $tellToGM(message) { | ||||||
|     ChatMessage.create({ |     ChatMessage.create({ | ||||||
|       user: game.user.id, |       user: game.user.id, | ||||||
|       content: message, |       content: message, | ||||||
| @@ -579,7 +592,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   _tellToUserAndGM(message) { |   $tellToUserAndGM(message) { | ||||||
|     ChatMessage.create({ |     ChatMessage.create({ | ||||||
|       user: game.user.id, |       user: game.user.id, | ||||||
|       content: message, |       content: message, | ||||||
| @@ -601,7 +614,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|     if (this.currentRencontre) { |     if (this.currentRencontre) { | ||||||
|       if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)) { |       if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)) { | ||||||
|         // rencontre en attente suite à dérobade |         // rencontre en attente suite à dérobade | ||||||
|         await this.maitriserRencontre(); |         await this.$maitriserRencontre(); | ||||||
|       } |       } | ||||||
|       else { |       else { | ||||||
|         const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr); |         const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr); | ||||||
| @@ -648,7 +661,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|       tmr: tmr, |       tmr: tmr, | ||||||
|       presentCite: presentCite |       presentCite: presentCite | ||||||
|     }; |     }; | ||||||
|     await this._tentativeMaitrise(rencontreData); |     await this.$tentativeMaitrise(rencontreData); | ||||||
|     this.postRencontre(tmr); |     this.postRencontre(tmr); | ||||||
|   } |   } | ||||||
|  |  | ||||||
| @@ -727,7 +740,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData) |       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData) | ||||||
|     }); |     }); | ||||||
|     if (rollData.rolled.isEchec) { |     if (rollData.rolled.isEchec) { | ||||||
|       await this.close(); |       await this.$forceClose(`n'a pas maîtrisé la case ${rollData.tmr.label} et quitte les terres médianes`) | ||||||
|     } |     } | ||||||
|     await this.souffleSiEchecTotal(rollData); |     await this.souffleSiEchecTotal(rollData); | ||||||
|   } |   } | ||||||
| @@ -782,7 +795,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|         onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), |         onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), | ||||||
|         onConqueteEchec: r => { |         onConqueteEchec: r => { | ||||||
|           this.souffleSiEchecTotal(rollData); |           this.souffleSiEchecTotal(rollData); | ||||||
|           this.close() |           this.$forceClose(`${this.actor.name} n'a pas maîtrisé la ${tmr.label}, et quitte les TMR.`) | ||||||
|         }, |         }, | ||||||
|         canClose: false |         canClose: false | ||||||
|       }); |       }); | ||||||
| @@ -797,7 +810,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|         onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), |         onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), | ||||||
|         onConqueteEchec: r => { |         onConqueteEchec: r => { | ||||||
|           this.souffleSiEchecTotal(rollData); |           this.souffleSiEchecTotal(rollData); | ||||||
|           this.close() |           this.$forceClose(`${this.actor.name} n'a pas purifié la ${tmr.label}, et quitte les TMR.`) | ||||||
|         }, |         }, | ||||||
|         canClose: false |         canClose: false | ||||||
|       }); |       }); | ||||||
| @@ -811,7 +824,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|         difficulte: -7, |         difficulte: -7, | ||||||
|         action: 'Conquérir', |         action: 'Conquérir', | ||||||
|         onConqueteReussie: r => EffetsDraconiques.conquete.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), |         onConqueteReussie: r => EffetsDraconiques.conquete.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), | ||||||
|         onConqueteEchec: r => this.close(), |         onConqueteEchec: r => this.$forceClose(`${this.actor.name} n'a pas conquis la case ${tmr.label}, et quitte les TMR.`), | ||||||
|         canClose: false |         canClose: false | ||||||
|       }); |       }); | ||||||
|     } |     } | ||||||
| @@ -922,19 +935,15 @@ export class RdDTMRDialog extends Dialog { | |||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   async processSortReserve(sortReserve) { |   async processSortReserve(sortReserve) { | ||||||
|     await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]); |     await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]); | ||||||
|     console.log("declencheSortEnReserve", sortReserve); |     console.log("declencheSortEnReserve", sortReserve) | ||||||
|     const heureCible = RdDTimestamp.definition(sortReserve.system.heurecible).label; |     const sort = sortReserve.system.sortid ? this.actor.items.get(sortReserve.system.sortid) : undefined | ||||||
|     this._tellToUserAndGM(`Vous avez déclenché  |     const message = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-lancement-sortreserve.hbs`, | ||||||
|         ${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"} |       { sortReserve, sort }) | ||||||
|         en réserve <strong>${sortReserve.name}</strong> |     await this.$forceClose(message) | ||||||
|         avec ${sortReserve.system.ptreve} points de Rêve |  | ||||||
|         en ${sortReserve.system.coord} (${TMRUtility.getTMRLabel(sortReserve.system.coord)}). |  | ||||||
|         L'heure ciblée est ${heureCible}`); |  | ||||||
|     this.close(); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   nettoyerRencontre() { |   $nettoyerRencontre() { | ||||||
|     // Suppression des dessins des zones possibles |     // Suppression des dessins des zones possibles | ||||||
|     this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic)) |     this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic)) | ||||||
|     // Nettoyage de la structureet de l'état |     // Nettoyage de la structureet de l'état | ||||||
| @@ -1021,7 +1030,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|         console.log("STATUS :", this.rencontreState, this.currentRencontre); |         console.log("STATUS :", this.rencontreState, this.currentRencontre); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     this.checkQuitterTMR(); |     await this.$checkQuitterTMR(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
| @@ -1054,13 +1063,13 @@ export class RdDTMRDialog extends Dialog { | |||||||
|     */ |     */ | ||||||
|     this.notifierResonanceSigneDraconique(targetCoord); |     this.notifierResonanceSigneDraconique(targetCoord); | ||||||
|     await this.actor.rollUnSort(targetCoord); |     await this.actor.rollUnSort(targetCoord); | ||||||
|     this.nettoyerRencontre(); |     this.$nettoyerRencontre(); | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   /* -------------------------------------------- */ |   /* -------------------------------------------- */ | ||||||
|   externalRefresh() { |   externalRefresh() { | ||||||
|     this.createPixiSprites(); |     this.createPixiSprites(); | ||||||
|     this.updateValuesDisplay(); |     this.$updateValuesDisplay(); | ||||||
|     this.updateTokens(); |     this.updateTokens(); | ||||||
|     console.log("TMR REFRESHED !!!"); |     console.log("TMR REFRESHED !!!"); | ||||||
|   } |   } | ||||||
| @@ -1071,7 +1080,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|       return this.forceTMRContinueAction() |       return this.forceTMRContinueAction() | ||||||
|     } |     } | ||||||
|     if (this.currentRencontre != 'normal') { |     if (this.currentRencontre != 'normal') { | ||||||
|       this.nettoyerRencontre(); |       this.$nettoyerRencontre(); | ||||||
|     } |     } | ||||||
|     let tmr = TMRUtility.getTMR(targetCoord); |     let tmr = TMRUtility.getTMR(targetCoord); | ||||||
|     // Gestion cases spéciales type Trou noir, etc |     // Gestion cases spéciales type Trou noir, etc | ||||||
| @@ -1083,7 +1092,7 @@ export class RdDTMRDialog extends Dialog { | |||||||
|     if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { |     if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { | ||||||
|       this.cumulFatigue += this.fatigueParCase; |       this.cumulFatigue += this.fatigueParCase; | ||||||
|     } |     } | ||||||
|     this.updateValuesDisplay(); |     this.$updateValuesDisplay(); | ||||||
|     this.actor.notifyRefreshTMR(); |     this.actor.notifyRefreshTMR(); | ||||||
|  |  | ||||||
|     if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... |     if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... | ||||||
|   | |||||||
| @@ -318,6 +318,7 @@ export class RdDUtility { | |||||||
|     // gestion des dates et heures |     // gestion des dates et heures | ||||||
|     Handlebars.registerHelper('timestamp-imgSigneHeure', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigneHeure(heure)) }); |     Handlebars.registerHelper('timestamp-imgSigneHeure', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigneHeure(heure)) }); | ||||||
|     Handlebars.registerHelper('timestamp-imgSigne', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigne(heure)) }); |     Handlebars.registerHelper('timestamp-imgSigne', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigne(heure)) }); | ||||||
|  |     Handlebars.registerHelper('timestamp-definition', (heure) => RdDTimestamp.definition(heure)) | ||||||
|     Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier()); |     Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier()); | ||||||
|     Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree()); |     Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree()); | ||||||
|     Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode()); |     Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode()); | ||||||
|   | |||||||
| @@ -1,6 +1,7 @@ | |||||||
| { | { | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "build": "npx vite build", |     "build": "npx vite build", | ||||||
|  |     "run": "npx vite serve", | ||||||
|     "packCompendiumsToDist": "node ./tools/packCompendiumsToDist.mjs", |     "packCompendiumsToDist": "node ./tools/packCompendiumsToDist.mjs", | ||||||
|     "packCompendiumsToPublic": "node ./tools/packCompendiumsToPublic.mjs", |     "packCompendiumsToPublic": "node ./tools/packCompendiumsToPublic.mjs", | ||||||
|     "unpackCompendiumsFromPublic": "node ./tools/unpackCompendiumsFromPublic.mjs" |     "unpackCompendiumsFromPublic": "node ./tools/unpackCompendiumsFromPublic.mjs" | ||||||
|   | |||||||
| @@ -196,7 +196,7 @@ system: | |||||||
|       derivee: false |       derivee: false | ||||||
|     protection: |     protection: | ||||||
|       type: number |       type: number | ||||||
|       value: 2 |       value: 10 | ||||||
|       label: Protection |       label: Protection | ||||||
|       derivee: false |       derivee: false | ||||||
|   compteurs: |   compteurs: | ||||||
|   | |||||||
| @@ -1,9 +1,9 @@ | |||||||
| { | { | ||||||
|   "id": "foundryvtt-reve-de-dragon", |   "id": "foundryvtt-reve-de-dragon", | ||||||
|   "title": "Rêve de Dragon", |   "title": "Rêve de Dragon", | ||||||
|   "version": "12.0.38", |   "version": "12.0.44", | ||||||
|   "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.38/rddsystem.zip", |   "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.44/rddsystem.zip", | ||||||
|   "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.38/system.json", |   "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/releases/download/12.0.44/system.json", | ||||||
|   "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", |   "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", | ||||||
|   "compatibility": { |   "compatibility": { | ||||||
|     "minimum": "11", |     "minimum": "11", | ||||||
|   | |||||||
| @@ -4,8 +4,7 @@ | |||||||
|     <a class="chat-card-button forcer-tmr-aleatoire" data-tooltip="Ré-insérer aléatoirement le demi-rêve, et masquer la position au joueur">Ré-insertion aléatoire</a> |     <a class="chat-card-button forcer-tmr-aleatoire" data-tooltip="Ré-insérer aléatoirement le demi-rêve, et masquer la position au joueur">Ré-insertion aléatoire</a> | ||||||
|   </span> |   </span> | ||||||
|   <span> |   <span> | ||||||
|     <a class="chat-card-button afficher-tmr" |     <a class="chat-card-button afficher-tmr" data-tooltip="{{#if hautreve.cacheTMR}}Révéler la position du demi-rêve au joueur{{else}}Cacher la position du demi-rêve au joueur{{/if}}">{{#if hautreve.cacheTMR}}Révéler le demi-rêve{{else}}Cacher le demi-rêve{{/if}}</a> | ||||||
|       data-tooltip="{{#if hautreve.cacheTMR}}Montrer la position du demi-rêve au joueur{{else}}Cacher la position du demi-rêve au joueur{{/if}}">{{#if hautreve.cacheTMR}}Montrer les TMR{{else}}Cacher les TMR{{/if}}</a> |  | ||||||
|   </span> |   </span> | ||||||
| </li> | </li> | ||||||
| {{/if}} | {{/if}} | ||||||
|   | |||||||
| @@ -1,15 +1,18 @@ | |||||||
| <div> | <div> | ||||||
|   <ul class="item-list"> |   <ul class="item-list"> | ||||||
|     <li class="item flexrow"> |     <li class="flexrow"> | ||||||
|       <label class="derivee-label" for="system.compteurs.experience.value">Stress transformé</label> |       <label class="derivee-label" for="system.compteurs.experience.value">Stress transformé</label> | ||||||
|       {{#if options.vueDetaillee}} |       {{#if options.vueDetaillee}} | ||||||
|       <input class="derivee-value" type="number" name="system.compteurs.experience.value" value="{{system.compteurs.experience.value}}" data-dtype="number" size="3"/> |       <input class="resource-content" | ||||||
|  |         type="text" data-dtype="Number" size="3" | ||||||
|  |         name="system.compteurs.experience.value" | ||||||
|  |         value="{{system.compteurs.experience.value}}"/> | ||||||
|       {{else}} |       {{else}} | ||||||
|       <label name="system.compteurs.experience.value">{{system.compteurs.experience.value}}</label> |       <label name="system.compteurs.experience.value">{{system.compteurs.experience.value}}</label> | ||||||
|       {{/if}} |       {{/if}} | ||||||
|     </li> |     </li> | ||||||
|     {{#if options.vueDetaillee}} |     {{#if options.vueDetaillee}} | ||||||
|     <li class="item flexrow"> |     <li class="flexrow"> | ||||||
|       <span class="generic-label">Total XP compétences</span> |       <span class="generic-label">Total XP compétences</span> | ||||||
|       <span class="competence-value">{{calc.competenceXPTotal}}</span> |       <span class="competence-value">{{calc.competenceXPTotal}}</span> | ||||||
|     </li> |     </li> | ||||||
|   | |||||||
| @@ -2,19 +2,22 @@ | |||||||
|   <h4 class="rdd-roll-part">{{alias}} réussit une attaque particulière!</strong></h4> |   <h4 class="rdd-roll-part">{{alias}} réussit une attaque particulière!</strong></h4> | ||||||
|   {{#if isForce}} |   {{#if isForce}} | ||||||
|   <br> |   <br> | ||||||
|   <a class="chat-card-button particuliere-attaque" data-mode="force" data-attackerId="{{attackerId}}"> |   <a class="chat-card-button particuliere-attaque" data-mode="force" data-attackerId="{{attackerId}}" | ||||||
|  |     data-defenderTokenId="{{defenderToken.id}}" data-attackerTokenId="{{attackerToken.id}}"> | ||||||
|     Attaquer en Force |     Attaquer en Force | ||||||
|   </a> |   </a> | ||||||
|   {{/if}} |   {{/if}} | ||||||
|   {{#if isRapide}} |   {{#if isRapide}} | ||||||
|   <br> |   <br> | ||||||
|   <a class="chat-card-button particuliere-attaque" data-mode="rapidite" data-attackerId="{{attackerId}}"> |   <a class="chat-card-button particuliere-attaque" data-mode="rapidite" data-attackerId="{{attackerId}}" | ||||||
|  |     data-defenderTokenId="{{defenderToken.id}}" data-attackerTokenId="{{attackerToken.id}}"> | ||||||
|     Attaquer en Rapidité |     Attaquer en Rapidité | ||||||
|   </a> |   </a> | ||||||
|   {{/if}} |   {{/if}} | ||||||
|   {{#if isFinesse}} |   {{#if isFinesse}} | ||||||
|   <br> |   <br> | ||||||
|   <a class="chat-card-button particuliere-attaque" data-mode="finesse" data-attackerId="{{attackerId}}"> |   <a class="chat-card-button particuliere-attaque" data-mode="finesse" data-attackerId="{{attackerId}}" | ||||||
|  |     data-defenderTokenId="{{defenderToken.id}}" data-attackerTokenId="{{attackerToken.id}}"> | ||||||
|     Attaquer en Finesse |     Attaquer en Finesse | ||||||
|   </a> |   </a> | ||||||
|   {{/if}} |   {{/if}} | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								templates/chat-lancement-sortreserve.hbs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								templates/chat-lancement-sortreserve.hbs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | <img class="chat-icon" src="{{sortReserve.img}}" data-tooltip="{{sortReserve.name}}"/> | ||||||
|  | <h4>Déclenchement de sort: {{sortReserve.name}}</h4> | ||||||
|  | <br> Vous avez déclenché {{#if sortReserve.system.echectotal}}<strong>l'échec total</strong>{{else}}le sort{{/if}} | ||||||
|  | en réserve en {{sortReserve.system.coord}} ({{caseTmr-label sortReserve.system.coord}}). | ||||||
|  | <br>Ce sort a {{sortReserve.system.ptreve}} points de Rêve | ||||||
|  | <br>L'heure ciblée est {{#if sortReserve.system.heurecible}} | ||||||
|  |   {{timestamp-imgSigneHeure sortReserve.system.heurecible}} {{sortReserve.system.heurecible}} | ||||||
|  |    {{else}}indéterminée{{/if}} | ||||||
|  | {{#if sort}} | ||||||
|  | <div class="poesie-extrait poesie-overflow"> | ||||||
|  |   {{{sort.system.description}}} | ||||||
|  | </div> | ||||||
|  | {{/if}} | ||||||
| @@ -4,7 +4,7 @@ | |||||||
| <hr> | <hr> | ||||||
| <div> | <div> | ||||||
|   {{#if rolled.isSuccess}} |   {{#if rolled.isSuccess}} | ||||||
|   {{alias}} a gagné {{xpSort}} points d'expérience en sorts dans la {{competence.name}}. |   {{alias}} a gagné {{xpSort}} points d'expérience en sorts en {{competence.name}}. | ||||||
|   {{else}} |   {{else}} | ||||||
|   {{alias}} n'a pas pu interpréter le signe draconique. |   {{alias}} n'a pas pu interpréter le signe draconique. | ||||||
|   {{/if}} |   {{/if}} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user