forked from public/foundryvtt-reve-de-dragon
		
	Compare commits
	
		
			97 Commits
		
	
	
		
			daca86b1df
			...
			12.0.48
		
	
	| 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 | |||
| 069fef4720 | |||
| e32a7d7540 | |||
| 0773493851 | |||
| da982678b7 | |||
| c1066d70f6 | |||
| 5085ba5b54 | |||
| f37483a61d | |||
| 5357e53a5f | |||
| 764dde6296 | |||
| 681fbc3177 | |||
| 70e3e63001 | |||
| 7ed9a4a12b | |||
| acfab362a0 | |||
| 3d49a3de11 | |||
| 24518642a7 | |||
| d917f80e88 | |||
| b29027c61a | |||
| 6083dd41fa | |||
| 8969d5e0ed | |||
| 7d135a214f | |||
| 9d66a479c4 | |||
| 800b4a2f32 | |||
| 9fc21e6d97 | |||
| ce7f5381ca | |||
| 48acdaaca6 | |||
| 425c6af672 | |||
| 4281f76dfb | |||
| 8ebd6ec771 | |||
| 14391daa0b | |||
| ac29e1410e | |||
| 442ffe9b3a | |||
| d922e4fdd5 | |||
| a8dc07b4db | |||
| 40a47ee8a2 | |||
| c5633a9fc5 | |||
| 7e8da49912 | |||
| b524716ede | |||
| 72a9752820 | |||
| 8e578c6566 | |||
| 5ac9c682d9 | |||
| 6de19eb357 | |||
| 90d096a6df | |||
| c733644f3a | |||
| de9d3bbb48 | |||
| efdffd171c | |||
| 8406c8434a | |||
| a4b474970c | |||
| 135e5e46a0 | |||
| 969bc3b573 | |||
| a9eb101c9d | |||
| d53da1f011 | |||
| ab0f7e563f | |||
| 57c41a0218 | |||
| 1b75decb18 | |||
| 551438f514 | |||
| 792558ac84 | |||
| 06aff9a3c0 | |||
| 7e736a00d7 | |||
| b87f406093 | |||
| 785bd4b9ce | 
							
								
								
									
										109
									
								
								changelog.md
									
									
									
									
									
								
							
							
						
						
									
										109
									
								
								changelog.md
									
									
									
									
									
								
							| @@ -1,20 +1,129 @@ | ||||
| # 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 | ||||
|  | ||||
| - 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 | ||||
|  | ||||
| ## 12.0.38 - Les prévisions d'Astrobazzarh | ||||
|  | ||||
| - Correction de modifications de personnages qui ne s'affichaient pas: | ||||
|   - changements d'endurance/vie/fatigue, transformé, ... | ||||
| - Migration des compétences "Ecriture" en "Écriture" dans les tâches, livres, oeuvres et méditations | ||||
| - Correction des jets de compétences de créatures | ||||
| - Premières préparations techniques pour le passage à Founry v13 | ||||
|   - liste des impacts d'un jet de dés (expérience, points de tâche, ...) | ||||
|   - utilisation de l'extension hbs pour tous les fichiers handlebars | ||||
|  | ||||
| ## 12.0.37 - Les enchantements d'Astrobazzarh | ||||
|  | ||||
| - les potions ont un état, seules les potions liquides sont enchantables | ||||
| - 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 | ||||
| - on peut enchanter des gemmes exactement comme des potions | ||||
|  | ||||
| ## 12.0.36 - L'alchimie d'Astrobazzarh | ||||
|  | ||||
| - Nouveautés | ||||
|   - ajout d'un bouton pour enchanter les potions | ||||
|   - standardisation des boutons d'actions sur les items | ||||
|   - utilisations d'icones pour les actions de l'inventaire | ||||
| - Corrections: | ||||
|   - la commande /tmra sans paramètres fonctionne | ||||
|   - les jets d'encaissement depuis le tchat fonctionnent | ||||
|   - affichage de la vie/endurance en cas de blessures et remise à neuf | ||||
|   - les queues durant 12 heures ajoutées début Vaisseau ne durent plus 24 heures | ||||
| - Compendiums | ||||
|   - Corrections des remedes enchantables | ||||
|   - Corrections de descriptions pour proposer les jet de dés | ||||
|  | ||||
| ## 12.0.35 - La Solution d'Astrobazzarh | ||||
|  | ||||
| - Fix problème d'initialisation des feuilles d'items | ||||
|  | ||||
| ## 12.0.34 - la tête d'Astrobazzarh | ||||
|  | ||||
| - support de liens "jets de dés" | ||||
|   - 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: | ||||
|     - un jet de caractéristique/compétence `@roll[carac/competence/difficulte]` / `@roll[carac/difficulte]` / `@roll[carac/competence]`  | ||||
|     - une formule foundry `@roll[2d6]` pour lancer 2d6  | ||||
|     - une manipulation alchimique `@roll[couleur vert-bleu]` | ||||
|   - les liens "jet avec caractéristiques" s'appliquent: | ||||
|     - à tous les tokens sélectionnés | ||||
|     - sinon, à l'acteur propriétaire (dans le cas d'un Item) ou à l'acteur courant | ||||
|     - sinon, au personnage du joueur | ||||
|   - on peut poster les liens dans le tchat pour proposer un jet aux joueurs | ||||
| - gestion des blocs secrets dans les descriptions | ||||
|  | ||||
| ## 12.0.33 - la vieillesse d'Astrobazzarh | ||||
|  | ||||
| - retour de l'expérience pour les joueurs | ||||
| - suppression du message "Pas de caractéristique" sur les jets d'odorat-goût | ||||
|  | ||||
| ## 12.0.32 - les rêveries d'Astrobazzarh | ||||
|  | ||||
| - Ajout des Items Race pour gérer les ajustements liés aux races | ||||
|  | ||||
| ## 12.0.31 - le mausolée d'Astrobazzarh | ||||
|  | ||||
| - Correction: les automatisation de combat jouer-MJ fonctionnentde nouveau | ||||
|  | ||||
| ## 12.0.30 - le cauchemar d'Astrobazzarh | ||||
|  | ||||
| - calcul automatique du niveau des entités selon leur rêve | ||||
| - 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) | ||||
|  | ||||
| ## 12.0.29 - L'indexation d'Astrobazzarh | ||||
|  | ||||
| - 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 | ||||
|  | ||||
|   | ||||
| @@ -44,13 +44,13 @@ export class ChatVente { | ||||
|     vente.nbLots = Math.max(0, vente.nbLots - quantite) | ||||
|     await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots) | ||||
|  | ||||
|     const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente); | ||||
|     const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.hbs', vente); | ||||
|     chatMessage.update({ content: html }); | ||||
|     chatMessage.render(true); | ||||
|   } | ||||
|  | ||||
|   static async displayAchatVente(vente) { | ||||
|     const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente); | ||||
|     const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.hbs', vente); | ||||
|     const chatMessage = await ChatMessage.create(RdDUtility.chatDataSetup(html)) | ||||
|     await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots) | ||||
|     await chatMessage.setFlag(SYSTEM_RDD, DETAIL_VENTE, { | ||||
|   | ||||
| @@ -29,7 +29,7 @@ export class DialogItemAchat extends Dialog { | ||||
|     } | ||||
|  | ||||
|     DialogItemAchat.changeNombreLots(venteData, 1) | ||||
|     const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData) | ||||
|     const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.hbs`, venteData) | ||||
|     new DialogItemAchat(html, venteData).render(true) | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -20,7 +20,7 @@ export class DialogItemVente extends Dialog { | ||||
|       quantiteIllimite: item.isItemCommerce() ? quantiteMax == undefined : !item.parent, | ||||
|       isOwned:  item.parent, | ||||
|     } | ||||
|     const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData); | ||||
|     const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.hbs`, venteData); | ||||
|     return new DialogItemVente(venteData, html).render(true); | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -12,13 +12,14 @@ import { RdDSheetUtility } from "./rdd-sheet-utility.js"; | ||||
| import { STATUSES } from "./settings/status-effects.js"; | ||||
| import { MAINS_DIRECTRICES } from "./actor.js"; | ||||
| import { RdDBaseActorReveSheet } from "./actor/base-actor-reve-sheet.js"; | ||||
| import { ITEM_TYPES, RdDItem } from "./item.js"; | ||||
| import { ITEM_TYPES } from "./constants.js"; | ||||
| import { RdDItem } from "./item.js"; | ||||
| import { RdDItemBlessure } from "./item/blessure.js"; | ||||
| import { RdDEmpoignade } from "./rdd-empoignade.js"; | ||||
| import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js"; | ||||
| import { RdDCoeur } from "./coeur/rdd-coeur.js"; | ||||
| import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js"; | ||||
| import { RdDItemRace } from "./item/race.js"; | ||||
| import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js"; | ||||
|  | ||||
| /* -------------------------------------------- */ | ||||
| /** | ||||
| @@ -29,7 +30,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | ||||
|   /** @override */ | ||||
|   static get defaultOptions() { | ||||
|     return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, { | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html", | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.hbs", | ||||
|       width: 550, | ||||
|       showCompNiveauBase: false, | ||||
|       vueArchetype: false, | ||||
| @@ -44,8 +45,8 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | ||||
|       cssClass: this.isEditable ? "editable" : "locked", | ||||
|       limited: this.actor.limited, | ||||
|       owner: this.actor.isOwner, | ||||
|       biographie: await TextEditor.enrichHTML(this.actor.system.biographie, { async: true }), | ||||
|       notes: await TextEditor.enrichHTML(this.actor.system.notes, { async: true }), | ||||
|       biographie: await RdDTextEditor.enrichHTML(this.actor.system.biographie, this.actor), | ||||
|       notes: await RdDTextEditor.enrichHTML(this.actor.system.notes, this.actor), | ||||
|     }); | ||||
|     foundry.utils.mergeObject(formData.calc, { | ||||
|       surenc: this.actor.computeMalusSurEncombrement(), | ||||
| @@ -125,80 +126,73 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | ||||
|     }) | ||||
|  | ||||
|     this.html.find('.show-hide-competences').click(async event => { | ||||
|       this.options.showCompNiveauBase = !this.options.showCompNiveauBase; | ||||
|       this.render(true); | ||||
|       this.options.showCompNiveauBase = !this.options.showCompNiveauBase | ||||
|       this.render(true) | ||||
|     }); | ||||
|  | ||||
|     this.html.find('.button-tmr-visu').click(async event => this.actor.displayTMR("visu")) | ||||
|     this.html.find('.button-tmr-visu').click(async event => await this.actor.displayTMR("visu")) | ||||
|  | ||||
|     // Everything below here is only needed if the sheet is editable | ||||
|     if (!this.options.editable) return; | ||||
|  | ||||
|     this.html.find('.sheet-possession-attack').click(async event => { | ||||
|       const poss = RdDSheetUtility.getItem(event, this.actor) | ||||
|       this.actor.conjurerPossession(poss) | ||||
|       await this.actor.conjurerPossession(poss) | ||||
|     }) | ||||
|  | ||||
|     this.html.find('.subacteur-coeur-toggle a').click(async event => { | ||||
|       const subActorIdactorId = RdDSheetUtility.getEventItemData(event, 'subactor-id') | ||||
|       const coeurNombre = $(event.currentTarget).data('numero-coeur') | ||||
|       RdDCoeur.toggleSubActeurCoeur(this.actor.id, subActorIdactorId, coeurNombre) | ||||
|       await RdDCoeur.toggleSubActeurCoeur(this.actor.id, subActorIdactorId, coeurNombre) | ||||
|     }) | ||||
|     this.html.find('.subacteur-tendre-moment').click(async event => { | ||||
|       const subActorId = RdDSheetUtility.getEventItemData(event, 'subactor-id') | ||||
|       RdDCoeur.startSubActeurTendreMoment(this.actor.id, subActorId) | ||||
|       await RdDCoeur.startSubActeurTendreMoment(this.actor.id, subActorId) | ||||
|     }) | ||||
|     this.html.find('.subacteur-delete').click(async event => { | ||||
|       const li = RdDSheetUtility.getEventElement(event); | ||||
|       const subActorId = li.data("subactor-id"); | ||||
|       this.deleteSubActeur(subActorId, li); | ||||
|     }) | ||||
|     this.html.find("input.derivee-value[name='system.compteurs.stress.value']").change(async event => { | ||||
|       this.actor.updateCompteurValue("stress", parseInt(event.target.value)); | ||||
|     }); | ||||
|     this.html.find("input.derivee-value[name='system.compteurs.experience.value']").change(async event => { | ||||
|       this.actor.updateCompteurValue("experience", parseInt(event.target.value)); | ||||
|     }); | ||||
|     this.html.find("input.derivee-value[name='system.compteurs.stress.value']").change(async event => | ||||
|       await this.actor.updateCompteurValue("stress", parseInt(event.target.value)) | ||||
|     ); | ||||
|     this.html.find("input.derivee-value[name='system.compteurs.experience.value']").change(async event => | ||||
|       await this.actor.updateCompteurValue("experience", parseInt(event.target.value)) | ||||
|     ); | ||||
|  | ||||
|     this.html.find('.creer-tache').click(async event => this.createEmptyTache()); | ||||
|     this.html.find('.creer-une-oeuvre').click(async event => this.selectTypeOeuvreToCreate()); | ||||
|     this.html.find('.creer-tache-blessure-legere').click(async event => RdDItemBlessure.createTacheSoinBlessure(this.actor, 2)); | ||||
|     this.html.find('.creer-tache-blessure-grave').click(async event => RdDItemBlessure.createTacheSoinBlessure(this.actor, 4)); | ||||
|     this.html.find('.creer-tache-blessure-critique').click(async event => RdDItemBlessure.createTacheSoinBlessure(this.actor, 6)); | ||||
|     this.html.find('.creer-tache').click(async event => await this.createEmptyTache()); | ||||
|     this.html.find('.creer-une-oeuvre').click(async event => await this.selectTypeOeuvreToCreate()); | ||||
|     this.html.find('.creer-tache-blessure-legere').click(async event => await RdDItemBlessure.createTacheSoinBlessure(this.actor, 2)); | ||||
|     this.html.find('.creer-tache-blessure-grave').click(async event => await RdDItemBlessure.createTacheSoinBlessure(this.actor, 4)); | ||||
|     this.html.find('.creer-tache-blessure-critique').click(async event => await RdDItemBlessure.createTacheSoinBlessure(this.actor, 6)); | ||||
|  | ||||
|     this.html.find('.blessure-premierssoins-done').change(async event => { | ||||
|       const blessure = this.getBlessure(event); | ||||
|       await blessure?.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } }); | ||||
|       await this.getBlessure(event)?.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } }); | ||||
|     }); | ||||
|     this.html.find('.blessure-soinscomplets-done').change(async event => { | ||||
|       const blessure = this.getBlessure(event); | ||||
|       await blessure?.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } }) | ||||
|       await this.getBlessure(event)?.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } }) | ||||
|     }); | ||||
|     this.html.find('.blessure-premierssoins-bonus').change(async event => { | ||||
|       const blessure = this.getBlessure(event); | ||||
|       await blessure?.setSoinsBlessure({ premierssoins: { bonus: Number(event.currentTarget.value) } }) | ||||
|       await this.getBlessure(event)?.setSoinsBlessure({ premierssoins: { bonus: Number(event.currentTarget.value) } }) | ||||
|     }); | ||||
|     this.html.find('.blessure-soinscomplets-bonus').change(async event => { | ||||
|       const blessure = this.getBlessure(event); | ||||
|       await blessure?.setSoinsBlessure({ soinscomplets: { bonus: Number(event.currentTarget.value) } }) | ||||
|       await this.getBlessure(event)?.setSoinsBlessure({ soinscomplets: { bonus: Number(event.currentTarget.value) } }) | ||||
|     }); | ||||
|  | ||||
|     // Equip Inventory Item | ||||
|     this.html.find('.item-equip').click(async event => this.actor.equiperObjet(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.roll-chance-actuelle').click(async event => this.actor.rollCarac('chance-actuelle')) | ||||
|     this.html.find('.roll-chance-actuelle').click(async event => await this.actor.rollCarac('chance-actuelle')) | ||||
|     this.html.find('.button-appel-chance').click(async event => await this.actor.rollAppelChance()) | ||||
|  | ||||
|     this.html.find('.button-appel-chance').click(async event => this.actor.rollAppelChance()) | ||||
|     this.html.find('[name="jet-astrologie"]').click(async event => await this.actor.astrologieNombresAstraux()) | ||||
|     this.html.find('.action-tache').click(async event => await this.actor.rollTache(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.meditation-label a').click(async event => await this.actor.rollMeditation(RdDSheetUtility.getItemId(event))) | ||||
|  | ||||
|     this.html.find('[name="jet-astrologie"]').click(async event => this.actor.astrologieNombresAstraux()) | ||||
|     this.html.find('.tache-label a').click(async event => this.actor.rollTache(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.meditation-label a').click(async event => this.actor.rollMeditation(RdDSheetUtility.getItemId(event))) | ||||
|  | ||||
|     this.html.find('.chant-label a').click(async event => this.actor.rollChant(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.danse-label a').click(async event => this.actor.rollDanse(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.musique-label a').click(async event => this.actor.rollMusique(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.oeuvre-label a').click(async event => this.actor.rollOeuvre(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.jeu-label a').click(async event => this.actor.rollJeu(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.recettecuisine-label a').click(async event => this.actor.rollRecetteCuisine(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.action-chant').click(async event => await this.actor.rollChant(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.action-danse').click(async event => await this.actor.rollDanse(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.action-musique').click(async event => await this.actor.rollMusique(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.action-oeuvre').click(async event => await this.actor.rollOeuvre(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.action-jeu').click(async event => await this.actor.rollJeu(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.action-recettecuisine').click(async event => await this.actor.rollRecetteCuisine(RdDSheetUtility.getItemId(event))) | ||||
|  | ||||
|     this.html.find('.description-aleatoire').click(async event => new AppPersonnageAleatoire(this.actor).render(true)) | ||||
|     if (game.user.isGM) { | ||||
| @@ -214,17 +208,16 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | ||||
|         await this.actor.deleteExperienceLog(0, key + 1); | ||||
|       }); | ||||
|       // Boutons spéciaux MJs | ||||
|       this.html.find('.forcer-tmr-aleatoire').click(async event => this.actor.reinsertionAleatoire("Action MJ")) | ||||
|       this.html.find('.don-de-haut-reve').click(async event => this.actor.addDonDeHautReve()) | ||||
|       this.html.find('.sortreserve-add').click(async event => this.actor.addSortReserve(RdDSheetUtility.getItemId(event))) | ||||
|       this.html.find('.afficher-tmr').click(async event => this.actor.changeTMRVisible()) | ||||
|       this.html.find('.forcer-tmr-aleatoire').click(async event => await this.actor.reinsertionAleatoire("Action MJ")) | ||||
|       this.html.find('.don-de-haut-reve').click(async event => await this.actor.addDonDeHautReve()) | ||||
|       this.html.find('.afficher-tmr').click(async event => await this.actor.changeTMRVisible()) | ||||
|     } | ||||
|  | ||||
|     // Points de reve actuel | ||||
|     this.html.find('.roll-reve-actuel').click(async event => this.actor.rollCarac('reve-actuel', true)) | ||||
|     this.html.find('.empoignade-label a').click(async event => RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor))) | ||||
|     this.html.find('.roll-reve-actuel').click(async event => await this.actor.rollCarac('reve-actuel', { resistance: true })) | ||||
|     this.html.find('.action-empoignade').click(async event => await RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor))) | ||||
|  | ||||
|     this.html.find('.roll-arme').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event)), 'competence')) | ||||
|     this.html.find('.roll-arme').click(async event => await this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event)), 'competence')) | ||||
|  | ||||
|     // Initiative pour l'arme | ||||
|     this.html.find('.roll-init-arme').click(async event => { | ||||
| @@ -237,30 +230,34 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | ||||
|     }) | ||||
|     // Display TMR | ||||
|  | ||||
|     this.html.find('.button-tmr').click(async event => this.actor.displayTMR("normal")) | ||||
|     this.html.find('.button-tmr-rapide').click(async event => this.actor.displayTMR("rapide")) | ||||
|     this.html.find('.button-tmr').click(async event => await this.actor.displayTMR("normal")) | ||||
|     this.html.find('.button-tmr-rapide').click(async event => await this.actor.displayTMR("rapide")) | ||||
|  | ||||
|     this.html.find('.button-repos').click(async event => await this.actor.repos()) | ||||
|  | ||||
|     this.html.find('.carac-xp-augmenter').click(async event => this.actor.updateCaracXPAuto(event.currentTarget.name.replace("augmenter.", ""))) | ||||
|     this.html.find('.competence-xp-augmenter').click(async event => this.actor.updateCompetenceXPAuto(RdDSheetUtility.getItemId(event))) | ||||
|     this.html.find('.competence-stress-augmenter').click(async event => this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event))) | ||||
|     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-stress-augmenter').click(async event =>{ | ||||
|       await this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event)) | ||||
|       this.render(true) | ||||
|     }  | ||||
|   ) | ||||
|  | ||||
|     if (this.options.vueDetaillee) { | ||||
|       // On carac change | ||||
|       this.html.find('input.carac-xp').change(async event => { | ||||
|         let caracName = event.currentTarget.name.replace(".xp", "").replace("system.carac.", ""); | ||||
|         this.actor.updateCaracXP(caracName, parseInt(event.target.value)); | ||||
|       }); | ||||
|         let caracName = event.currentTarget.name.replace(".xp", "").replace("system.carac.", "") | ||||
|         await this.actor.updateCaracXP(caracName, parseInt(event.target.value)) | ||||
|       }) | ||||
|       // On competence xp change | ||||
|       this.html.find('input.competence-xp').change(async event => { | ||||
|         let compName = event.currentTarget.attributes.compname.value; | ||||
|         this.actor.updateCompetenceXP(compName, parseInt(event.target.value)); | ||||
|       }); | ||||
|         let compName = event.currentTarget.attributes.compname.value | ||||
|         await this.actor.updateCompetenceXP(compName, parseInt(event.target.value)) | ||||
|       }) | ||||
|       this.html.find('input.competence-xp-sort').change(async event => { | ||||
|         let compName = event.currentTarget.attributes.compname.value; | ||||
|         this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value)); | ||||
|       }); | ||||
|         let compName = event.currentTarget.attributes.compname.value | ||||
|         await this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value)) | ||||
|       }) | ||||
|  | ||||
|       this.html.find('.toggle-archetype').click(async event => { | ||||
|         this.options.vueArchetype = !this.options.vueArchetype; | ||||
| @@ -269,27 +266,27 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | ||||
|       // On competence archetype change | ||||
|       this.html.find('.competence-archetype').change(async event => { | ||||
|         let compName = event.currentTarget.attributes.compname.value; | ||||
|         this.actor.updateCompetenceArchetype(compName, parseInt(event.target.value)); | ||||
|         await this.actor.updateCompetenceArchetype(compName, parseInt(event.target.value)); | ||||
|       }); | ||||
|       this.html.find('.nouvelle-incarnation').click(async event => this.actor.nouvelleIncarnation()) | ||||
|       this.html.find('.nouvelle-incarnation').click(async event => await this.actor.nouvelleIncarnation()) | ||||
|     } | ||||
|  | ||||
|     // On pts de reve change | ||||
|     this.html.find('.pointsreve-value').change(async event => this.actor.update({ "system.reve.reve.value": event.currentTarget.value })) | ||||
|     this.html.find('.seuil-reve-value').change(async event => this.actor.setPointsDeSeuil(event.currentTarget.value)) | ||||
|     this.html.find('.pointsreve-value').change(async event => await this.actor.update({ "system.reve.reve.value": event.currentTarget.value })) | ||||
|     this.html.find('.seuil-reve-value').change(async event => await this.actor.setPointsDeSeuil(event.currentTarget.value)) | ||||
|  | ||||
|     this.html.find('.stress-test').click(async event => this.actor.transformerStress()) | ||||
|     this.html.find('.moral-malheureux').click(async event => this.actor.jetDeMoral('malheureuse')) | ||||
|     this.html.find('.moral-neutre').click(async event => this.actor.jetDeMoral('neutre')) | ||||
|     this.html.find('.moral-heureux').click(async event => this.actor.jetDeMoral('heureuse')) | ||||
|     this.html.find('.button-ethylisme').click(async event => this.actor.jetEthylisme()) | ||||
|     this.html.find('.stress-test').click(async event => await this.actor.transformerStress()) | ||||
|     this.html.find('.moral-malheureux').click(async event => await this.actor.jetDeMoral('malheureuse')) | ||||
|     this.html.find('.moral-neutre').click(async event => await this.actor.jetDeMoral('neutre')) | ||||
|     this.html.find('.moral-heureux').click(async event => await this.actor.jetDeMoral('heureuse')) | ||||
|     this.html.find('.button-ethylisme').click(async event => await this.actor.jetEthylisme()) | ||||
|  | ||||
|     this.html.find('.ptreve-actuel-plus').click(async event => this.actor.reveActuelIncDec(1)) | ||||
|     this.html.find('.ptreve-actuel-moins').click(async event => this.actor.reveActuelIncDec(-1)) | ||||
|     this.html.find('.chance-actuelle-plus').click(async event => this.actor.chanceActuelleIncDec(1)) | ||||
|     this.html.find('.chance-actuelle-moins').click(async event => this.actor.chanceActuelleIncDec(-1)) | ||||
|     this.html.find('.fatigue-plus').click(async event => this.actor.santeIncDec("fatigue", 1)) | ||||
|     this.html.find('.fatigue-moins').click(async event => this.actor.santeIncDec("fatigue", -1)) | ||||
|     this.html.find('.ptreve-actuel-plus').click(async event => await this.actor.reveActuelIncDec(1)) | ||||
|     this.html.find('.ptreve-actuel-moins').click(async event => await this.actor.reveActuelIncDec(-1)) | ||||
|     this.html.find('.chance-actuelle-plus').click(async event => await this.actor.chanceActuelleIncDec(1)) | ||||
|     this.html.find('.chance-actuelle-moins').click(async event => await this.actor.chanceActuelleIncDec(-1)) | ||||
|     this.html.find('.fatigue-plus').click(async event => await this.actor.santeIncDec("fatigue", 1)) | ||||
|     this.html.find('.fatigue-moins').click(async event => await this.actor.santeIncDec("fatigue", -1)) | ||||
|   } | ||||
|  | ||||
|   getBlessure(event) { | ||||
| @@ -326,7 +323,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet { | ||||
|   /* -------------------------------------------- */ | ||||
|   async selectTypeOeuvreToCreate() { | ||||
|     let types = RdDItem.getTypesOeuvres(); | ||||
|     let content = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`; | ||||
|     let content = `<span class="generic-label">Selectionnez le type d'oeuvre</span><select class="item-type">`; | ||||
|     for (let typeName of types) { | ||||
|       content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>` | ||||
|     } | ||||
|   | ||||
							
								
								
									
										538
									
								
								module/actor.js
									
									
									
									
									
								
							
							
						
						
									
										538
									
								
								module/actor.js
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,5 +1,6 @@ | ||||
| import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js"; | ||||
| import { Grammar } from "../grammar.js"; | ||||
| import { ITEM_TYPES } from "../item.js"; | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { RdDSheetUtility } from "../rdd-sheet-utility.js"; | ||||
| import { RdDBaseActorSheet } from "./base-actor-sheet.js"; | ||||
|  | ||||
| @@ -25,16 +26,17 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet { | ||||
|     // Everything below here is only needed if the sheet is editable | ||||
|     if (!this.options.editable) return; | ||||
|  | ||||
|     this.html.find('.button-encaissement').click(async event => this.actor.encaisser()) | ||||
|     this.html.find('.button-encaissement').click(async event => await this.actor.encaisser()) | ||||
|     this.html.find('.roll-carac').click(async event => { | ||||
|       this.actor.rollCarac(Grammar.toLowerCaseNoAccent(event.currentTarget.attributes['data-carac-name'].value))}); | ||||
|     this.html.find('.roll-competence').click(async event => this.actor.rollCompetence(RdDSheetUtility.getItemId(event))); | ||||
|     this.html.find('.endurance-plus').click(async event => this.actor.santeIncDec("endurance", 1)); | ||||
|     this.html.find('.endurance-moins').click(async event => this.actor.santeIncDec("endurance", -1)); | ||||
|       await this.actor.rollCarac(Grammar.toLowerCaseNoAccent(event.currentTarget.attributes['data-carac-name'].value)) | ||||
|     }) | ||||
|     this.html.find('.roll-competence').click(async event => await this.actor.rollCompetence(RdDSheetUtility.getItemId(event))); | ||||
|     this.html.find('.endurance-plus').click(async event => await this.actor.santeIncDec("endurance", 1)); | ||||
|     this.html.find('.endurance-moins').click(async event => await this.actor.santeIncDec("endurance", -1)); | ||||
|  | ||||
|     if (game.user.isGM) { | ||||
|       this.html.find('.button-remise-a-neuf').click(async event => this.actor.remiseANeuf()) | ||||
|       this.html.find('.delete-active-effect').click(async event => this.actor.removeEffect(this.html.find(event.currentTarget).parents(".active-effect").data('effect'))); | ||||
|       this.html.find('.button-remise-a-neuf').click(async event => await this.actor.remiseANeuf()) | ||||
|       this.html.find('.delete-active-effect').click(async event => await this.actor.removeEffect(this.html.find(event.currentTarget).parents(".active-effect").data('effect'))); | ||||
|       this.html.find('.enlever-tous-effets').click(async event => await this.actor.removeEffects()); | ||||
|     } | ||||
|     this.html.find('.competence-add').click(async event => | ||||
| @@ -47,18 +49,20 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet { | ||||
|         } | ||||
|       }], { renderSheet: true }) | ||||
|     ) | ||||
|     this.html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event, this.actor)) | ||||
|     this.html.find('.chat-roll-text').click(async event => await RdDTextEditor.chatRollText(event)) | ||||
|  | ||||
|  | ||||
|     if (this.options.vueDetaillee) { | ||||
|       // On carac change | ||||
|       this.html.find('.carac-value').change(async event => { | ||||
|         let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", ""); | ||||
|         this.actor.updateCarac(caracName, parseInt(event.target.value)); | ||||
|         let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", "") | ||||
|         await this.actor.updateCarac(caracName, parseInt(event.target.value)) | ||||
|       }); | ||||
|       // On competence change | ||||
|       this.html.find('.competence-value').change(async event => { | ||||
|         let compName = event.currentTarget.attributes.compname.value; | ||||
|         //console.log("Competence changed :", compName); | ||||
|         this.actor.updateCompetence(compName, parseInt(event.target.value)); | ||||
|         let compName = event.currentTarget.attributes.compname.value | ||||
|         await this.actor.updateCompetence(compName, parseInt(event.target.value)) | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
|   | ||||
| @@ -7,7 +7,7 @@ import { RdDRoll } from "../rdd-roll.js"; | ||||
| import { RdDUtility } from "../rdd-utility.js"; | ||||
| import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; | ||||
| import { RdDBaseActor } from "./base-actor.js"; | ||||
| import { ITEM_TYPES } from "../item.js"; | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { RdDItemCompetence } from "../item-competence.js"; | ||||
| import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; | ||||
| import { RdDItemArme } from "../item-arme.js"; | ||||
| @@ -15,6 +15,7 @@ import { StatusEffects } from "../settings/status-effects.js"; | ||||
| import { Targets } from "../targets.js"; | ||||
| import { RdDConfirm } from "../rdd-confirm.js"; | ||||
| import { RdDCarac } from "../rdd-carac.js"; | ||||
| import { RdDRollResult } from "../rdd-roll-result.js"; | ||||
|  | ||||
| import { ChatUtility } from "../chat-utility.js"; | ||||
| import { DialogValidationEncaissement } from "../dialog-validation-encaissement.js"; | ||||
| @@ -22,6 +23,7 @@ import { RdDCombat } from "../rdd-combat.js"; | ||||
| import { RdDEmpoignade } from "../rdd-empoignade.js"; | ||||
| import { RdDPossession } from "../rdd-possession.js"; | ||||
| import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, POSSESSION_SANS_DRACONIC } from "../item/base-items.js"; | ||||
| import { RollDataAjustements } from "../rolldata-ajustements.js"; | ||||
|  | ||||
| /** | ||||
|  * Classe de base pour les acteurs disposant de rêve (donc, pas des objets) | ||||
| @@ -267,32 +269,70 @@ export class RdDBaseActorReve extends RdDBaseActor { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async openRollDialog({ name, label, template, rollData, callbackAction }) { | ||||
|   async openRollDialog({ name, label, template, rollData, callbacks }) { | ||||
|     const dialog = await RdDRoll.create(this, rollData, | ||||
|       { html: template, close: async html => await this._onCloseRollDialog(html) }, | ||||
|       { | ||||
|         name: name, | ||||
|         label: label, | ||||
|         callbacks: [ | ||||
|           this.createCallbackExperience(), | ||||
|           this.createCallbackAppelAuMoral(), | ||||
|           { action: callbackAction } | ||||
|         ] | ||||
|       }); | ||||
|     dialog.render(true); | ||||
|       { name: name, label: label, callbacks: [this.createCallbackExperience(), this.createCallbackAppelAuMoral()].concat(callbacks) }) | ||||
|     dialog.render(true) | ||||
|     return dialog | ||||
|   } | ||||
|  | ||||
|   createEmptyCallback() { | ||||
|     return { | ||||
|       condition: r => false, | ||||
|       action: r => { } | ||||
|     }; | ||||
|   } | ||||
|   createCallbackExperience() { return this.createEmptyCallback(); } | ||||
|   createCallbackAppelAuMoral() { return this.createEmptyCallback(); } | ||||
|   createCallbackExperience() { return { action: r => { } } } | ||||
|   createCallbackAppelAuMoral() { return { action: r => { } } } | ||||
|  | ||||
|   async _onCloseRollDialog(html) { } | ||||
|  | ||||
|   async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) { | ||||
|     RdDEmpoignade.checkEmpoignadeEnCours(this) | ||||
|     const competence = this.getCompetence(compName); | ||||
|     await this.openRollDialog({ | ||||
|       name: 'jet-competence', | ||||
|       label: competence ? 'Jet ' + Grammar.apostrophe('de', competence.name) : `Jet sans compétence (${compName})`, | ||||
|       template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs', | ||||
|       rollData: { | ||||
|         alias: this.getAlias(), | ||||
|         carac: this.system.carac, | ||||
|         selectedCarac: this.getCaracByName(caracName), | ||||
|         selectedCaracName: caracName, | ||||
|         diffLibre: diff, | ||||
|         competence: competence, | ||||
|         show: { title: options?.title ?? '' } | ||||
|       }, | ||||
|       callbacks: [async r => this.$onRollCompetence(r, options)] | ||||
|     }); | ||||
|   } | ||||
|   /** | ||||
|    * Méthode pour faire un jet prédéterminer sans ouvrir la fenêtre de dialogue | ||||
|    * @param {*} caracName code ou label de la caractéristique. On peut utiliser 'intel' pour Intellect. | ||||
|    * @param {*} compName nom de compétence ou nom abrégé. | ||||
|    * @param {*} diff difficulté (0 si undefined) | ||||
|    * @param {*} options | ||||
|    * @returns le jet effectué | ||||
|    */ | ||||
|   async doRollCaracCompetence(caracName, compName, diff, options = { title: "" }) { | ||||
|     const carac = this.getCaracByName(caracName); | ||||
|     if (!carac) { | ||||
|       ui.notifications.warn(`${this.name} n'a pas de caractéristique correspondant à ${caracName}`) | ||||
|       return | ||||
|     } | ||||
|     const competence = this.getCompetence(compName); | ||||
|     let rollData = { | ||||
|       alias: this.getAlias(), | ||||
|       caracValue: Number(carac.value), | ||||
|       selectedCarac: carac, | ||||
|       competence: competence, | ||||
|       diffLibre: diff ?? 0, | ||||
|       show: { title: options?.title ?? '' } | ||||
|     } | ||||
|     RollDataAjustements.calcul(rollData, this); | ||||
|     await RdDResolutionTable.rollData(rollData); | ||||
|     this.gererExperience(rollData); | ||||
|     await RdDResolutionTable.displayRollData(rollData, this) | ||||
|     return rollData.rolled; | ||||
|   } | ||||
|  | ||||
|   gererExperience(rollData) { } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async roll() { | ||||
|     RdDEmpoignade.checkEmpoignadeEnCours(this) | ||||
| @@ -301,51 +341,56 @@ export class RdDBaseActorReve extends RdDBaseActor { | ||||
|     const selectedCaracName = ['apparence', 'perception', 'force', 'reve'].find(it => carac[it] != undefined) | ||||
|  | ||||
|     await this.openRollDialog({ | ||||
|       name: `jet-${this.id}`, | ||||
|       label: `Jet de ${this.getAlias()}`, | ||||
|       template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll.html', | ||||
|       rollData: { | ||||
|         alias: this.getAlias(), | ||||
|         carac: carac, | ||||
|         selectedCarac: carac[selectedCaracName], | ||||
|         selectedCaracName: selectedCaracName, | ||||
|         competences: this.itemTypes['competence'] | ||||
|       }, | ||||
|       callbackAction: r => this.$onRollCaracResult(r) | ||||
|     }); | ||||
|       callbacks: [{ action: r => this.$onRollCaracResult(r) }] | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async rollCarac(caracName, jetResistance = undefined) { | ||||
|   async rollCarac(caracName, options = {}) { | ||||
|     if (Grammar.equalsInsensitive(caracName, 'taille')) { | ||||
|       return | ||||
|     } | ||||
|     foundry.utils.mergeObject(options, { resistance: false, diff: 0 }, { overwrite: false }) | ||||
|     RdDEmpoignade.checkEmpoignadeEnCours(this) | ||||
|     let selectedCarac = this.getCaracByName(caracName) | ||||
|     console.log("selectedCarac", selectedCarac) | ||||
|     const title = 'Jet ' + Grammar.apostrophe('de', selectedCarac.label); | ||||
|     const jetResistance = options.resistance ? caracName : undefined; | ||||
|     await this.openRollDialog({ | ||||
|       name: 'jet-' + caracName, | ||||
|       label: 'Jet ' + Grammar.apostrophe('de', selectedCarac.label), | ||||
|       template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html', | ||||
|       label: title, | ||||
|       template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.hbs', | ||||
|       rollData: { | ||||
|         alias: this.getAlias(), | ||||
|         selectedCarac: selectedCarac, | ||||
|         competences: this.itemTypes['competence'], | ||||
|         jetResistance: jetResistance ? caracName : undefined | ||||
|         diffLibre: options.diff ?? 0, | ||||
|         jetResistance: jetResistance | ||||
|       }, | ||||
|       callbackAction: r => this.$onRollCaracResult(r) | ||||
|       callbacks: [{ action: r => this.$onRollCaracResult(r) }] | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async $onRollCaracResult(rollData) { | ||||
|     // Final chat message | ||||
|     await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-general.html'); | ||||
|     await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-general.hbs'); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) { | ||||
|     RdDEmpoignade.checkEmpoignadeEnCours(this) | ||||
|     const competence = this.getCompetence(idOrName); | ||||
|     let rollData = { carac: this.system.carac, competence: competence, arme: options.arme } | ||||
|     let rollData = { | ||||
|       carac: this.system.carac, | ||||
|       competence: competence, | ||||
|       arme: options.arme | ||||
|     } | ||||
|     if (competence.type == ITEM_TYPES.competencecreature) { | ||||
|       const token = RdDUtility.getSelectedToken(this) | ||||
|       const arme = RdDItemCompetenceCreature.armeCreature(competence) | ||||
| @@ -363,18 +408,18 @@ export class RdDBaseActorReve extends RdDBaseActor { | ||||
|       // Transformer la competence de créature | ||||
|       RdDItemCompetenceCreature.setRollDataCreature(rollData) | ||||
|     } | ||||
|  | ||||
|     const dialogLabel = 'Jet ' + Grammar.apostrophe('de', competence.name); | ||||
|     await this.openRollDialog({ | ||||
|       name: 'jet-competence', | ||||
|       label: 'Jet ' + Grammar.apostrophe('de', competence.name), | ||||
|       template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html', | ||||
|       label: dialogLabel, | ||||
|       template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs', | ||||
|       rollData: rollData, | ||||
|       callbackAction: r => this.$onRollCompetence(r, options) | ||||
|       callbacks: [{ action: r => this.$onRollCompetence(r, options) }] | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   async $onRollCompetence(rollData, options) { | ||||
|     await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-competence.html') | ||||
|     await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-competence.hbs') | ||||
|     if (options?.onRollAutomate) { | ||||
|       options.onRollAutomate(rollData); | ||||
|     } | ||||
| @@ -474,7 +519,7 @@ export class RdDBaseActorReve extends RdDBaseActor { | ||||
|     await ChatUtility.createChatWithRollMode( | ||||
|       { | ||||
|         roll: encaissement.roll, | ||||
|         content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html', encaissement) | ||||
|         content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.hbs', encaissement) | ||||
|       }, | ||||
|       this | ||||
|     ) | ||||
| @@ -484,7 +529,7 @@ export class RdDBaseActorReve extends RdDBaseActor { | ||||
|       encaissement.isGM = true | ||||
|       ChatMessage.create({ | ||||
|         whisper: ChatUtility.getGMs(), | ||||
|         content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.html', encaissement) | ||||
|         content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.hbs', encaissement) | ||||
|       }); | ||||
|     } | ||||
|   } | ||||
| @@ -509,10 +554,8 @@ export class RdDBaseActorReve extends RdDBaseActor { | ||||
|       await entite.setEntiteReveAccordee(this); | ||||
|     } | ||||
|  | ||||
|     await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-accorder-cauchemar.html'); | ||||
|     if (rolled.isPart) { | ||||
|       await this.appliquerAjoutExperience(rollData, true); | ||||
|     } | ||||
|     await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-accorder-cauchemar.hbs'); | ||||
|     await this.appliquerAjoutExperience(rollData, true); | ||||
|     return rolled.isSuccess; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -17,20 +17,20 @@ export class RdDBaseActorSangSheet extends RdDBaseActorReveSheet { | ||||
|     // Everything below here is only needed if the sheet is editable | ||||
|     if (!this.options.editable) return; | ||||
|  | ||||
|     this.html.find('.creer-blessure-legere').click(async event => RdDItemBlessure.createBlessure(this.actor, 2)); | ||||
|     this.html.find('.creer-blessure-grave').click(async event => RdDItemBlessure.createBlessure(this.actor, 4)); | ||||
|     this.html.find('.creer-blessure-critique').click(async event => RdDItemBlessure.createBlessure(this.actor, 6)); | ||||
|     this.html.find('.creer-blessure-legere').click(async event => await RdDItemBlessure.createBlessure(this.actor, 2)); | ||||
|     this.html.find('.creer-blessure-grave').click(async event => await RdDItemBlessure.createBlessure(this.actor, 4)); | ||||
|     this.html.find('.creer-blessure-critique').click(async event => await RdDItemBlessure.createBlessure(this.actor, 6)); | ||||
|  | ||||
|     this.html.find('.subir-blessure-contusion').click(async event => RdDItemBlessure.applyFullBlessure(this.actor, 0)); | ||||
|     this.html.find('.subir-blessure-legere').click(async event => RdDItemBlessure.applyFullBlessure(this.actor, 2)); | ||||
|     this.html.find('.subir-blessure-grave').click(async event => RdDItemBlessure.applyFullBlessure(this.actor, 4)); | ||||
|     this.html.find('.subir-blessure-critique').click(async event => RdDItemBlessure.applyFullBlessure(this.actor, 6)); | ||||
|     this.html.find('.subir-blessure-contusion').click(async event => await RdDItemBlessure.applyFullBlessure(this.actor, 0)); | ||||
|     this.html.find('.subir-blessure-legere').click(async event => await RdDItemBlessure.applyFullBlessure(this.actor, 2)); | ||||
|     this.html.find('.subir-blessure-grave').click(async event => await RdDItemBlessure.applyFullBlessure(this.actor, 4)); | ||||
|     this.html.find('.subir-blessure-critique').click(async event => await RdDItemBlessure.applyFullBlessure(this.actor, 6)); | ||||
|  | ||||
|     this.html.find('.jet-vie').click(async event => this.actor.jetDeVie()) | ||||
|     this.html.find('.jet-vie').click(async event => await this.actor.jetDeVie()) | ||||
|     this.html.find('.jet-endurance').click(async event => await this.jetEndurance()) | ||||
|  | ||||
|     this.html.find('.vie-plus').click(async event => this.actor.santeIncDec("vie", 1)) | ||||
|     this.html.find('.vie-moins').click(async event => this.actor.santeIncDec("vie", -1)) | ||||
|     this.html.find('.vie-plus').click(async event => await this.actor.santeIncDec("vie", 1)) | ||||
|     this.html.find('.vie-moins').click(async event => await this.actor.santeIncDec("vie", -1)) | ||||
|   } | ||||
|  | ||||
|   async jetEndurance() { | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| import { RdDUtility } from "../rdd-utility.js"; | ||||
| import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; | ||||
| import { STATUSES } from "../settings/status-effects.js"; | ||||
| import { ITEM_TYPES } from "../item.js"; | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { RdDBaseActorReve } from "./base-actor-reve.js"; | ||||
| import { RdDDice } from "../rdd-dice.js"; | ||||
| import { RdDItemBlessure } from "../item/blessure.js"; | ||||
| @@ -39,7 +39,12 @@ export class RdDBaseActorSang extends RdDBaseActorReve { | ||||
|     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 } | ||||
|  | ||||
|   malusFatigue() { | ||||
|   | ||||
| @@ -3,8 +3,11 @@ import { Misc } from "../misc.js"; | ||||
| import { DialogSplitItem } from "../dialog-split-item.js"; | ||||
| import { RdDSheetUtility } from "../rdd-sheet-utility.js"; | ||||
| import { Monnaie } from "../item-monnaie.js"; | ||||
| import { RdDItem, ITEM_TYPES } from "../item.js"; | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { RdDItem } from "../item.js"; | ||||
| import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; | ||||
| import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js"; | ||||
| import { ItemAction } from "../item/item-actions.js"; | ||||
|  | ||||
| /* -------------------------------------------- */ | ||||
| /** | ||||
| @@ -25,7 +28,7 @@ export class RdDBaseActorSheet extends ActorSheet { | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async getData() { | ||||
|     Monnaie.validerMonnaies(this.actor.itemTypes['monnaie']); | ||||
|     Monnaie.validerMonnaies(this.actor) | ||||
|  | ||||
|     this.actor.computeEtatGeneral(); | ||||
|     let formData = { | ||||
| @@ -35,13 +38,13 @@ export class RdDBaseActorSheet extends ActorSheet { | ||||
|       img: this.actor.img, | ||||
|       name: this.actor.name, | ||||
|       system: this.actor.system, | ||||
|       description: await TextEditor.enrichHTML(this.actor.system.description, { async: true }), | ||||
|       notesmj: await TextEditor.enrichHTML(this.actor.system.notesmj, { async: true }), | ||||
|       description: await RdDTextEditor.enrichHTML(this.actor.system.description, this.actor), | ||||
|       notesmj: await RdDTextEditor.enrichHTML(this.actor.system.notesmj, this.actor), | ||||
|       options: RdDSheetUtility.mergeDocumentRights(this.options, this.actor, this.isEditable), | ||||
|       effects: this.actor.effects | ||||
|     } | ||||
|  | ||||
|     RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes); | ||||
|     RdDUtility.filterItemsPerTypeForSheet(formData, this.actor.itemTypes); | ||||
|     formData.calc = { | ||||
|       fortune: Monnaie.toSolsDeniers(this.actor.getFortune()), | ||||
|       prixTotalEquipement: this.actor.computePrixTotalEquipement(), | ||||
| @@ -53,6 +56,7 @@ export class RdDBaseActorSheet extends ActorSheet { | ||||
|     formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs); | ||||
|     formData.competences.filter(it => it.type == ITEM_TYPES.competencecreature) | ||||
|       .forEach(it => it.isdommages = RdDItemCompetenceCreature.isDommages(it)) | ||||
|  | ||||
|     return formData; | ||||
|   } | ||||
|  | ||||
| @@ -76,109 +80,51 @@ export class RdDBaseActorSheet extends ActorSheet { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static filterItemsPerTypeForSheet(formData, itemTypes) { | ||||
|     formData.blessures = Misc.arrayOrEmpty(itemTypes['blessure']); | ||||
|     formData.recettescuisine = Misc.arrayOrEmpty(itemTypes['recettecuisine']); | ||||
|     formData.recettesAlchimiques = Misc.arrayOrEmpty(itemTypes['recettealchimique']); | ||||
|     formData.maladies = Misc.arrayOrEmpty(itemTypes['maladie']); | ||||
|     formData.poisons = Misc.arrayOrEmpty(itemTypes['poison']); | ||||
|     formData.possessions = Misc.arrayOrEmpty(itemTypes['possession']); | ||||
|     formData.maladiesPoisons = formData.maladies.concat(formData.poisons); | ||||
|     formData.competences = (itemTypes['competence'] ?? []).concat(itemTypes['competencecreature'] ?? []); | ||||
|     formData.sortsReserve = Misc.arrayOrEmpty(itemTypes['sortreserve']); | ||||
|  | ||||
|     formData.sorts = Misc.arrayOrEmpty(itemTypes['sort']); | ||||
|     formData.rencontres = Misc.arrayOrEmpty(itemTypes['rencontre']); | ||||
|     formData.casestmr = Misc.arrayOrEmpty(itemTypes['casetmr']); | ||||
|     formData.signesdraconiques = Misc.arrayOrEmpty(itemTypes['signedraconique']); | ||||
|     formData.queues = Misc.arrayOrEmpty(itemTypes['queue']); | ||||
|     formData.souffles = Misc.arrayOrEmpty(itemTypes['souffle']); | ||||
|     formData.ombres = Misc.arrayOrEmpty(itemTypes['ombre']); | ||||
|     formData.tetes = Misc.arrayOrEmpty(itemTypes['tete']); | ||||
|     formData.taches = Misc.arrayOrEmpty(itemTypes['tache']); | ||||
|     formData.meditations = Misc.arrayOrEmpty(itemTypes['meditation']); | ||||
|     formData.chants = Misc.arrayOrEmpty(itemTypes['chant']); | ||||
|     formData.danses = Misc.arrayOrEmpty(itemTypes['danse']); | ||||
|     formData.musiques = Misc.arrayOrEmpty(itemTypes['musique']); | ||||
|     formData.oeuvres = Misc.arrayOrEmpty(itemTypes['oeuvre']); | ||||
|     formData.jeux = Misc.arrayOrEmpty(itemTypes['jeu']); | ||||
|  | ||||
|     formData.services = Misc.arrayOrEmpty(itemTypes['service']); | ||||
|     formData.conteneurs = Misc.arrayOrEmpty(itemTypes['conteneur']); | ||||
|     formData.materiel = Misc.arrayOrEmpty(itemTypes['objet']); | ||||
|     formData.armes = Misc.arrayOrEmpty(itemTypes['arme']); | ||||
|     formData.armures = Misc.arrayOrEmpty(itemTypes['armure']); | ||||
|     formData.munitions = Misc.arrayOrEmpty(itemTypes['munition']); | ||||
|     formData.livres = Misc.arrayOrEmpty(itemTypes['livre']); | ||||
|     formData.potions = Misc.arrayOrEmpty(itemTypes['potion']); | ||||
|     formData.plantes = Misc.arrayOrEmpty(itemTypes['plante']); | ||||
|     formData.ingredients = Misc.arrayOrEmpty(itemTypes['ingredient']); | ||||
|     formData.faunes = Misc.arrayOrEmpty(itemTypes['faune']); | ||||
|     formData.herbes = Misc.arrayOrEmpty(itemTypes['herbe']); | ||||
|     formData.nourritureboissons = Misc.arrayOrEmpty(itemTypes['nourritureboisson']); | ||||
|     formData.gemmes = Misc.arrayOrEmpty(itemTypes['gemme']); | ||||
|     formData.monnaies = Misc.arrayOrEmpty(itemTypes['monnaie']).sort(Monnaie.triValeurEntiere()); | ||||
|     formData.objets = Misc.arrayOrEmpty(itemTypes['objet']) | ||||
|  | ||||
|     formData.inventaires = RdDItem.getItemTypesInventaire('all') | ||||
|       .map(t => Misc.arrayOrEmpty(itemTypes[t])) | ||||
|       .reduce((a, b) => a.concat(b), []) | ||||
|       .sort(Misc.ascending(it => it.name)); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */  /** @override */ | ||||
|   activateListeners(html) { | ||||
|     super.activateListeners(html); | ||||
|     this.html = html; | ||||
|  | ||||
|     this.html.find('.actionItem').click(async event => await ItemAction.onActionItem(event, this.actor, this.options)) | ||||
|     this.html.find('.item-edit').click(async event => await this.itemActionEdit(event)) | ||||
|     this.html.find('.conteneur-name a').click(async event => { | ||||
|       RdDUtility.toggleAfficheContenu(this.getItemId(event)); | ||||
|       this.render(true); | ||||
|     }); | ||||
|     this.html.find('.actor-montrer').click(async event => this.actor.postActorToChat()); | ||||
|     this.html.find('.item-edit').click(async event => this.getItem(event)?.sheet.render(true)) | ||||
|     this.html.find('.item-montrer').click(async event => this.getItem(event)?.postItemToChat()); | ||||
|       RdDUtility.toggleAfficheContenu(this.getItemId(event)) | ||||
|       this.render(true) | ||||
|     }) | ||||
|  | ||||
|     this.html.find('.actor-montrer').click(async event => await this.actor.postActorToChat()); | ||||
|  | ||||
|     this.html.find('.recherche') | ||||
|       .each((index, field) => { | ||||
|         this._rechercheSelectArea(field); | ||||
|       }) | ||||
|       .keyup(async event => this._rechercherKeyup(event)) | ||||
|       .change(async event => this._rechercherKeyup(event)); | ||||
|     this.html.find('.recherche').prop("disabled", false); | ||||
|       .change(async event => this._rechercherKeyup(event)) | ||||
|  | ||||
|     this.html.find('.recherche').prop("disabled", false) | ||||
|  | ||||
|     // Everything below here is only needed if the sheet is editable | ||||
|     if (!this.options.editable) return; | ||||
|  | ||||
|     this.html.find('.item-action').click(async event => { | ||||
|       const item = RdDSheetUtility.getItem(event, this.actor); | ||||
|       item?.actionPrincipale(this.actor, async () => this.render()) | ||||
|     }); | ||||
|     this.html.find('.item-equip-armure').click(async event => await this.actor.equiperObjet(this.getItem(event))) | ||||
|     this.html.find('.item-delete').click(async event => await RdDUtility.confirmActorItemDelete(this.getItem(event), this.actor)); | ||||
|     this.html.find('.item-quantite-plus').click(async event => await this.actor.itemQuantiteIncDec(this.getItemId(event), 1)); | ||||
|     this.html.find('.item-quantite-moins').click(async event => await this.actor.itemQuantiteIncDec(this.getItemId(event), -1)); | ||||
|  | ||||
|  | ||||
|     this.html.find('.item-split').click(async event => { | ||||
|       const item = this.getItem(event); | ||||
|       RdDSheetUtility.splitItem(item, this.actor); | ||||
|     }); | ||||
|     this.html.find('.item-quantite-plus').click(async event => this.actor.itemQuantiteIncDec(this.getItemId(event), 1)); | ||||
|     this.html.find('.item-quantite-moins').click(async event => this.actor.itemQuantiteIncDec(this.getItemId(event), -1)); | ||||
|     this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, this.getItem(event))); | ||||
|     this.html.find('.item-vendre').click(async event => this.vendre(this.getItem(event))); | ||||
|  | ||||
|     this.html.find('.creer-un-objet').click(async event => { | ||||
|       this.selectObjetTypeToCreate(); | ||||
|     }); | ||||
|     this.html.find('.nettoyer-conteneurs').click(async event => { | ||||
|       this.actor.nettoyerConteneurs(); | ||||
|     }); | ||||
|     this.html.find('.creer-un-objet').click(async event => await this.selectObjetTypeToCreate()) | ||||
|     this.html.find('.nettoyer-conteneurs').click(async event => await this.actor.nettoyerConteneurs()) | ||||
|  | ||||
|     this.html.find('.vue-detaillee').click(async event => { | ||||
|       this.options.vueDetaillee = !this.options.vueDetaillee; | ||||
|       this.render(true); | ||||
|       this.options.vueDetaillee = !this.options.vueDetaillee | ||||
|       this.render(true) | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   itemActionEdit(event) { | ||||
|     const item = this.getItem(event); | ||||
|     return item?.sheet.render(true); | ||||
|   } | ||||
|  | ||||
|   _rechercherKeyup(event) { | ||||
|     const currentTarget = event.currentTarget; | ||||
|     const nouvelleRecherche = this._optionRecherche(currentTarget); | ||||
| @@ -245,7 +191,7 @@ export class RdDBaseActorSheet extends ActorSheet { | ||||
|   /* -------------------------------------------- */ | ||||
|   async selectObjetTypeToCreate() { | ||||
|     let types = this.getTypesInventaire().sort(Misc.ascending(type => Misc.typeName('Item', type))); | ||||
|     let content = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`; | ||||
|     let content = `<span class="generic-label">Selectionnez le type d'équipement</span><select class="item-type">`; | ||||
|     for (let typeName of types) { | ||||
|       content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>` | ||||
|     } | ||||
|   | ||||
| @@ -3,7 +3,7 @@ import { ChatUtility } from "../chat-utility.js"; | ||||
| import { SYSTEM_SOCKET_ID } from "../constants.js"; | ||||
| import { Grammar } from "../grammar.js"; | ||||
| import { Monnaie } from "../item-monnaie.js"; | ||||
| import { ITEM_TYPES } from "../item.js"; | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { Misc } from "../misc.js"; | ||||
| import { RdDAudio } from "../rdd-audio.js"; | ||||
| import { RdDConfirm } from "../rdd-confirm.js"; | ||||
| @@ -81,7 +81,6 @@ export class RdDBaseActor extends Actor { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|  | ||||
|   static getRealActor(actorId, tokenId) { | ||||
|     if (tokenId) { | ||||
|       let token = canvas.tokens.get(tokenId) | ||||
| @@ -161,8 +160,11 @@ export class RdDBaseActor extends Actor { | ||||
|     return RdDBaseActor.$findCaracByName(carac, name); | ||||
|   } | ||||
|  | ||||
|   mapCarac(caracCode) { return caracCode } | ||||
|  | ||||
|   getCaracByName(name) { | ||||
|     switch (Grammar.toLowerCaseNoAccent(name)) { | ||||
|     name = this.mapCarac(Grammar.toLowerCaseNoAccent(name)) | ||||
|     switch (name) { | ||||
|       case 'reve-actuel': case 'reve actuel': | ||||
|         return this.getCaracReveActuel(); | ||||
|       case 'chance-actuelle': case 'chance-actuelle': | ||||
| @@ -242,16 +244,19 @@ export class RdDBaseActor extends Actor { | ||||
|   async onUpdateActor(update, options, actorId) { } | ||||
|   async onDeleteItem(item, options, id) { | ||||
|     if (item.isInventaire()) { | ||||
|       this._removeItemFromConteneur(item) | ||||
|       await this._removeItemFromConteneur(item) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   _removeItemFromConteneur(item) { | ||||
|     this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id)) | ||||
|       .forEach(conteneur => { | ||||
|         const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id); | ||||
|         conteneur.update({ 'system.contenu': nouveauContenu }); | ||||
|       }); | ||||
|   async _removeItemFromConteneur(item) { | ||||
|     const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id)) | ||||
|       .map(conteneur => { | ||||
|         const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id) | ||||
|         return { _id: conteneur.id, 'system.contenu': nouveauContenu } | ||||
|       }) | ||||
|     if (updates.length > 0) { | ||||
|       await this.updateEmbeddedDocuments('Item', updates) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   async onTimeChanging(oldTimestamp, newTimestamp) { | ||||
| @@ -412,7 +417,7 @@ export class RdDBaseActor extends Actor { | ||||
|       user: achat.userId, | ||||
|       speaker: { alias: (acheteur ?? vendeur).getAlias() }, | ||||
|       whisper: ChatUtility.getOwners(this), | ||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.html', chatAchatItem) | ||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-achat-item.hbs', chatAchatItem) | ||||
|     }); | ||||
|  | ||||
|     if (!achat.vente.quantiteIllimite) { | ||||
| @@ -729,31 +734,26 @@ export class RdDBaseActor extends Actor { | ||||
|       name: this.getAlias(), | ||||
|       system: { description: this.system.description } | ||||
|     } | ||||
|     renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.html', chatData) | ||||
|     renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.hbs', chatData) | ||||
|       .then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride))); | ||||
|   } | ||||
|  | ||||
|   actionImpossible(action) { | ||||
|     ui.notifications.info(`${this.getAlias()} ne peut pas faire cette action: ${action}`) | ||||
|  | ||||
|   } | ||||
|  | ||||
|   async jetEthylisme() { this.actionImpossible("jet d'éthylisme") } | ||||
|   async rollAppelChance() { this.actionImpossible("appel à la chance") } | ||||
|   async jetDeMoral() { this.actionImpossible("jet de moral") } | ||||
|  | ||||
|   async actionPrincipale(item, onActionItem = async () => { }) { | ||||
|     switch (item.type) { | ||||
|       case ITEM_TYPES.conteneur: return await item.sheet.render(true); | ||||
|     } | ||||
|     return undefined | ||||
|   } | ||||
|   async resetItemUse() { } | ||||
|   async incDecItemUse(itemId, inc = 1) { } | ||||
|   async incDecItemUse(itemId, shouldIncrease = true) { } | ||||
|   getItemUse(itemId) { return 0; } | ||||
|  | ||||
|   async finDeRound(options = { terminer: false }) { } | ||||
|   isActorCombat() { return false } | ||||
|   getCaracInit(competence) { return 0 } | ||||
|  | ||||
|   listActionsCombat() { return [] } | ||||
|   listActionsPossessions() { | ||||
|     return this.itemTypes[ITEM_TYPES.possession] | ||||
|   | ||||
| @@ -12,7 +12,7 @@ export class RdDCommerceSheet extends RdDBaseActorSheet { | ||||
|   /** @override */ | ||||
|   static get defaultOptions() { | ||||
|     return foundry.utils.mergeObject(super.defaultOptions, { | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.html", | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.hbs", | ||||
|       width: 600, height: 720, | ||||
|       tabs: [] | ||||
|     }, { inplace: false }) | ||||
| @@ -45,6 +45,7 @@ export class RdDCommerceSheet extends RdDBaseActorSheet { | ||||
|     super.activateListeners(html); | ||||
|  | ||||
|     this.html.find('a.item-acheter').click(async event => await this.vente(this.getItem(event))); | ||||
|     this.html.find('.service-acheter').click(async event => await this.vente(this.getItem(event))); | ||||
|  | ||||
|     if (!this.options.editable) return; | ||||
|  | ||||
|   | ||||
| @@ -10,7 +10,7 @@ export class RdDCreatureSheet extends RdDBaseActorSangSheet { | ||||
|   /** @override */ | ||||
|   static get defaultOptions() { | ||||
|     return foundry.utils.mergeObject(RdDBaseActorSangSheet.defaultOptions, { | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html", | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.hbs", | ||||
|       width: 640, height: 720 | ||||
|     }, { inplace: false }) | ||||
|   } | ||||
| @@ -26,15 +26,15 @@ export class RdDCreatureSheet extends RdDBaseActorSangSheet { | ||||
|     // On competence change | ||||
|     this.html.find('.creature-carac').change(async event => { | ||||
|       let compName = event.currentTarget.attributes.compname.value; | ||||
|       this.actor.updateCreatureCompetence(compName, "carac_value", parseInt(event.target.value)); | ||||
|       await this.actor.updateCreatureCompetence(compName, "carac_value", parseInt(event.target.value)); | ||||
|     }); | ||||
|     this.html.find('.creature-niveau').change(async event => { | ||||
|       let compName = event.currentTarget.attributes.compname.value; | ||||
|       this.actor.updateCreatureCompetence(compName, "niveau", parseInt(event.target.value)); | ||||
|       await this.actor.updateCreatureCompetence(compName, "niveau", parseInt(event.target.value)); | ||||
|     }); | ||||
|     this.html.find('.creature-dommages').change(async event => { | ||||
|       let compName = event.currentTarget.attributes.compname.value; | ||||
|       this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value)); | ||||
|       await this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value)); | ||||
|     }); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,6 @@ | ||||
| import { ITEM_TYPES } from "../item.js"; | ||||
| import { Grammar } from "../grammar.js"; | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { LIST_CARAC_AUTRES } from "../rdd-carac.js"; | ||||
| import { RdDBaseActorSang } from "./base-actor-sang.js"; | ||||
|  | ||||
| export class RdDCreature extends RdDBaseActorSang { | ||||
| @@ -32,4 +34,16 @@ export class RdDCreature extends RdDBaseActorSang { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   mapCarac(caracCode) { | ||||
|     switch (caracCode) { | ||||
|       case 'vue': case 'ouie': case 'odoratgout': case 'empathie': case 'perception': | ||||
|         return 'perception' | ||||
|       case 'agilite': | ||||
|         return 'force' | ||||
|       case 'force': case 'constitution': case 'taille': case 'reve': case 'volonte': | ||||
|         return caracCode | ||||
|     } | ||||
|     return undefined | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -8,7 +8,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet { | ||||
|   /** @override */ | ||||
|   static get defaultOptions() { | ||||
|     return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, { | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html", | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.hbs", | ||||
|       width: 640, height: 720, | ||||
|     }, { inplace: false }) | ||||
|   } | ||||
| @@ -33,15 +33,15 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet { | ||||
|     // On competence change | ||||
|     this.html.find('.creature-carac').change(async event => { | ||||
|       let compName = event.currentTarget.attributes.compname.value; | ||||
|       this.actor.updateCreatureCompetence(compName, "carac_value", parseInt(event.target.value)); | ||||
|       await this.actor.updateCreatureCompetence(compName, "carac_value", parseInt(event.target.value)); | ||||
|     }); | ||||
|     this.html.find('.creature-dommages').change(async event => { | ||||
|       let compName = event.currentTarget.attributes.compname.value; | ||||
|       this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value)); | ||||
|       await this.actor.updateCreatureCompetence(compName, "dommages", parseInt(event.target.value)); | ||||
|     }) | ||||
|  | ||||
|     this.html.find('.resonance-add').click(async event => | ||||
|       DialogSelect.select({ | ||||
|       await DialogSelect.select({ | ||||
|         label: "Choisir un acteur à accorder", | ||||
|         list: game.actors.filter(it => it.isPersonnage() && it.prototypeToken.actorLink) | ||||
|       }, | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js"; | ||||
| import { ITEM_TYPES } from "../item.js"; | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { Misc } from "../misc.js"; | ||||
| import { RdDCarac } from "../rdd-carac.js"; | ||||
| import { RdDEncaisser } from "../rdd-roll-encaisser.js"; | ||||
| @@ -117,4 +117,14 @@ export class RdDEntite extends RdDBaseActorReve { | ||||
|       super.setEntiteReveAccordee(actor) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   mapCarac(caracCode) { | ||||
|     switch (caracCode) { | ||||
|       case 'taille': | ||||
|       case 'reve': | ||||
|         return caracCode | ||||
|     } | ||||
|     return 'reve' | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,8 +6,8 @@ import { ExportScriptarium } from "./export-scriptarium.js"; | ||||
| import { CATEGORIES_COMPETENCES, CATEGORIES_DRACONIC, Mapping } from "./mapping.js"; | ||||
|  | ||||
| export class RdDActorExportSheet extends RdDActorSheet { | ||||
|   static async init() { | ||||
|     await loadTemplates([ | ||||
|   static init() { | ||||
|     loadTemplates([ | ||||
|       "systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs", | ||||
|       "systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/blessure.hbs", | ||||
|       "systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/blessures.hbs", | ||||
| @@ -23,6 +23,7 @@ export class RdDActorExportSheet extends RdDActorSheet { | ||||
|     ]) | ||||
|     Actors.registerSheet(SYSTEM_RDD, RdDActorExportSheet, { types: ["personnage"], makeDefault: false, label: "Feuille simplifiée" }) | ||||
|   } | ||||
|  | ||||
|   static get defaultOptions() { | ||||
|     return foundry.utils.mergeObject(RdDActorSheet.defaultOptions, { | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/actor-encart-sheet.hbs", | ||||
| @@ -103,13 +104,12 @@ export class RdDActorExportSheet extends RdDActorSheet { | ||||
|     this.html.find('.click-blessure-add').click(async event => | ||||
|       await this.actor.ajouterBlessure({ | ||||
|         gravite: this.html.find(event.currentTarget).data('gravite') | ||||
|         // event.currentTarget.attributes['data-gravite'].value | ||||
|       }) | ||||
|     ) | ||||
|     this.html.find('.button-export').click(async event => { | ||||
|     this.html.find('.button-export').click(async event => await | ||||
|       ExportScriptarium.INSTANCE.exportActors([this.actor], | ||||
|         `${this.actor.uuid}-${this.actor.name}` | ||||
|       ) | ||||
|     }) | ||||
|     ) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,4 +1,4 @@ | ||||
| import { ACTOR_TYPES } from "../../item.js" | ||||
| import { ACTOR_TYPES } from "../../constants.js" | ||||
| import { Misc } from "../../misc.js" | ||||
| import { EXPORT_CSV_SCRIPTARIUM, OptionsAvancees } from "../../settings/options-avancees.js" | ||||
| import { Mapping } from "./mapping.js" | ||||
|   | ||||
| @@ -2,7 +2,7 @@ import { Grammar } from "../../grammar.js" | ||||
| import { RdDItemArme } from "../../item-arme.js" | ||||
| import { RdDItemCompetence } from "../../item-competence.js" | ||||
| import { RdDItemSort } from "../../item-sort.js" | ||||
| import { ITEM_TYPES } from "../../item.js" | ||||
| import { ITEM_TYPES } from "../../constants.js" | ||||
| import { Misc } from "../../misc.js" | ||||
| import { RdDTimestamp } from "../../time/rdd-timestamp.js" | ||||
| import { RdDBonus } from "../../rdd-bonus.js" | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export class RdDActorVehiculeSheet extends RdDBaseActorSheet { | ||||
|   /** @override */ | ||||
|   static get defaultOptions() { | ||||
|     return foundry.utils.mergeObject(RdDBaseActorSheet.defaultOptions, { | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html", | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.hbs", | ||||
|       width: 640, height: 720, | ||||
|     }, { inplace: false }) | ||||
|   } | ||||
| @@ -32,18 +32,10 @@ export class RdDActorVehiculeSheet extends RdDBaseActorSheet { | ||||
|     super.activateListeners(html); | ||||
|     if (!this.options.editable) return; | ||||
|  | ||||
|     this.html.find('.resistance-moins').click(async event => { | ||||
|       this.actor.vehicleIncDec("resistance", -1); | ||||
|     }); | ||||
|     this.html.find('.resistance-plus').click(async event => { | ||||
|       this.actor.vehicleIncDec("resistance", 1); | ||||
|     }); | ||||
|     this.html.find('.structure-moins').click(async event => { | ||||
|       this.actor.vehicleIncDec("structure", -1); | ||||
|     }); | ||||
|     this.html.find('.structure-plus').click(async event => { | ||||
|       this.actor.vehicleIncDec("structure", 1); | ||||
|     }); | ||||
|     this.html.find('.resistance-moins').click(async event => await this.actor.vehicleIncDec("resistance", -1)) | ||||
|     this.html.find('.resistance-plus').click(async event => await this.actor.vehicleIncDec("resistance", 1)) | ||||
|     this.html.find('.structure-moins').click(async event => await this.actor.vehicleIncDec("structure", -1)) | ||||
|     this.html.find('.structure-plus').click(async event => await this.actor.vehicleIncDec("structure", 1)) | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -6,7 +6,7 @@ import { Grammar } from "../grammar.js"; | ||||
| import { Misc } from "../misc.js"; | ||||
| import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js"; | ||||
| import { RdDItemTete } from "../item/tete.js"; | ||||
| import { ITEM_TYPES } from "../item.js"; | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
|  | ||||
| const WHITESPACES = "\\s+" | ||||
| const NUMERIC = "[\\+\\-]?\\d+" | ||||
| @@ -34,7 +34,6 @@ const XREGEXP_WEAPON_MANIEMENT = "(?<maniement>(" + Misc.join(Object.keys(MANIEM | ||||
|  | ||||
| const XREGEXP_SORT_VOIE = "(?<voies>[OHNT](\\/[OHNT])*)" | ||||
| const XREGEXP_SORT_NAME = "(?<name>[^\\(]+)" | ||||
| // const XREGEXP_SORT_CASE = "(?<coord>([A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+|[A-M]\\d{1,2})+)" | ||||
| const XREGEXP_SORT_CASE = "(?<coord>([A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+|[A-M]\\d{1,2}))" | ||||
|  | ||||
| const XREGEXP_SORT = "(" + XREGEXP_SORT_VOIE | ||||
|   | ||||
							
								
								
									
										78
									
								
								module/apps/rdd-text-roll-editor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								module/apps/rdd-text-roll-editor.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| import "./xregexp-all.js"; | ||||
| import { SystemCompendiums } from "../settings/system-compendiums.js"; | ||||
| import { ACTOR_TYPES } from "../constants.js"; | ||||
| import { TextRollAlchimie } from "./textroll/text-roll-alchimie.js"; | ||||
| import { TextRollCaracCompetence } from "./textroll/text-roll-carac-competence.js"; | ||||
| import { TextRollFormula } from "./textroll/text-roll-formula.js"; | ||||
| import { TextRollManager } from "./textroll/text-roll-formatter.js"; | ||||
|  | ||||
| const TEXT_ROLL_MANAGERS = [ | ||||
|   new TextRollAlchimie(), | ||||
|   new TextRollCaracCompetence(), | ||||
|   new TextRollFormula()] | ||||
|  | ||||
| export class RdDTextEditor { | ||||
|   static registerChatCallbacks(html) { | ||||
|     html.on("click", '.roll-text', async event => await RdDTextEditor.rollText(event)) | ||||
|   } | ||||
|  | ||||
|   static async enrichHTML(text, object, options = {showlink:true}) { | ||||
|     const context = { | ||||
|       text, | ||||
|       object, | ||||
|       options, | ||||
|       competences: await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage), | ||||
|     } | ||||
|  | ||||
|     for (let manager of TEXT_ROLL_MANAGERS) { | ||||
|       context.code = manager.code | ||||
|       context.template = manager.template | ||||
|       context.text = await manager.onReplaceRoll(context); | ||||
|     } | ||||
|  | ||||
|     return await TextEditor.enrichHTML(context.text, { | ||||
|       relativeTo: object, | ||||
|       secrets: object?.isOwner, | ||||
|       async: true | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   static async _applyReplaceAll(manager, context) { | ||||
|     context.code = manager.code | ||||
|     context.template = manager.template | ||||
|     context.text = await manager.onReplaceRoll(context); | ||||
|     return context.text | ||||
|   } | ||||
|  | ||||
|   static getEventElement(event) { | ||||
|     return $(event.currentTarget)?.parents(".roll-text-link"); | ||||
|   } | ||||
|  | ||||
|   static async rollText(event, actor) { | ||||
|     const code = TextRollManager.getNode(event)?.data('code') | ||||
|     const manager = TEXT_ROLL_MANAGERS.find(it => it.code == code) | ||||
|     if (manager) { | ||||
|       await manager.onRollText(event, actor) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static async chatRollText(event) { | ||||
|     const node = TextRollManager.getNode(event); | ||||
|     if (node) { | ||||
|       const code = node.data('code') | ||||
|       const param = node.data('json') | ||||
|       const manager = TEXT_ROLL_MANAGERS.find(it => it.code == code) | ||||
|  | ||||
|       const text = await TextRollManager.createRollText( | ||||
|         { | ||||
|           code, | ||||
|           template: manager.template, | ||||
|           options: { showLink: false } | ||||
|         }, | ||||
|         param) | ||||
|       ChatMessage.create({ | ||||
|         content: text | ||||
|       }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
							
								
								
									
										79
									
								
								module/apps/textroll/text-roll-alchimie.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								module/apps/textroll/text-roll-alchimie.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| import "../xregexp-all.js"; | ||||
| import { ACTOR_TYPES, ITEM_TYPES } from "../../constants.js"; | ||||
| import { RdDCarac } from "../../rdd-carac.js"; | ||||
| import { RdDUtility } from "../../rdd-utility.js"; | ||||
| import { RdDAlchimie } from "../../rdd-alchimie.js"; | ||||
| import { TextRollManager } from "./text-roll-formatter.js"; | ||||
|  | ||||
| const REGEX_ALCHIMIE_TERMES = "(?<termes>([-A-Za-zÀ-ÖØ-öø-ÿ ])+)" | ||||
| 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_MANIP = XRegExp("@" + REGEX_ALCHIMIE_MANIP + "\\{" + REGEX_ALCHIMIE_TERMES + "\\}", 'giu') | ||||
|  | ||||
| /** | ||||
|  * classe pour gérer les jets d'alchimie | ||||
|  */ | ||||
| export class TextRollAlchimie { | ||||
|   get code() { return 'alchimie' } | ||||
|   get template() { return `systems/foundryvtt-reve-de-dragon/templates/apps/textroll/link-text-roll-alchimie.hbs` } | ||||
|  | ||||
|   async onReplaceRoll(context) { | ||||
|     const handler = new AlchimieTextBuilder(context) | ||||
|     return await handler.replaceAll() | ||||
|   } | ||||
|  | ||||
|   async onRollText(event, actor) { | ||||
|     actor = this.getSelectedActor(actor) | ||||
|     if (actor) { | ||||
|       const node = TextRollManager.getNode(event) | ||||
|       const recetteId = node.data('recetteid') | ||||
|       const manip = node.data('manip') | ||||
|       const termes = node.data('termes') | ||||
|       if (recetteId) { | ||||
|         await actor.effectuerTacheAlchimie(recetteId, manip, termes) | ||||
|       } | ||||
|       else { | ||||
|         const carac = RdDCarac.caracDetails(RdDAlchimie.getCaracTache(manip)) | ||||
|         const diff = RdDAlchimie.getDifficulte(termes) | ||||
|         await actor.rollCaracCompetence(carac.code, 'Alchimie', diff) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   getSelectedActor(actor) { | ||||
|     actor = actor ?? RdDUtility.getSelectedActor() | ||||
|     if (actor && actor.type == ACTOR_TYPES.personnage) { | ||||
|       return actor | ||||
|     } | ||||
|     return undefined | ||||
|   } | ||||
| } | ||||
|  | ||||
| class AlchimieTextBuilder { | ||||
|   constructor(context) { | ||||
|     this.context = context | ||||
|   } | ||||
|  | ||||
|   async replaceAll() { | ||||
|     await XRegExp.forEach(this.context.text, XREGEXP_ROLL_ALCHIMIE, async (rollMatch, i) => await this.replaceMatch(rollMatch, i)) | ||||
|     await XRegExp.forEach(this.context.text, XREGEXP_ROLL_ALCHIMIE_MANIP, async (rollMatch, i) => await this.replaceMatch(rollMatch, i)) | ||||
|     return this.context.text | ||||
|   } | ||||
|  | ||||
|   async replaceMatch(rollMatch, i) { | ||||
|     if (rollMatch.termes && rollMatch.manip) { | ||||
|       const manip = rollMatch.manip | ||||
|       const termes = rollMatch.termes | ||||
|       const carac = RdDCarac.caracDetails(RdDAlchimie.getCaracTache(manip)) | ||||
|       const diff = RdDAlchimie.getDifficulte(termes) | ||||
|       const recette = (this.context.object instanceof Item && this.context.object.type == ITEM_TYPES.recettealchimique) ? this.context.object : undefined | ||||
|       const replacement = await TextRollManager.createRollText(this.context, | ||||
|         { | ||||
|           code: this.context.code, | ||||
|           manip, termes, carac, diff, recetteid: recette?.id, | ||||
|         }) | ||||
|       this.context.text = this.context.text.replace(rollMatch[0], replacement); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										98
									
								
								module/apps/textroll/text-roll-carac-competence.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								module/apps/textroll/text-roll-carac-competence.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| import "../xregexp-all.js"; | ||||
| import { RdDCarac } from "../../rdd-carac.js"; | ||||
| import { RdDItemCompetence } from "../../item-competence.js"; | ||||
| import { RdDUtility } from "../../rdd-utility.js"; | ||||
| import { TextRollManager } from "./text-roll-formatter.js"; | ||||
|  | ||||
| const REGECP_CARAC = "(?<carac>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)" | ||||
| const REGEXP_COMP = "(\\/(?<competence>[A-Za-zÀ-ÖØ-öø-ÿ ]+([1-2]?[A-Za-zÀ-ÖØ-öø-ÿ ]+)?))?" | ||||
| const REGEXP_DIFF = "(/(?<diff>[\\+\\-]?\\d+(d\\d+)?))?" | ||||
| const REGEXP_ROLL_CARAC_COMP = REGECP_CARAC + REGEXP_COMP + REGEXP_DIFF | ||||
| const XREGEXP_ROLL_CARAC_COMP = XRegExp("@roll\\[" + REGEXP_ROLL_CARAC_COMP + "\\]", 'giu') | ||||
|  | ||||
| /** | ||||
|  * classe pour gérer les jets de caractéristique/compétence depuis | ||||
|  * les journaux/descriptions | ||||
|  */ | ||||
| export class TextRollCaracCompetence { | ||||
|   get code() { return 'carac' } | ||||
|   get template() { return `systems/foundryvtt-reve-de-dragon/templates/apps/textroll/link-text-roll-carac-competence.hbs` } | ||||
|  | ||||
|   async onReplaceRoll(context) { | ||||
|     const handler = new CaracCompetenceTextBuilder(context) | ||||
|     return await handler.replaceAll() | ||||
|   } | ||||
|  | ||||
|   async onRollText(event, actor) { | ||||
|     const node = TextRollManager.getNode(event) | ||||
|     const caracCode = node.data('carac-code') | ||||
|     if (caracCode) { | ||||
|       const competence = node.data('competence') | ||||
|       const diff = await this.calculDiff(node) | ||||
|       const actors = this.getSelectedActors(actor) | ||||
|       actors.forEach(async it => await this.doRoll(it, caracCode, competence, diff)) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   async calculDiff(node) { | ||||
|     const diff = node.data('diff') ?? 0 | ||||
|     if (!Number.isInteger(diff)) { | ||||
|       const roll = new Roll(diff) | ||||
|       await roll.evaluate() | ||||
|       await roll.toMessage({ flavor: `La difficulté de ${diff} a donné ${roll.total}` }) | ||||
|       return roll.total | ||||
|     } | ||||
|     return diff | ||||
|   } | ||||
|  | ||||
|   async doRoll(actor, caracCode, competence, diff) { | ||||
|     caracCode = actor.mapCarac(caracCode) | ||||
|     if (caracCode) { | ||||
|       if (competence) { | ||||
|         await actor.rollCaracCompetence(caracCode, competence, diff) | ||||
|       } | ||||
|       else { | ||||
|         await actor.rollCarac(caracCode, { diff }) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   getSelectedActors(actor) { | ||||
|     const selected = canvas.tokens.controlled.map(it => it.actor).filter(it => it) | ||||
|     if (selected.length > 0) { | ||||
|       return selected | ||||
|     } | ||||
|     actor = actor ?? RdDUtility.getSelectedActor() | ||||
|     if (actor) { | ||||
|       return [actor] | ||||
|     } | ||||
|     return [] | ||||
|   } | ||||
| } | ||||
|  | ||||
| class CaracCompetenceTextBuilder { | ||||
|   constructor(context) { | ||||
|     this.context = context | ||||
|   } | ||||
|  | ||||
|   async replaceAll() { | ||||
|     await XRegExp.forEach(this.context.text, XREGEXP_ROLL_CARAC_COMP, async (rollMatch, i) => await this.replaceMatch(rollMatch, i)) | ||||
|     return this.context.text | ||||
|   } | ||||
|  | ||||
|   async replaceMatch(rollMatch, i) { | ||||
|     const carac = RdDCarac.caracDetails(rollMatch.carac) | ||||
|     if (carac) { | ||||
|       const competence = rollMatch.competence ? RdDItemCompetence.findCompetence(this.context.competences, rollMatch.competence) : undefined | ||||
|       const replacement = await TextRollManager.createRollText(this.context, | ||||
|         { | ||||
|           code: this.context.code, | ||||
|           carac: carac, | ||||
|           competence: competence?.name, | ||||
|           diff: rollMatch.diff, | ||||
|         }) | ||||
|       this.context.text = this.context.text.replace(rollMatch[0], replacement) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
							
								
								
									
										13
									
								
								module/apps/textroll/text-roll-formatter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								module/apps/textroll/text-roll-formatter.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
|  | ||||
| export class TextRollManager { | ||||
|  | ||||
|   static async createRollText(context, param) { | ||||
|     return await renderTemplate(context.template, { | ||||
|       param, options: context.options | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   static getNode(event) { | ||||
|     return $(event.currentTarget)?.parents(".roll-text-link"); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										51
									
								
								module/apps/textroll/text-roll-formula.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								module/apps/textroll/text-roll-formula.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| import "../xregexp-all.js"; | ||||
| import { TextRollManager } from "./text-roll-formatter.js"; | ||||
|  | ||||
| const REGEXP_ROLL_FORMULA = "(?<formula>[^\\[\\]]+)" | ||||
| const XREGEXP_ROLL_FORMULA = XRegExp("@roll\\[" + REGEXP_ROLL_FORMULA + "\\]", 'giu') | ||||
|  | ||||
| /** | ||||
|  * classe pour gérer les jets de dés (formules Foundry) | ||||
|  */ | ||||
| export class TextRollFormula { | ||||
|   get code() { return 'formula' } | ||||
|   get template() { return `systems/foundryvtt-reve-de-dragon/templates/apps/textroll/link-text-roll-formula.hbs` } | ||||
|  | ||||
|   async onReplaceRoll(context) { | ||||
|     const handler = new FormulaTextBuilder(context) | ||||
|     return await handler.replaceAll() | ||||
|   } | ||||
|  | ||||
|   async onRollText(event, actor) { | ||||
|     const node = TextRollManager.getNode(event) | ||||
|     const rollFormula = node.data('formula') | ||||
|     if (rollFormula) { | ||||
|       const roll = new Roll(rollFormula) | ||||
|       await roll.evaluate() | ||||
|       await roll.toMessage() | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| class FormulaTextBuilder { | ||||
|   constructor(context) { | ||||
|     this.context = context | ||||
|   } | ||||
|  | ||||
|   async replaceAll() { | ||||
|     await XRegExp.forEach(this.context.text, XREGEXP_ROLL_FORMULA, | ||||
|       async (rollMatch, i) => await this.replaceMatch(rollMatch, i)) | ||||
|     return this.context.text | ||||
|   } | ||||
|  | ||||
|   async replaceMatch(rollMatch, i) { | ||||
|     if (rollMatch.formula) { | ||||
|       const replacement = await TextRollManager.createRollText(this.context, | ||||
|         { | ||||
|           code: this.context.code, | ||||
|           formula: rollMatch.formula, | ||||
|         }) | ||||
|       this.context.text = this.context.text.replace(rollMatch[0], replacement) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -2002,7 +2002,7 @@ XRegExp.exec = function (str, regex, pos, sticky) { | ||||
|  */ | ||||
|  | ||||
|  | ||||
| XRegExp.forEach = function (str, regex, callback) { | ||||
| XRegExp.forEach = async function (str, regex, callback) { | ||||
|   var pos = 0; | ||||
|   var i = -1; | ||||
|   var match; | ||||
| @@ -2014,7 +2014,7 @@ XRegExp.forEach = function (str, regex, callback) { | ||||
|     // at least. Actually, because of the way `XRegExp.exec` caches globalized versions of | ||||
|     // regexes, mutating the regex will not have any effect on the iteration or matched strings, | ||||
|     // which is a nice side effect that brings extra safety. | ||||
|     callback(match, ++i, str, regex); | ||||
|     await callback(match, ++i, str, regex); | ||||
|     pos = match.index + (match[0].length || 1); | ||||
|   } | ||||
| }; | ||||
|   | ||||
| @@ -1,6 +1,7 @@ | ||||
| import { Misc } from "./misc.js"; | ||||
| import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; | ||||
| import { RdDTimestamp } from "./time/rdd-timestamp.js"; | ||||
| import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js"; | ||||
|  | ||||
|  | ||||
| /** | ||||
| @@ -61,7 +62,6 @@ export class ChatUtility { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|  | ||||
|   static removeMessages(socketData) { | ||||
|     if (Misc.isFirstConnectedGM()) { | ||||
|       ChatUtility.onRemoveMessages(socketData); | ||||
| @@ -96,7 +96,7 @@ export class ChatUtility { | ||||
|         } | ||||
|         break | ||||
|       case "gmroll": | ||||
|         messageData.whisper = ChatUtility.getOwners(actor) | ||||
|         messageData.whisper = actor ? ChatUtility.getOwners(actor) : ChatUtility.getUserAndGMs() | ||||
|         break | ||||
|       case "selfroll": | ||||
|         messageData.whisper = [game.user] | ||||
| @@ -107,7 +107,7 @@ export class ChatUtility { | ||||
|   } | ||||
|  | ||||
|   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() { | ||||
| @@ -198,6 +198,7 @@ export class ChatUtility { | ||||
|   static async onCreateChatMessage(chatMessage, options, id) { | ||||
|     if (chatMessage.isAuthor) { | ||||
|       await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp()); | ||||
|       await chatMessage.update({ content: await RdDTextEditor.enrichHTML(chatMessage.content, undefined, { showLink: false }) }) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,5 @@ | ||||
| import { RdDBaseActor } from "../actor/base-actor.js"; | ||||
| import { ChatUtility } from "../chat-utility.js"; | ||||
| import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; | ||||
|  | ||||
| const INFO_COEUR = 'info-coeur'; | ||||
|  | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| export const SYSTEM_RDD = 'foundryvtt-reve-de-dragon'; | ||||
| export const SYSTEM_SOCKET_ID = 'system.foundryvtt-reve-de-dragon'; | ||||
| export const LOG_HEAD = 'RdD | '; | ||||
| export const SYSTEM_RDD = 'foundryvtt-reve-de-dragon' | ||||
| export const SYSTEM_SOCKET_ID = 'system.foundryvtt-reve-de-dragon' | ||||
| export const LOG_HEAD = 'RdD | ' | ||||
|  | ||||
| export const HIDE_DICE = 'hide'; | ||||
| export const SHOW_DICE = 'show'; | ||||
| export const HIDE_DICE = 'hide' | ||||
| export const SHOW_DICE = 'show' | ||||
|  | ||||
| export const ENTITE_INCARNE = 'incarne'; | ||||
| export const ENTITE_NONINCARNE = 'nonincarne'; | ||||
| export const ENTITE_BLURETTE = 'blurette'; | ||||
| export const ENTITE_INCARNE = 'incarne' | ||||
| export const ENTITE_NONINCARNE = 'nonincarne' | ||||
| export const ENTITE_BLURETTE = 'blurette' | ||||
|  | ||||
| export const RDD_CONFIG = { | ||||
|   niveauEthylisme : [ | ||||
| @@ -50,4 +50,59 @@ export const RDD_CONFIG = { | ||||
|     {value: "Rare", label: "Rare"}, | ||||
|     {value: "Rarissime", label: "Rarissime"} | ||||
|   ] | ||||
| } | ||||
| } | ||||
|  | ||||
| export const ACTOR_TYPES = { | ||||
|   personnage: 'personnage', | ||||
|   creature: 'creature', | ||||
|   entite: 'entite', | ||||
|   commerce: 'commerce', | ||||
|   vehicule: 'vehicule' | ||||
| } | ||||
|  | ||||
| export const ITEM_TYPES = { | ||||
|   competence: 'competence', | ||||
|   competencecreature: 'competencecreature', | ||||
|   empoignade: 'empoignade', | ||||
|   possession: 'possession', | ||||
|   blessure: 'blessure', | ||||
|   maladie: 'maladie', | ||||
|   poison: 'poison', | ||||
|   arme: 'arme', | ||||
|   armure: 'armure', | ||||
|   conteneur: 'conteneur', | ||||
|   objet: 'objet', | ||||
|   monnaie: 'monnaie', | ||||
|   gemme: 'gemme', | ||||
|   munition: 'munition', | ||||
|   nourritureboisson: 'nourritureboisson', | ||||
|   herbe: 'herbe', | ||||
|   plante: 'plante', | ||||
|   ingredient: 'ingredient', | ||||
|   faune: 'faune', | ||||
|   livre: 'livre', | ||||
|   potion: 'potion', | ||||
|   service: 'service', | ||||
|   musique: 'musique', | ||||
|   danse: 'danse', | ||||
|   chant: 'chant', | ||||
|   jeu: 'jeu', | ||||
|   race: 'race', | ||||
|   recettecuisine: 'recettecuisine', | ||||
|   oeuvre: 'oeuvre', | ||||
|   recettealchimique: 'recettealchimique', | ||||
|   tache: 'tache', | ||||
|   sort: 'sort', | ||||
|   sortreserve: 'sortreserve', | ||||
|   rencontre: 'rencontre', | ||||
|   queue: 'queue', | ||||
|   ombre: 'ombre', | ||||
|   souffle: 'souffle', | ||||
|   tete: 'tete', | ||||
|   casetmr: 'casetmr', | ||||
|   meditation: 'meditation', | ||||
|   signedraconique: 'signedraconique', | ||||
|   tarot: 'tarot', | ||||
|   nombreastral: 'nombreastral', | ||||
|   extraitpoetique: 'extraitpoetique', | ||||
| } | ||||
|   | ||||
| @@ -27,7 +27,7 @@ export class DialogChoixXpCarac extends Dialog { | ||||
|     dialogData = foundry.utils.mergeObject(dialogData, { | ||||
|       default: 'appliquer', | ||||
|       buttons: { | ||||
|         'appliquer': { icon:'<i class="fa-solid fa-check"></i>', label: "Ajouter la répartition", callback: it => this.appliquerSelection() } | ||||
|         'appliquer': { icon: '<i class="fa-solid fa-check"></i>', label: "Ajouter la répartition", callback: it => this.appliquerSelection() } | ||||
|       } | ||||
|     }) | ||||
|     super(dialogData, dialogOptions) | ||||
| @@ -37,18 +37,13 @@ export class DialogChoixXpCarac extends Dialog { | ||||
|   } | ||||
|  | ||||
|   activateListeners(html) { | ||||
|     //TODO | ||||
|     super.activateListeners(html) | ||||
|     this.html = html | ||||
|     this.html.find("li.xpCarac-option .xpCarac-moins").click(event => | ||||
|       this.ajouterXp(event, -1) | ||||
|     ) | ||||
|     this.html.find("li.xpCarac-option .xpCarac-plus").click(event => | ||||
|       this.ajouterXp(event, 1) | ||||
|     ) | ||||
|     this.html.find("li.xpCarac-option .xpCarac-moins").click(event => this.ajouterXp(event, -1)) | ||||
|     this.html.find("li.xpCarac-option .xpCarac-plus").click(event => this.ajouterXp(event, 1)) | ||||
|   } | ||||
|  | ||||
|   async ajouterXp(event, delta) { | ||||
|   ajouterXp(event, delta) { | ||||
|     const liCarac = this.html.find(event.currentTarget)?.parents("li.xpCarac-option") | ||||
|     const label = liCarac?.data("carac-label") | ||||
|     const carac = this.caracs.find(c => c.label == label) | ||||
|   | ||||
| @@ -27,7 +27,7 @@ export class DialogChronologie extends Dialog { | ||||
|       timestamp: game.system.rdd.calendrier.timestamp, | ||||
|       dateReel: game.system.rdd.calendrier.dateReel() | ||||
|     }; | ||||
|     const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-chronologie.html", dialogData); | ||||
|     const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-chronologie.hbs", dialogData); | ||||
|     const dialog = new DialogChronologie(html, dialogData); | ||||
|     dialog.render(true); | ||||
|   } | ||||
| @@ -100,7 +100,7 @@ export class DialogChronologie extends Dialog { | ||||
|   } | ||||
|  | ||||
|   async prepareChronologieEntry(journalParameters) { | ||||
|     return await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chronologie-entry.html", journalParameters); | ||||
|     return await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chronologie-entry.hbs", journalParameters); | ||||
|   } | ||||
|  | ||||
|   extractJournalParameters() { | ||||
|   | ||||
| @@ -18,7 +18,7 @@ export class DialogCreateSigneDraconique extends Dialog { | ||||
|         })) | ||||
|     }; | ||||
|  | ||||
|     const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-create-signedraconique.html", dialogData); | ||||
|     const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-create-signedraconique.hbs", dialogData); | ||||
|     new DialogCreateSigneDraconique(dialogData, html) | ||||
|       .render(true); | ||||
|   } | ||||
| @@ -49,7 +49,7 @@ export class DialogCreateSigneDraconique extends Dialog { | ||||
|     actor.createEmbeddedDocuments("Item", [signe]); | ||||
|     ChatMessage.create({ | ||||
|       whisper: ChatUtility.getOwners(actor), | ||||
|       content: await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html", { | ||||
|       content: await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.hbs", { | ||||
|         signe: signe, | ||||
|         alias: actor.getAlias() | ||||
|       }) | ||||
|   | ||||
| @@ -1,88 +1,79 @@ | ||||
| import { Grammar } from "./grammar.js"; | ||||
| import { Misc } from "./misc.js"; | ||||
| import { RdDUtility } from "./rdd-utility.js"; | ||||
|  | ||||
| export class DialogFabriquerPotion extends Dialog { | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static async create(actor, item, onActionItem) { | ||||
|     const min = DialogFabriquerPotion.nombreBrinsMinimum(item); | ||||
|     if (item.system.quantite < min) { | ||||
|       ui.notifications.warn(`Vous avez ${item.system.quantite} brins de ${item.name}, il en faut au moins ${min} pour faire une potion!`); | ||||
|       return; | ||||
|   static async create(actor, item) { | ||||
|     const brinsMinimum = DialogFabriquerPotion.nombreBrinsMinimum(item) | ||||
|     if (item.system.quantite < brinsMinimum) { | ||||
|       ui.notifications.warn(`Vous avez ${item.system.quantite} brins de ${item.name}, il en faut au moins ${brinsMinimum} pour faire une potion!`) | ||||
|       return | ||||
|     } | ||||
|     let potionData = DialogFabriquerPotion.prepareData(actor, item); | ||||
|     const potionData = DialogFabriquerPotion.prepareData(item, brinsMinimum) | ||||
|     const options = { classes: ["dialogfabriquerpotion"], width: 600, height: 160, 'z-index': 99999 } | ||||
|     const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-fabriquer-potion-base.hbs', potionData) | ||||
|  | ||||
|     const html = await renderTemplate( 'systems/foundryvtt-reve-de-dragon/templates/dialog-fabriquer-potion-base.html', potionData); | ||||
|  | ||||
|     let options = { classes: ["dialogfabriquerpotion"], width: 600, height: 160, 'z-index': 99999 }; | ||||
|     new DialogFabriquerPotion(actor, potionData, onActionItem, html, options).render(true); | ||||
|     new DialogFabriquerPotion(actor, potionData, html, options).render(true) | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static prepareData(actor, item) { | ||||
|     let potionData = foundry.utils.duplicate(item) | ||||
|     potionData.nbBrinsSelect = RdDUtility.buildListOptions( | ||||
|       DialogFabriquerPotion.nombreBrinsMinimum(item), | ||||
|       DialogFabriquerPotion.nombreBrinsOptimal(item)); | ||||
|     potionData.nbBrins = Math.min(potionData.system.quantite, DialogFabriquerPotion.nombreBrinsOptimal(potionData)); | ||||
|     potionData.herbebonus = item.system.niveau; | ||||
|     potionData.buttonName = "Fabriquer"; | ||||
|     return potionData; | ||||
|   static prepareData(item, brinsMinimum) { | ||||
|     const brinsOptimal = DialogFabriquerPotion.nombreBrinsOptimal(item) | ||||
|     return foundry.utils.mergeObject(foundry.utils.duplicate(item), { | ||||
|       nbBrinsSelect: RdDUtility.buildListOptions(brinsMinimum, brinsOptimal), | ||||
|       nbBrins: Math.min(item.system.quantite, brinsOptimal), | ||||
|       herbebonus: item.system.niveau | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   constructor(actor, potionData, onActionItem, html, options) { | ||||
|   constructor(actor, potionData, html, options) { | ||||
|     const conf = { | ||||
|       title: `Fabriquer une potion de ${potionData.system.categorie}`, | ||||
|       content: html, | ||||
|       default: 'fabriquer', | ||||
|       buttons: { | ||||
|         'fabriquer': { | ||||
|           label: potionData.buttonName, callback: it => this.onFabriquer() | ||||
|         } | ||||
|         'fabriquer': { label: "Fabriquer", callback: it => this.onFabriquer() } | ||||
|       } | ||||
|     }; | ||||
|     } | ||||
|     super(conf, options) | ||||
|  | ||||
|     super(conf, options); | ||||
|  | ||||
|     this.actor = actor; | ||||
|     this.potionData = potionData; | ||||
|     this.onActionItem = onActionItem; | ||||
|     this.actor = actor | ||||
|     this.potionData = potionData | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   activateListeners(html) { | ||||
|     super.activateListeners(html); | ||||
|     this.html = html; | ||||
|     super.activateListeners(html) | ||||
|     this.html = html | ||||
|     this.html.find("[name='nbBrins']").change(event => { | ||||
|       this.potionData.nbBrins = Misc.toInt(event.currentTarget.value); | ||||
|       const brinsManquants = Math.max(0, DialogFabriquerPotion.nombreBrinsOptimal(this.potionData) - this.potionData.nbBrins); | ||||
|       this.potionData.nbBrins = Misc.toInt(event.currentTarget.value) | ||||
|       const brinsManquants = Math.max(0, DialogFabriquerPotion.nombreBrinsOptimal(this.potionData) - this.potionData.nbBrins) | ||||
|       this.potionData.herbebonus = Math.max(0, this.potionData.system.niveau - brinsManquants) | ||||
|     }); | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async onFabriquer() { | ||||
|     await this.html.find("[name='nbBrins']").change(); | ||||
|     await this.actor.fabriquerPotion(this.potionData); | ||||
|     this.close(); | ||||
|     await this.onActionItem() | ||||
|     await this.html.find("[name='nbBrins']").change() | ||||
|     await this.actor.fabriquerPotion(this.potionData) | ||||
|     this.close() | ||||
|   } | ||||
|  | ||||
|   static nombreBrinsMinimum(herbeData) { | ||||
|     switch (herbeData.system.categorie ?? '') { | ||||
|       case "Soin": return 1 + Math.max(0, 12 - 2 * herbeData.system.niveau); | ||||
|       case "Repos": return 1 + Math.max(0, 7 - 2 * herbeData.system.niveau); | ||||
|       case "Soin": return 1 + Math.max(0, 12 - 2 * herbeData.system.niveau) | ||||
|       case "Repos": return 1 + Math.max(0, 7 - 2 * herbeData.system.niveau) | ||||
|     } | ||||
|     return 1; | ||||
|     return 1 | ||||
|   } | ||||
|  | ||||
|   static nombreBrinsOptimal(herbeData) { | ||||
|     switch (herbeData.system.categorie ?? '') { | ||||
|       case "Soin": return 12 - herbeData.system.niveau; | ||||
|       case "Repos": return 7 - herbeData.system.niveau; | ||||
|       case "Soin": return 12 - herbeData.system.niveau | ||||
|       case "Repos": return 7 - herbeData.system.niveau | ||||
|     } | ||||
|     return 1; | ||||
|     return 1 | ||||
|   } | ||||
| } | ||||
| @@ -2,13 +2,13 @@ import { Misc } from "./misc.js"; | ||||
|  | ||||
| export class DialogConsommer extends Dialog { | ||||
|  | ||||
|   static async create(actor, item, onActionItem = async () => { }) { | ||||
|   static async create(actor, item) { | ||||
|     const consommerData = DialogConsommer.prepareData(actor, item); | ||||
|     const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-item-consommer.html', consommerData); | ||||
|     return new DialogConsommer(actor, item, consommerData, html, onActionItem) | ||||
|     const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-item-consommer.hbs', consommerData); | ||||
|     return new DialogConsommer(actor, item, consommerData, html) | ||||
|   } | ||||
|  | ||||
|   constructor(actor, item, consommerData, html, onActionItem = async () => { }) { | ||||
|   constructor(actor, item, consommerData, html) { | ||||
|     const options = { classes: ["dialogconsommer"], width: 350, height: 'fit-content', 'z-index': 99999 }; | ||||
|     let conf = { | ||||
|       title: consommerData.title, | ||||
| @@ -16,10 +16,7 @@ export class DialogConsommer extends Dialog { | ||||
|       default: consommerData.buttonName, | ||||
|       buttons: { | ||||
|         [consommerData.buttonName]: { | ||||
|           label: consommerData.buttonName, callback: async it => { | ||||
|             await this.onConsommer(); | ||||
|             await onActionItem(); | ||||
|           } | ||||
|           label: consommerData.buttonName, callback: async it => await this.onConsommer() | ||||
|         } | ||||
|       } | ||||
|     }; | ||||
|   | ||||
| @@ -3,7 +3,7 @@ export class DialogSelect extends Dialog { | ||||
|   static extractIdNameImg(it) { return { id: it.id, name: it.name, img: it.img } } | ||||
|  | ||||
|   static async select(selectionData, onSelectChoice) { | ||||
|     const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-select.html", selectionData) | ||||
|     const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-select.hbs", selectionData) | ||||
|  | ||||
|     const dialogData = { | ||||
|       title: selectionData.title ?? selectionData.label, | ||||
|   | ||||
| @@ -7,7 +7,7 @@ export class DialogSplitItem extends Dialog { | ||||
|       item: item, | ||||
|       choix: { quantite: 1, max: item.system.quantite - 1 } | ||||
|     }; | ||||
|     const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-split.html`, splitData); | ||||
|     const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-split.hbs`, splitData); | ||||
|     return new DialogSplitItem(item, splitData, html, callback) | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -9,7 +9,7 @@ export class DialogValidationEncaissement extends Dialog { | ||||
|  | ||||
|   static async validerEncaissement(actor, rollData, armure, onEncaisser) { | ||||
|     const encaissement = await RdDUtility.jetEncaissement(actor, rollData, armure, { showDice: HIDE_DICE }); | ||||
|     const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', { | ||||
|     const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.hbs', { | ||||
|       actor: actor, | ||||
|       rollData: rollData, | ||||
|       encaissement: encaissement | ||||
|   | ||||
							
								
								
									
										177
									
								
								module/enchantement/dialog-enchanter.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								module/enchantement/dialog-enchanter.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,177 @@ | ||||
| import { ITEM_TYPES } from "../constants.js" | ||||
| import { RdDItemSort } from "../item-sort.js" | ||||
| import { Misc } from "../misc.js" | ||||
|  | ||||
| export const ACTION_ITEM_ENCHANTER =  { | ||||
|   code: 'item-enchanter', label: 'Enchanter', icon: it => 'fa-solid fa-sparkles', | ||||
|   filter: it => game.user.isGM || DialogEnchanter.isEnchantable(it), | ||||
|   optionsFilter: options => options.editable, | ||||
|   action: (item, actor) => DialogEnchanter.enchanter(item) | ||||
| } | ||||
|  | ||||
| export class DialogEnchanter extends Dialog { | ||||
|  | ||||
|   static isEnchantable(item) { | ||||
|     if (!item.isEnchantementPossible) { | ||||
|       return false | ||||
|     } | ||||
|     if (game.user.isGM) { | ||||
|       return true | ||||
|     } | ||||
|     if (item.system.prpermanent) { | ||||
|       return false | ||||
|     } | ||||
|     if (!item.parent?.isHautRevant()) { | ||||
|       return false | ||||
|     } | ||||
|     return RdDItemSort.lancements(RdDItemSort.findEnchantement(item.parent)) > 0 | ||||
|       || RdDItemSort.lancements(RdDItemSort.findPurification(item.parent)) > 0 | ||||
|       || RdDItemSort.lancements(RdDItemSort.findPermanence(item.parent)) > 0 | ||||
|   } | ||||
|  | ||||
|   static dateEnchantement() { | ||||
|     return game.system.rdd.calendrier.getTimestamp().debutJournee().indexDate | ||||
|   } | ||||
|  | ||||
|   static async enchanter(item) { | ||||
|     const actor = item.parent | ||||
|     const sorts = { | ||||
|       enchantement: RdDItemSort.findEnchantement(actor), | ||||
|       purification: RdDItemSort.findPurification(actor), | ||||
|       permanence: RdDItemSort.findPermanence(actor) | ||||
|     } | ||||
|     const nouveauxpr = (sorts.enchantement?.system.lancements ?? []).map(it => it.reve) | ||||
|     const purification = (sorts.purification?.system.lancements ?? []).find(it => true) | ||||
|     const permanence = (sorts.permanence?.system.lancements ?? []).find(it => true) | ||||
|  | ||||
|     const enchanter = { | ||||
|       type: item.type == ITEM_TYPES.potion ? 'potion' : Misc.typeName('Item', item.type), | ||||
|       actor: actor, | ||||
|       item: item, | ||||
|       reve: item.system.pr, | ||||
|       sorts: sorts, | ||||
|       nouveauxpr: nouveauxpr, | ||||
|       purification: purification != undefined, | ||||
|       permanence: permanence != undefined, | ||||
|       options: { isGM: game.user.isGM } | ||||
|     } | ||||
|     if (!item.isEnchantementPossible) { | ||||
|       ui.notifications.info("Seuls les liquides et les gemmes sont enchantables") | ||||
|       return | ||||
|     } | ||||
|     if (item.system.prpermanent) { | ||||
|       ui.notifications.info(`La ${enchanter.type} est permanente`) | ||||
|       return | ||||
|     } | ||||
|     if (!game.user.isGM) { | ||||
|       if (!(actor?.isPersonnage() || actor?.isHautRevant())) { | ||||
|         ui.notifications.info(`Seul un haut rêvant peut enchanter une ${enchanter.type}`) | ||||
|         return | ||||
|       } | ||||
|       if (item.system.quantite != 1) { | ||||
|         ui.notifications.info(`Impossible d'enchanter ${item.system.quantite} ${enchanter.type}s ${item.system.quantite > 1 ? 'en une seule fois' : ''}`) | ||||
|         return | ||||
|       } | ||||
|       if (!(nouveauxpr.length > 0 || purification || permanence)) { | ||||
|         ui.notifications.info("Le haut-rêvant n'a lancé de rituel d'enchantement") | ||||
|         return | ||||
|       } | ||||
|       if (item.system.magique && item.system.purifie && !purification && !permanence) { | ||||
|         ui.notifications.info(`La ${enchanter.type} est déjà enchantée et doit être purifiée`) | ||||
|         return | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/enchantement/dialog-enchanter.hbs`, enchanter) | ||||
|     const dialog = new DialogEnchanter(enchanter, html) | ||||
|     dialog.render(true) | ||||
|   } | ||||
|  | ||||
|   constructor(enchanter, html) { | ||||
|     let options = { classes: ["dialog-enchanter"], width: 400, height: 'fit-content', 'z-index': 99999 } | ||||
|     let conf = { | ||||
|       title: `Enchanter une ${enchanter.type}`, | ||||
|       content: html, | ||||
|       default: "enchanter", | ||||
|       buttons: { | ||||
|         "enchanter": { label: "Enchanter", callback: it => this.onEnchanter() } | ||||
|       } | ||||
|     }; | ||||
|     super(conf, options) | ||||
|     this.html = html | ||||
|     this.enchanter = enchanter | ||||
|     this.item = enchanter.item | ||||
|   } | ||||
|  | ||||
|   activateListeners(html) { | ||||
|     super.activateListeners(html) | ||||
|     this.html = html | ||||
|     this.html.find("input.enchantement").change(event => this.$onSelectEnchantement(event)) | ||||
|     this.html.find("input.reve").change(event => this.$onForceReve(event)) | ||||
|   } | ||||
|  | ||||
|   $onSelectEnchantement(event) { | ||||
|     const addReve = $(event.currentTarget).data('reve') | ||||
|     this.enchanter.idx = $(event.currentTarget).data('idx') | ||||
|     this.enchanter.reve = this.item.system.pr + Number(addReve) | ||||
|     this.html.find("input.reve").val(this.enchanter.reve) | ||||
|     for (let idx = 0; idx < this.enchanter.nouveauxpr.length; idx++) { | ||||
|       if (idx != this.enchanter.idx) { | ||||
|         this.html.find(`.enchantement[data-idx='${idx}']`).prop("checked", false) | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   $onForceReve(event) { | ||||
|     const newReve = Number(event.currentTarget.value) | ||||
|     if (this.enchanter.reve != newReve) { | ||||
|       this.enchanter.idx = undefined | ||||
|     } | ||||
|     this.enchanter.reve = newReve | ||||
|   } | ||||
|  | ||||
|   async onEnchanter() { | ||||
|     foundry.utils.mergeObject(this.enchanter, | ||||
|       { | ||||
|         rendrepurifie: this.html.find("input.rendrepurifie").prop("checked"), | ||||
|         rendrepermanent: this.html.find("input.rendrepermanent").prop("checked"), | ||||
|         addreve: this.enchanter.reve != this.item.system.pr | ||||
|       }, | ||||
|       { inplace: true }) | ||||
|     const item = this.enchanter.item | ||||
|     const actor = this.enchanter.actor | ||||
|  | ||||
|     if (this.enchanter.reve == 0) { | ||||
|       await item.update({ | ||||
|         'system.pr': 0, | ||||
|         'system.magique': false, | ||||
|         'system.purifie': false, | ||||
|         'system.prpermanent': false, | ||||
|         'system.prdate': 0 | ||||
|       }) | ||||
|     } | ||||
|     else { | ||||
|       const isPurifiee = this.enchanter.addreve | ||||
|         ? (this.enchanter.rendrepurifie && (item.item.system.pr == 0 ? true : item.system.purifie)) | ||||
|         : (this.enchanter.rendrepurifie || item.system.purifie) | ||||
|       await item.update({ | ||||
|         'system.pr': this.enchanter.reve, | ||||
|         'system.magique': true, | ||||
|         'system.purifie': isPurifiee, | ||||
|         'system.prpermanent': item.system.prpermanent || this.enchanter.rendrepermanent, | ||||
|         'system.prdate': DialogEnchanter.dateEnchantement() | ||||
|       }) | ||||
|       if (actor) { | ||||
|         if (this.enchanter.rendrepurifie) { | ||||
|           await RdDItemSort.changeLancementsSort(this.enchanter.sorts.purification, it => it.slice(1)); | ||||
|         } | ||||
|         if (this.enchanter.rendrepermanent) { | ||||
|           await RdDItemSort.changeLancementsSort(this.enchanter.sorts.permanence, it => it.slice(1)); | ||||
|         } | ||||
|         if (this.enchanter.addreve && this.enchanter.idx != undefined) { | ||||
|           await RdDItemSort.changeLancementsSort(RdDItemSort.findEnchantement(actor), it => it.toSpliced(this.enchanter.idx, 1)) | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { Grammar } from "./grammar.js"; | ||||
| import { RdDItemCompetenceCreature } from "./item-competencecreature.js" | ||||
| import { ITEM_TYPES } from "./item.js"; | ||||
| import { ITEM_TYPES } from "./constants.js"; | ||||
| import { BASE_CORPS_A_CORPS } from "./item/base-items.js"; | ||||
| import { RdDCombatManager } from "./rdd-combat.js"; | ||||
|  | ||||
| @@ -123,10 +123,10 @@ export class RdDItemArme extends Item { | ||||
|     if (defCategory == 'bouclier') { | ||||
|       return 'norm' | ||||
|     } | ||||
|     if (armeAttaque.system.competence.toLowerCase().match(/(fléau)/)) { | ||||
|     if (armeAttaque?.system?.competence?.toLowerCase().match(/(fléau)/)) { | ||||
|       return '' | ||||
|     } | ||||
|     if (armeParade.system.tir) { | ||||
|     if (armeParade.system?.tir) { | ||||
|       return '' | ||||
|     } | ||||
|     const attCategory = RdDItemArme.getCategorieParade(armeAttaque) | ||||
|   | ||||
| @@ -1,5 +1,6 @@ | ||||
|  | ||||
| import { ITEM_TYPES } from "./item.js"; | ||||
| import { ITEM_TYPES } from "./constants.js"; | ||||
| import { Grammar } from "./grammar.js"; | ||||
| import { RdDCombatManager } from "./rdd-combat.js"; | ||||
|  | ||||
| export const CATEGORIES_COMPETENCES_CREATURES = { | ||||
| @@ -17,9 +18,11 @@ export class RdDItemCompetenceCreature extends Item { | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static setRollDataCreature(rollData) { | ||||
|     rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } } | ||||
|     rollData.competence.system.defaut_carac = "carac_creature" | ||||
|     rollData.selectedCarac = rollData.carac.carac_creature | ||||
|     const code = Grammar.toLowerCaseNoAccentNoSpace(rollData.competence.name); | ||||
|     const selectedCarac = { code: code, label: rollData.competence.name, value: rollData.competence.system.carac_value }; | ||||
|     rollData.carac = { [code]: selectedCarac } | ||||
|     rollData.competence.system.defaut_carac = code | ||||
|     rollData.selectedCarac = selectedCarac | ||||
|     rollData.arme = RdDItemCompetenceCreature.armeCreature(rollData.competence); | ||||
|   } | ||||
|  | ||||
| @@ -29,20 +32,20 @@ export class RdDItemCompetenceCreature extends Item { | ||||
|     if (categorieAttaque != undefined) { | ||||
|       // cloner pour ne pas modifier la compétence | ||||
|       return foundry.utils.mergeObject(item, { | ||||
|           action: item.isCompetencePossession() ? 'possession' : 'attaque', | ||||
|           system: { | ||||
|             competence: item.name, | ||||
|             cac: categorieAttaque == "naturelle" ? "naturelle" : "", | ||||
|             niveau: item.system.niveau, | ||||
|             initiative: RdDCombatManager.calculInitiative(item.system.niveau, item.system.carac_value), | ||||
|             equipe: true, | ||||
|             resistance: 100, | ||||
|             dommagesReels: item.system.dommages, | ||||
|             penetration: 0, | ||||
|             force: 0, | ||||
|             rapide: true, | ||||
|           } | ||||
|         }, { inplace: false, }); | ||||
|         action: item.isCompetencePossession() ? 'possession' : 'attaque', | ||||
|         system: { | ||||
|           competence: item.name, | ||||
|           cac: categorieAttaque == "naturelle" ? "naturelle" : "", | ||||
|           niveau: item.system.niveau, | ||||
|           initiative: RdDCombatManager.calculInitiative(item.system.niveau, item.system.carac_value), | ||||
|           equipe: true, | ||||
|           resistance: 100, | ||||
|           dommagesReels: item.system.dommages, | ||||
|           penetration: 0, | ||||
|           force: 0, | ||||
|           rapide: true, | ||||
|         } | ||||
|       }, { inplace: false, }); | ||||
|     } | ||||
|     return undefined; | ||||
|   } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { Misc } from "./misc.js"; | ||||
| import { LOG_HEAD } from "./constants.js"; | ||||
| import { ITEM_TYPES, LOG_HEAD } from "./constants.js"; | ||||
|  | ||||
| const MONNAIE_ETAIN = { | ||||
|   name: "Denier (étain)", type: 'monnaie', | ||||
| @@ -70,18 +70,17 @@ export class Monnaie { | ||||
|   } | ||||
|  | ||||
|   static getFortune(monnaies) { | ||||
|     return (monnaies??[]) | ||||
|     return (monnaies ?? []) | ||||
|       .map(m => Number(m.system.cout) * Number(m.system.quantite)) | ||||
|       .reduce(Misc.sum(), 0); | ||||
|   } | ||||
|  | ||||
|   static async optimiserFortune(actor, fortune) { | ||||
|     Monnaie.validerMonnaies(actor) | ||||
|     let resteEnDeniers = Math.round(fortune * 100); | ||||
|     let monnaies = actor.itemTypes['monnaie']; | ||||
|     let updates = []; | ||||
|     Monnaie.validerMonnaies(monnaies, actor); | ||||
|     const updates = [] | ||||
|  | ||||
|     let parValeur = Misc.classifyFirst(monnaies, it => VALEUR_DENIERS(it.system.cout)); | ||||
|     const  parValeur = Misc.classifyFirst(actor.itemTypes[ITEM_TYPES.monnaie], it => VALEUR_DENIERS(it.system.cout)); | ||||
|     for (let valeurDeniers of [1000, 100, 10, 1]) { | ||||
|       const itemPiece = parValeur[valeurDeniers]; | ||||
|       if (itemPiece) { | ||||
| @@ -102,8 +101,11 @@ export class Monnaie { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static validerMonnaies(monnaies, actor = undefined) { | ||||
|     monnaies.filter(it => VALEUR_DENIERS(it.system.cout) == 0) | ||||
|   static validerMonnaies(actor) { | ||||
|     if (!actor) { | ||||
|       return | ||||
|      } | ||||
|     actor.itemTypes[ITEM_TYPES.monnaie]?.filter(it => VALEUR_DENIERS(it.system.cout) == 0) | ||||
|       .map(it => `La  monnaie ${it.name} de l'acteur ${actor?.name ?? 'sélectionné'} a une valeur de 0!`) | ||||
|       .forEach(message => { | ||||
|         ui.notifications.warn(message); | ||||
|   | ||||
| @@ -1,9 +1,7 @@ | ||||
| import { ACTOR_TYPES, ITEM_TYPES } from "./constants.js"; | ||||
| import { RdDItemSort } from "./item-sort.js"; | ||||
| import { RdDUtility } from "./rdd-utility.js"; | ||||
| import { RdDAlchimie } from "./rdd-alchimie.js"; | ||||
| import { RdDItemCompetence } from "./item-competence.js"; | ||||
| import { RdDHerbes } from "./rdd-herbes.js"; | ||||
| import { RdDGemme } from "./rdd-gemme.js"; | ||||
| import { HtmlUtility } from "./html-utility.js"; | ||||
| import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; | ||||
| import { SYSTEM_RDD } from "./constants.js"; | ||||
| @@ -12,8 +10,11 @@ import { SystemCompendiums } from "./settings/system-compendiums.js"; | ||||
| import { Misc } from "./misc.js"; | ||||
| import { RdDTimestamp } from "./time/rdd-timestamp.js"; | ||||
| import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; | ||||
| import { ITEM_TYPES, RdDItem } from "./item.js"; | ||||
| import { RdDItem } from "./item.js"; | ||||
| import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js"; | ||||
| import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js"; | ||||
| import { ItemAction } from "./item/item-actions.js"; | ||||
| import { RdDItemGemme } from "./item/gemme.js"; | ||||
|  | ||||
| /** | ||||
|  * Extend the basic ItemSheet for RdD specific items | ||||
| @@ -26,8 +27,8 @@ export class RdDItemSheet extends ItemSheet { | ||||
|  | ||||
|   static defaultTemplate(type) { | ||||
|     return type ? | ||||
|       `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html` : | ||||
|       "systems/foundryvtt-reve-de-dragon/templates/item-sheet.html"; | ||||
|       `systems/foundryvtt-reve-de-dragon/templates/item/${type}-sheet.hbs` : | ||||
|       "systems/foundryvtt-reve-de-dragon/templates/item/item-sheet.hbs"; | ||||
|   } | ||||
|  | ||||
|   static register(sheetClass) { | ||||
| @@ -97,11 +98,11 @@ export class RdDItemSheet extends ItemSheet { | ||||
|       name: this.item.name, | ||||
|       system: this.item.system, | ||||
|       actorId: this.actor?.id, | ||||
|       description: await TextEditor.enrichHTML(this.item.system.description, { async: true }), | ||||
|       descriptionmj: await TextEditor.enrichHTML(this.item.system.descriptionmj, { async: true }), | ||||
|       description: await RdDTextEditor.enrichHTML(this.item.system.description, this.item), | ||||
|       descriptionmj: await RdDTextEditor.enrichHTML(this.item.system.descriptionmj, this.item), | ||||
|       isComestible: this.item.getUtilisationCuisine(), | ||||
|       options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable), | ||||
|       competences: await SystemCompendiums.getCompetences('personnage'), | ||||
|       competences: await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage), | ||||
|       categories: RdDItem.getCategories(this.item.type), | ||||
|     } | ||||
|  | ||||
| @@ -120,26 +121,19 @@ export class RdDItemSheet extends ItemSheet { | ||||
|       formData.competences = formData.competences.filter(it => it.isCompetenceArme()) | ||||
|     } | ||||
|     if (this.item.type == ITEM_TYPES.recettecuisine) { | ||||
|       formData.ingredients = await TextEditor.enrichHTML(this.object.system.ingredients, { async: true }) | ||||
|       formData.ingredients = await RdDTextEditor.enrichHTML(this.item.system.ingredients, this.item) | ||||
|     } | ||||
|     if (this.item.type == ITEM_TYPES.extraitpoetique) { | ||||
|       formData.extrait = await TextEditor.enrichHTML(this.object.system.extrait, { async: true }) | ||||
|       formData.texte = await TextEditor.enrichHTML(this.object.system.texte, { async: true }) | ||||
|       formData.extrait = await RdDTextEditor.enrichHTML(this.item.system.extrait, this.item) | ||||
|       formData.texte = await RdDTextEditor.enrichHTML(this.item.system.texte, this.item) | ||||
|     } | ||||
|     if (this.item.type == ITEM_TYPES.recettealchimique) { | ||||
|       RdDAlchimie.processManipulation(this.item, this.actor?.id); | ||||
|       formData.manipulation_update = await TextEditor.enrichHTML(this.object.system.manipulation_update, { async: true }) | ||||
|       formData.utilisation = await TextEditor.enrichHTML(this.object.system.utilisation, { async: true }) | ||||
|       formData.enchantement = await TextEditor.enrichHTML(this.object.system.enchantement, { async: true }) | ||||
|       formData.sureffet = await TextEditor.enrichHTML(this.object.system.sureffet, { async: true }) | ||||
|     } | ||||
|     if (this.item.type == ITEM_TYPES.gemme) { | ||||
|       formData.gemmeTypeList = RdDGemme.getGemmeTypeOptionList(); | ||||
|       RdDGemme.calculDataDerivees(this.item) | ||||
|     } | ||||
|     if (this.item.type == ITEM_TYPES.potion) { | ||||
|       RdDHerbes.calculFormData(formData, this.item) | ||||
|       formData.manipulation = await RdDTextEditor.enrichHTML(this.item.system.manipulation, this.item) | ||||
|       formData.utilisation = await RdDTextEditor.enrichHTML(this.item.system.utilisation, this.item) | ||||
|       formData.enchantement = await RdDTextEditor.enrichHTML(this.item.system.enchantement, this.item) | ||||
|       formData.sureffet = await RdDTextEditor.enrichHTML(this.item.system.sureffet, this.item) | ||||
|     } | ||||
|  | ||||
|     if (this.item.type == ITEM_TYPES.herbe) { | ||||
|       if (formData.options.isOwned && ['Soin', 'Repos'].includes(formData.system.categorie)) { | ||||
|         formData.isIngredientPotionBase = true; | ||||
| @@ -165,23 +159,19 @@ export class RdDItemSheet extends ItemSheet { | ||||
|  | ||||
|     HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionnelles.isUsing('afficher-prix-joueurs') | ||||
|       || game.user.isGM | ||||
|       || !this.item.isOwned); | ||||
|     HtmlUtility.showControlWhen(this.html.find(".item-magique"), this.item.isMagique()); | ||||
|       || !this.item.isOwned) | ||||
|     HtmlUtility.showControlWhen(this.html.find(".item-magique"), this.item.isMagique) | ||||
|  | ||||
|     // Everything below here is only needed if the sheet is editable | ||||
|     if (!this.options.editable) return; | ||||
|     if (!this.options.editable) return | ||||
|  | ||||
|     this.form.ondragstart = (event) => this._onDragStart(event); | ||||
|     this.form.ondrop = (event) => this._onDrop(event); | ||||
|     this.form.ondragstart = async event => await this._onDragStart(event) | ||||
|     this.form.ondrop = async event => await this._onDrop(event) | ||||
|  | ||||
|     // Select competence categorie | ||||
|     this.html.find(".categorie").change(event => this._onSelectCategorie(event)); | ||||
|     this.html.find(".categorie").change(async event => await this._onSelectCategorie(event)) | ||||
|  | ||||
|     this.html.find('.sheet-competence-xp').change((event) => { | ||||
|       if (this.item.isCompetencePersonnage()) { | ||||
|         RdDUtility.checkThanatosXP(this.item.name); | ||||
|       } | ||||
|     }); | ||||
|     this.html.find('.sheet-competence-xp').change(event => RdDUtility.checkThanatosXP(this.item)) | ||||
|     this.html.find(".item-cout input[name='system.cout']").change(event => { | ||||
|       if (this.item.isMonnaie()) { | ||||
|         const value = event.currentTarget.value; | ||||
| @@ -190,75 +180,60 @@ export class RdDItemSheet extends ItemSheet { | ||||
|         } | ||||
|       } | ||||
|     }) | ||||
|     this.html.find('.delete-bonus-case').click((event) => { | ||||
|       this.supprimerBonusCase(event.currentTarget.attributes['data-deleteCoord'].value) | ||||
|     }) | ||||
|     this.html.find('.delete-bonus-case').click(async event => await this.supprimerBonusCase(event.currentTarget.attributes['data-deleteCoord'].value)) | ||||
|     this.html.find('.creer-tache-livre').click(async event => await this._getEventActor(event).creerTacheDepuisLivre(this.item)) | ||||
|     this.html.find('.creer-potion-base').click(async event => await this._getEventActor(event).fabriquerDecoctionHerbe(this.item)) | ||||
|     this.html.find('input[name="system.cacher_points_de_tache"]').change(async event => | ||||
|       await this.item.update({ 'system.cacher_points_de_tache': event.currentTarget.checked }) | ||||
|     ) | ||||
|  | ||||
|     this.html.find('.date-enchantement').change((event) => { | ||||
|       const jour = Number(this.html.find('input.date-enchantement[name="enchantement.jour"]').val()); | ||||
|       const mois = RdDTimestamp.definition(this.html.find('select.date-enchantement[name="enchantement.mois"]').val()); | ||||
|       const indexDate = game.system.rdd.calendrier.getIndexFromDate(jour, mois.heure); | ||||
|       this.item.update({ 'system.prdate': indexDate }); | ||||
|       console.warn(`Date d'enchantement modifiée ${jour}/${mois.heure}: ${indexDate}`) | ||||
|     }); | ||||
|  | ||||
|     this.html.find('.creer-tache-livre').click((event) => this._getEventActor(event).creerTacheDepuisLivre(this.item)); | ||||
|     this.html.find('.consommer-potion').click((event) => this._getEventActor(event).consommerPotion(this.item, this.getActionRenderItem())); | ||||
|     this.html.find('.creer-potion-base').click((event) => this._getEventActor(event).actionHerbe(this.item)); | ||||
|     this.html.find('input[name="system.cacher_points_de_tache"]').change(async event => await this.item.update({ 'system.cacher_points_de_tache': event.currentTarget.checked })); | ||||
|  | ||||
|     this.html.find('.alchimie-tache a').click((event) => { | ||||
|       let actor = this._getEventActor(event); | ||||
|       if (actor) { | ||||
|         let recetteId = event.currentTarget.attributes['data-recette-id'].value; | ||||
|         let tacheName = event.currentTarget.attributes['data-alchimie-tache'].value; | ||||
|         let tacheData = event.currentTarget.attributes['data-alchimie-data'].value; | ||||
|         actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData); | ||||
|       } else { | ||||
|         ui.notifications.info("Impossible trouver un acteur pour réaliser cette tache Alchimique."); | ||||
|       } | ||||
|     }); | ||||
|     this.html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event, this.actor)) | ||||
|     this.html.find('.chat-roll-text').click(async event => await RdDTextEditor.chatRollText(event)) | ||||
|  | ||||
|     if (this.actor) { | ||||
|       this.html.find('.item-split').click(async event => RdDSheetUtility.splitItem(RdDSheetUtility.getItem(event, this.actor), this.actor, this.getActionRenderItem())); | ||||
|       this.html.find('.item-edit').click(async event => RdDSheetUtility.getItem(event, this.actor)?.sheet.render(true)); | ||||
|       this.html.find('.item-delete').click(async event => RdDUtility.confirmActorItemDelete(this, RdDSheetUtility.getItem(event, this.actor))); | ||||
|       this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente()); | ||||
|       this.html.find('.item-montrer').click(async event => RdDSheetUtility.getItem(event, this.actor)?.postItemToChat()); | ||||
|       this.html.find('.item-action').click(async event => RdDSheetUtility.getItem(event, this.actor)?.actionPrincipale(this.actor, this.getActionRenderItem())); | ||||
|       this.html.find('.actionItem').click(async event => await ItemAction.onActionItem(event, this.actor, this.options)) | ||||
|  | ||||
|       // TODO: utiliser un itemAction? | ||||
|       this.html.find('.item-potion-consommer').click(async event => await this.itemActionConsommer(event)) | ||||
|  | ||||
|       this.html.find('.item-quantite-plus').click(async event => { | ||||
|         await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), 1) | ||||
|         this.render(); | ||||
|       }); | ||||
|         //this.render() | ||||
|       }) | ||||
|       this.html.find('.item-quantite-moins').click(async event => { | ||||
|         await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), -1) | ||||
|         this.render(); | ||||
|       }); | ||||
|         //this.render() | ||||
|       }) | ||||
|     } | ||||
|  | ||||
|     const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: foundry.utils.duplicate(timestamp) }) | ||||
|  | ||||
|     RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.debut', updateItemTimestamp); | ||||
|     RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp); | ||||
|     RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.debut', updateItemTimestamp) | ||||
|     RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp) | ||||
|   } | ||||
|  | ||||
|   getActionRenderItem() { | ||||
|     return async () => { | ||||
|       let item = this.item; | ||||
|       while (item) { | ||||
|         await item.sheet?.render() | ||||
|         item = this.actor.getContenant(item) | ||||
|       } | ||||
|   async itemActionDelete(event) { | ||||
|     const item = RdDSheetUtility.getItem(event, this.actor) | ||||
|     return await RdDUtility.confirmActorItemDelete(item, this.actor) | ||||
|   } | ||||
|  | ||||
|   async itemActionConsommer(event) { | ||||
|     const item = RdDSheetUtility.getItem(event, this.actor) | ||||
|     if (item) { | ||||
|       await actor.consommerPotion(item) | ||||
|       await RdDSheetUtility.renderItemBranch(this.actor, item) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   _getEventActor(event) { | ||||
|     let actorId = event.currentTarget.attributes['data-actor-id'].value; | ||||
|     let actor = game.actors.get(actorId); | ||||
|     return actor; | ||||
|   async itemActionSplit(event) { | ||||
|     const item = RdDSheetUtility.getItem(event, this.actor) | ||||
|     if (item) { | ||||
|       await RdDSheetUtility.splitItem(item, this.actor) | ||||
|       await RdDSheetUtility.renderItemBranch(this.actor, item) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   _getEventActor(event) { return game.actors.get(event.currentTarget.attributes['data-actor-id'].value) } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async _onSelectCategorie(event) { | ||||
| @@ -272,7 +247,7 @@ export class RdDItemSheet extends ItemSheet { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   async supprimerBonusCase(deleteCoord){ | ||||
|   async supprimerBonusCase(deleteCoord) { | ||||
|     if (this.item.type == ITEM_TYPES.sort) { | ||||
|       const oldList = RdDItemSort.getBonusCaseList(this.item) | ||||
|       const newList = oldList.filter(it => it.case != deleteCoord); | ||||
| @@ -300,7 +275,7 @@ export class RdDItemSheet extends ItemSheet { | ||||
|         break | ||||
|     } | ||||
|  | ||||
|     return this.item.update(formData); | ||||
|     return this.item.update(formData) | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
| @@ -333,8 +308,9 @@ export class RdDItemSheet extends ItemSheet { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async _onDragStart(event) { | ||||
|   } | ||||
|   async _onDragStart(event) { } | ||||
|   async _onDropItem(event, dragData) { } | ||||
|   async _onDropActor(event, dragData) { } | ||||
|  | ||||
|   async _onDrop(event) { | ||||
|     // Try to extract the dragData | ||||
| @@ -360,13 +336,7 @@ export class RdDItemSheet extends ItemSheet { | ||||
|         return JSON.parse(eventData); | ||||
|       } | ||||
|     } catch (err) { } | ||||
|     return undefined; | ||||
|   } | ||||
|  | ||||
|   async _onDropItem(event, dragData) { | ||||
|   } | ||||
|  | ||||
|   async _onDropActor(event, dragData) { | ||||
|     return undefined | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { Grammar } from "./grammar.js"; | ||||
| import { RdDItemCompetence } from "./item-competence.js"; | ||||
| import { ITEM_TYPES } from "./item.js"; | ||||
| import { ITEM_TYPES } from "./constants.js"; | ||||
| import { Misc } from "./misc.js"; | ||||
| import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js"; | ||||
|  | ||||
| @@ -22,7 +22,21 @@ export class RdDItemSort extends Item { | ||||
|   } | ||||
|  | ||||
|   static addSpaceToNonNumeric(value) { | ||||
|     return Number.isNumeric(value) || ['-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].includes( String(value).charAt[0]) ? value : ' ' + RdDItemSort.toVar(value) | ||||
|     return Number.isNumeric(value) || ['-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].includes(String(value).charAt[0]) ? value : ' ' + RdDItemSort.toVar(value) | ||||
|   } | ||||
|  | ||||
|   static lancements(sort) { return sort?.system.lancements.length ?? 0 } | ||||
|  | ||||
|   static findEnchantement(actor) { return RdDItemSort.findSort(actor, 'Enchantement', ['Narcos', 'N']) } | ||||
|   static findPermanence(actor) { return RdDItemSort.findSort(actor, 'Permanence', ['Narcos', 'N']) } | ||||
|   static findPurification(actor) { return RdDItemSort.findSort(actor, 'Purification', ['Narcos', 'N']) } | ||||
|  | ||||
|   static findSort(actor, name, draconics) { | ||||
|     return actor.itemTypes[ITEM_TYPES.sort].find(it => Grammar.includesLowerCaseNoAccent(it.name, name) | ||||
|       && (draconics == undefined || draconics.includes(it.system.draconic))) | ||||
|   } | ||||
|   static async changeLancementsSort(sort, changement) { | ||||
|     await sort?.update({ 'system.lancements': changement(sort.system.lancements) }); | ||||
|   } | ||||
|  | ||||
|   static toVar(value) { | ||||
| @@ -42,6 +56,10 @@ export class RdDItemSort extends Item { | ||||
|     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) { | ||||
|     return (VOIES_DRACONIC.find(it => it.code == code)?.ordre ?? '?') | ||||
|   } | ||||
| @@ -78,7 +96,7 @@ export class RdDItemSort extends Item { | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   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); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
| @@ -151,5 +169,4 @@ export class RdDItemSort extends Item { | ||||
|       .map(it => it.split(':')) | ||||
|       .map(it => { return { case: it[0], bonus: it[1] } }); | ||||
|   } | ||||
|  | ||||
| } | ||||
							
								
								
									
										218
									
								
								module/item.js
									
									
									
									
									
								
							
							
						
						
									
										218
									
								
								module/item.js
									
									
									
									
									
								
							| @@ -1,7 +1,7 @@ | ||||
| import { ITEM_TYPES } from "./constants.js"; | ||||
| import { DialogItemVente } from "./achat-vente/dialog-item-vente.js"; | ||||
| import { Grammar } from "./grammar.js"; | ||||
| import { Misc } from "./misc.js"; | ||||
| import { RdDHerbes } from "./rdd-herbes.js"; | ||||
| import { RdDTimestamp } from "./time/rdd-timestamp.js"; | ||||
| import { RdDUtility } from "./rdd-utility.js"; | ||||
| import { SystemCompendiums } from "./settings/system-compendiums.js"; | ||||
| @@ -9,61 +9,7 @@ import { RdDRaretes } from "./item/raretes.js"; | ||||
| import { CATEGORIES_COMPETENCES } from "./item-competence.js"; | ||||
| import { CATEGORIES_COMPETENCES_CREATURES } from "./item-competencecreature.js"; | ||||
| import { BASE_CORPS_A_CORPS, BASE_ESQUIVE } from "./item/base-items.js"; | ||||
|  | ||||
| export const ACTOR_TYPES = { | ||||
|   personnage: 'personnage', | ||||
|   creature: 'creature', | ||||
|   entite: 'entite', | ||||
|   commerce: 'commerce', | ||||
|   vehicule: 'vehicule' | ||||
| } | ||||
|  | ||||
| export const ITEM_TYPES = { | ||||
|   competence: 'competence', | ||||
|   competencecreature: 'competencecreature', | ||||
|   empoignade: 'empoignade', | ||||
|   possession: 'possession', | ||||
|   blessure: 'blessure', | ||||
|   maladie: 'maladie', | ||||
|   poison: 'poison', | ||||
|   arme: 'arme', | ||||
|   armure: 'armure', | ||||
|   conteneur: 'conteneur', | ||||
|   objet: 'objet', | ||||
|   monnaie: 'monnaie', | ||||
|   gemme: 'gemme', | ||||
|   munition: 'munition', | ||||
|   nourritureboisson: 'nourritureboisson', | ||||
|   herbe: 'herbe', | ||||
|   plante: 'plante', | ||||
|   ingredient: 'ingredient', | ||||
|   faune: 'faune', | ||||
|   livre: 'livre', | ||||
|   potion: 'potion', | ||||
|   service: 'service', | ||||
|   musique: 'musique', | ||||
|   danse: 'danse', | ||||
|   chant: 'chant', | ||||
|   jeu: 'jeu', | ||||
|   race: 'race', | ||||
|   recettecuisine: 'recettecuisine', | ||||
|   oeuvre: 'oeuvre', | ||||
|   recettealchimique: 'recettealchimique', | ||||
|   tache: 'tache', | ||||
|   sort: 'sort', | ||||
|   sortreserve: 'sortreserve', | ||||
|   rencontre: 'rencontre', | ||||
|   queue: 'queue', | ||||
|   ombre: 'ombre', | ||||
|   souffle: 'souffle', | ||||
|   tete: 'tete', | ||||
|   casetmr: 'casetmr', | ||||
|   meditation: 'meditation', | ||||
|   signedraconique: 'signedraconique', | ||||
|   tarot: 'tarot', | ||||
|   nombreastral: 'nombreastral', | ||||
|   extraitpoetique: 'extraitpoetique', | ||||
| } | ||||
| import { ITEM_ACTIONS, DEFAULT_ACTIONS, COMMON_ACTIONS } from "./item/item-actions.js"; | ||||
|  | ||||
| const typesInventaireMateriel = [ | ||||
|   ITEM_TYPES.arme, | ||||
| @@ -95,51 +41,47 @@ const typesObjetsTemporels = [ITEM_TYPES.blessure, ITEM_TYPES.poison, ITEM_TYPES | ||||
| const typesObjetsEquipable = [ITEM_TYPES.arme, ITEM_TYPES.armure, ITEM_TYPES.objet]; | ||||
| const typesEnvironnement = typesInventaireMateriel; | ||||
| const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc | ||||
| const encPepin = 0.0007; /* un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc | ||||
| densité 3.5 (~2.3 à 4, parfois plus) -- https://www.juwelo.fr/guide-des-pierres/faits-et-chiffres/  | ||||
|    */ | ||||
|  | ||||
| export const defaultItemImg = { | ||||
|   competence: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp", | ||||
|   competencecreature: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp", | ||||
|   arme: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.webp", | ||||
|   armure: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.webp", | ||||
|   conteneur: "systems/foundryvtt-reve-de-dragon/icons/objets/sac_a_dos.webp", | ||||
|   sort: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp", | ||||
|   herbe: "systems/foundryvtt-reve-de-dragon/icons/botanique/Endorlotte.webp", | ||||
|   faune: "systems/foundryvtt-reve-de-dragon/icons/faune/rongeur.webp", | ||||
|   ingredient: "systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp", | ||||
|   livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp", | ||||
|   potion: "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp", | ||||
|   rencontre: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp", | ||||
|   queue: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp", | ||||
|   ombre: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp", | ||||
|   souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp", | ||||
|   tete: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp", | ||||
|   meditation: "systems/foundryvtt-reve-de-dragon/icons/meditations_ecrits/meditation_alchimie.webp", | ||||
|   recettealchimique: "systems/foundryvtt-reve-de-dragon/icons/competence_alchimie.webp", | ||||
|   chant: "systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp", | ||||
|   competence: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp", | ||||
|   competencecreature: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp", | ||||
|   conteneur: "systems/foundryvtt-reve-de-dragon/icons/objets/sac_a_dos.webp", | ||||
|   danse: "systems/foundryvtt-reve-de-dragon/icons/arts/danse_0.webp", | ||||
|   empoignade: "systems/foundryvtt-reve-de-dragon/icons/empoignade.webp", | ||||
|   extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp", | ||||
|   faune: "systems/foundryvtt-reve-de-dragon/icons/faune/rongeur.webp", | ||||
|   gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp", | ||||
|   herbe: "systems/foundryvtt-reve-de-dragon/icons/botanique/Endorlotte.webp", | ||||
|   ingredient: "systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp", | ||||
|   jeu: "systems/foundryvtt-reve-de-dragon/icons/arts/jeux_petasse.webp", | ||||
|   recettecuisine: "systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_1.webp", | ||||
|   musique: "systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp", | ||||
|   livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp", | ||||
|   maladie: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/maladie.webp", | ||||
|   poison: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp", | ||||
|   oeuvre: "systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp", | ||||
|   meditation: "systems/foundryvtt-reve-de-dragon/icons/meditations_ecrits/meditation_alchimie.webp", | ||||
|   musique: "systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp", | ||||
|   nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp", | ||||
|   oeuvre: "systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp", | ||||
|   ombre: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp", | ||||
|   poison: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp", | ||||
|   possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp", | ||||
|   potion: "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp", | ||||
|   queue: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp", | ||||
|   recettealchimique: "systems/foundryvtt-reve-de-dragon/icons/competence_alchimie.webp", | ||||
|   recettecuisine: "systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_1.webp", | ||||
|   rencontre: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp", | ||||
|   service: "systems/foundryvtt-reve-de-dragon/icons/services/lit.webp", | ||||
|   signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp", | ||||
|   gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp", | ||||
|   possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp", | ||||
|   sort: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp", | ||||
|   sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp", | ||||
|   extraitpoetique: "systems/foundryvtt-reve-de-dragon/icons/competence_ecriture.webp", | ||||
|   souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp", | ||||
|   tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp", | ||||
|   empoignade: "systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp" | ||||
|   tete: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp", | ||||
| } | ||||
|  | ||||
| /* -------------------------------------------- */ | ||||
| export class RdDItem extends Item { | ||||
|  | ||||
|   static get defaultIcon() { | ||||
|     return undefined; | ||||
|   } | ||||
| @@ -238,7 +180,6 @@ export class RdDItem extends Item { | ||||
|   isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature } | ||||
|   isConteneur() { return this.type == ITEM_TYPES.conteneur; } | ||||
|   isMonnaie() { return this.type == ITEM_TYPES.monnaie; } | ||||
|   isPotion() { return this.type == ITEM_TYPES.potion; } | ||||
|   isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; } | ||||
|   isService() { return this.type == ITEM_TYPES.service; } | ||||
|  | ||||
| @@ -277,6 +218,12 @@ export class RdDItem extends Item { | ||||
|     return this.getEnvironnements(milieux).length > 0 | ||||
|   } | ||||
|  | ||||
|   get nameDisplay() { | ||||
|     return this.isMagique ? (this.name + ' <i class="fa-solid fa-sparkles"></i>') : this.name | ||||
|   } | ||||
|  | ||||
|   get isEnchantementPossible() { return false } | ||||
|  | ||||
|   getEnvironnements(milieux = undefined) { | ||||
|     const environnements = this.isInventaire() ? this.system.environnement : undefined; | ||||
|     if (milieux == undefined || !environnements) { | ||||
| @@ -356,13 +303,6 @@ export class RdDItem extends Item { | ||||
|  | ||||
|   getUtilisation() { | ||||
|     switch (this.type) { | ||||
|       case ITEM_TYPES.potion: | ||||
|         switch (this.system.categorie) { | ||||
|           case 'Alchimie': case 'AlchimieEnchante': case 'AlchimieAutre': return 'alchimie' | ||||
|           case 'Cuisine': return 'cuisine' | ||||
|           case 'Remede': case 'Repos': case 'ReposEnchante': case 'Soin': case 'SoinEnchante': return 'soins' | ||||
|         } | ||||
|         return ''; | ||||
|       case ITEM_TYPES.nourritureboisson: return 'cuisine'; | ||||
|       case ITEM_TYPES.herbe: case ITEM_TYPES.faune: case ITEM_TYPES.ingredient: case ITEM_TYPES.plante: | ||||
|         switch (this.system.categorie) { | ||||
| @@ -392,7 +332,7 @@ export class RdDItem extends Item { | ||||
|     return this.type == ITEM_TYPES.objet && Grammar.includesLowerCaseNoAccent(this.name, 'cristal alchimique') && this.system.quantite > 0; | ||||
|   } | ||||
|  | ||||
|   isMagique() { | ||||
|   get isMagique() { | ||||
|     return this.system.magique | ||||
|   } | ||||
|  | ||||
| @@ -403,6 +343,7 @@ export class RdDItem extends Item { | ||||
|   isNomLike(texte) { | ||||
|     return Grammar.includesLowerCaseNoAccent(this.name, texte) | ||||
|   } | ||||
|  | ||||
|   isNomTypeLike(texte) { | ||||
|     return this.isNomLike(texte) || Grammar.includesLowerCaseNoAccent(Misc.typeName(this.type, 'Item'), texte) | ||||
|   } | ||||
| @@ -421,8 +362,6 @@ export class RdDItem extends Item { | ||||
|         return 0; | ||||
|       case ITEM_TYPES.herbe: | ||||
|         return this.getEncHerbe(); | ||||
|       case ITEM_TYPES.gemme: | ||||
|         return encPepin * this.system.taille; | ||||
|     } | ||||
|     return Math.max(this.system.encombrement ?? 0, 0); | ||||
|   } | ||||
| @@ -471,68 +410,47 @@ export class RdDItem extends Item { | ||||
|       // appliquer le pourcentage | ||||
|       return this.parent.calculerPrix(this); | ||||
|     } | ||||
|     return this.system.cout; | ||||
|     return this.system.cout | ||||
|   } | ||||
|  | ||||
|   prepareDerivedData() { | ||||
|     super.prepareDerivedData(); | ||||
|     if (this.isInventaire()) { | ||||
|       this.system.encTotal = this.getEncTotal(); | ||||
|       if (this.isPotion()) { | ||||
|         this.prepareDataPotion() | ||||
|       } | ||||
|       this.system.actionPrincipale = this.getActionPrincipale({ warnIfNot: false }); | ||||
|       this.system.encTotal = this.getEncTotal() | ||||
|     } | ||||
|     this.equipable = this.isEquipable(); | ||||
|     this.equipable = this.isEquipable() | ||||
|   } | ||||
|  | ||||
|   prepareDataPotion() { | ||||
|     const categorie = Grammar.toLowerCaseNoAccent(this.system.categorie); | ||||
|     this.system.magique = categorie.includes('enchante'); | ||||
|     if (this.system.magique) { | ||||
|       if (categorie.includes('soin') || categorie.includes('repos')) { | ||||
|         // TODO: utiliser calculPointsRepos / calculPointsGuerison | ||||
|         this.system.puissance = RdDHerbes.calculPuissancePotion(this); | ||||
|       } | ||||
|     } | ||||
|   itemActions() { | ||||
|     return COMMON_ACTIONS.concat(this.itemSpecificActions()).concat(DEFAULT_ACTIONS) | ||||
|   } | ||||
|  | ||||
|   getActionPrincipale(options = { warnIfNot: true }) { | ||||
|   itemSpecificActions() { | ||||
|     const actions = ITEM_ACTIONS[this.type] ?? [] | ||||
|     return actions | ||||
|   } | ||||
|  | ||||
|   isActionAllowed(code) { | ||||
|     switch (this.type) { | ||||
|       case ITEM_TYPES.conteneur: return 'Ouvrir'; | ||||
|     } | ||||
|     if (this.actor?.isPersonnage()) { | ||||
|       const warn = options.warnIfNot; | ||||
|       if (this.getUtilisationCuisine() == 'brut') { | ||||
|         return 'Cuisiner'; | ||||
|       } | ||||
|       switch (this.type) { | ||||
|         case ITEM_TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn); | ||||
|         case ITEM_TYPES.potion: return this._actionOrWarnQuantiteZero('Consommer', warn); | ||||
|         case ITEM_TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn); | ||||
|         case ITEM_TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined; | ||||
|         case ITEM_TYPES.queue: case ITEM_TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined; | ||||
|       } | ||||
|     } | ||||
|     return undefined; | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async actionPrincipale(actor, onActionItem = async () => { }) { | ||||
|     if (!this.getActionPrincipale()) { return } | ||||
|     await actor?.actionPrincipale(this, onActionItem); | ||||
|   } | ||||
|  | ||||
|   _actionOrWarnQuantiteZero(actionName, warn) { | ||||
|     if ((this.system.quantite ?? 0) <= 0) { | ||||
|       if (warn) { | ||||
|         ui.notifications.warn(`Vous n'avez plus de ${this.name}.`); | ||||
|       } | ||||
|       return undefined; | ||||
|     } | ||||
|     else { | ||||
|       return actionName; | ||||
|       case ITEM_TYPES.possession: | ||||
|       case ITEM_TYPES.empoignade: | ||||
|       case ITEM_TYPES.rencontre: | ||||
|       case ITEM_TYPES.signedraconique: | ||||
|         switch (code) { | ||||
|           case 'item-edit': | ||||
|           case 'item-delete': | ||||
|             return game.user.isGM | ||||
|         } | ||||
|       case ITEM_TYPES.maladie: | ||||
|       case ITEM_TYPES.poison: | ||||
|         return game.user.isGM | ||||
|       case ITEM_TYPES.casetmr: | ||||
|         switch (code) { | ||||
|           case 'item-delete': | ||||
|             return game.user.isGM | ||||
|         } | ||||
|     } | ||||
|     return true | ||||
|   } | ||||
|  | ||||
|   async diminuerQuantite(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) { | ||||
| @@ -673,7 +591,7 @@ export class RdDItem extends Item { | ||||
|   } | ||||
|  | ||||
|   getChatItemTemplate() { | ||||
|     return 'systems/foundryvtt-reve-de-dragon/templates/post-item.html'; | ||||
|     return 'systems/foundryvtt-reve-de-dragon/templates/post-item.hbs'; | ||||
|   } | ||||
|  | ||||
|   static propertyIfDefined(name, val, condition = true) { | ||||
| @@ -805,14 +723,6 @@ export class RdDItem extends Item { | ||||
|     ] | ||||
|   } | ||||
|   /* -------------------------------------------- */ | ||||
|   _potionChatData() { | ||||
|     return [ | ||||
|       `<b>Rareté</b>: ${this.system.rarete}`, | ||||
|       `<b>Catégorie</b>: ${this.system.categorie}`, | ||||
|       ...this._inventaireTemplateChatData() | ||||
|     ] | ||||
|   } | ||||
|   /* -------------------------------------------- */ | ||||
|   _queueChatData() { | ||||
|     function label(categorie) { | ||||
|       switch (categorie) { | ||||
|   | ||||
| @@ -1,4 +1,5 @@ | ||||
| import { ITEM_TYPES, RdDItem } from "../item.js"; | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { RdDItem } from "../item.js"; | ||||
| import { Misc } from "../misc.js"; | ||||
| import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; | ||||
|  | ||||
| @@ -10,7 +11,7 @@ export class RdDItemArmure extends RdDItem { | ||||
|     return "systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.webp"; | ||||
|   } | ||||
|  | ||||
|   deteriorerArmure(dmg) { | ||||
|   async deteriorerArmure(dmg) { | ||||
|     if (!ReglesOptionnelles.isUsing('deteriorationArmure') || this.system.protection == '0') { | ||||
|       return; | ||||
|     } | ||||
| @@ -22,12 +23,10 @@ export class RdDItemArmure extends RdDItem { | ||||
|       protection = this.calculProtectionDeterioree(); | ||||
|       ChatMessage.create({ content: `Votre armure ${this.name} s'est détériorée, elle protège maintenant de ${protection}` }); | ||||
|     } | ||||
|     this.update({ | ||||
|       system: { | ||||
|         deterioration: deterioration, | ||||
|         protection: protection | ||||
|       } | ||||
|     }); | ||||
|     await this.update({ | ||||
|       'system.deterioration': deterioration, | ||||
|       'system.protection': protection | ||||
|     }) | ||||
|   } | ||||
|  | ||||
|   calculProtectionDeterioree() { | ||||
|   | ||||
| @@ -30,7 +30,7 @@ export class RdDItemBlessure extends RdDItem { | ||||
|  | ||||
|   prepareDerivedData() { | ||||
|     super.prepareDerivedData(); | ||||
|     this.system.label = this.getLabelGravite() | ||||
|     this.system.label = RdDItemBlessure.getLabelGravite(this.system.gravite) | ||||
|   } | ||||
|  | ||||
|   static prepareTacheSoin(gravite) { | ||||
| @@ -43,29 +43,32 @@ export class RdDItemBlessure extends RdDItem { | ||||
|   } | ||||
|  | ||||
|   static async applyFullBlessure(actor, gravite) { | ||||
|     const definition = RdDItemBlessure.getDefinition(gravite) | ||||
|      | ||||
|     let lostEndurance = 0 | ||||
|     let lostVie = 0 | ||||
|     if (definition.endurance) { | ||||
|       lostEndurance = new Roll(definition.endurance) | ||||
|       await lostEndurance.roll(); | ||||
|       actor.santeIncDec("endurance", -Number(lostEndurance.total)); | ||||
|     } | ||||
|     const definition = foundry.utils.duplicate(RdDItemBlessure.getDefinition(gravite)) | ||||
|  | ||||
|     if (definition.vie) { | ||||
|       lostVie = definition.vie | ||||
|       actor.santeIncDec("vie", definition.vie) | ||||
|       await actor.santeIncDec("vie", definition.vie) | ||||
|     } | ||||
|     const lostEndurance = await RdDItemBlessure.rollLostEndurance(definition.endurance) | ||||
|     if (lostEndurance) { | ||||
|       await actor.santeIncDec("endurance", -Number(lostEndurance)); | ||||
|     } | ||||
|      | ||||
|     await this.createBlessure(actor, gravite) | ||||
|  | ||||
|     ChatMessage.create({ | ||||
|       content: `Blessure ${definition.label} appliquée à ${actor.name}`+ | ||||
|         `<br>Perte d'endurance : ${lostEndurance}`+ | ||||
|         `<br>Perte de Vie : ${lostVie}`, | ||||
|       //TODO: hbs | ||||
|       content: `Blessure ${definition.label} appliquée à ${actor.name}<br>Perte d'endurance : ${lostEndurance} (${definition.endurance})<br>Perte de Vie : ${definition.vie}`, | ||||
|       whisper: ChatUtility.getOwners(actor) | ||||
|     }); | ||||
|     actor.sheet?.render() | ||||
|   } | ||||
|  | ||||
|   static async rollLostEndurance(formula) { | ||||
|     if (formula) { | ||||
|       const roll = new Roll(formula) | ||||
|       await roll.evaluate() | ||||
|       return roll.total | ||||
|     } | ||||
|     return 0 | ||||
|   } | ||||
|  | ||||
|   static async createBlessure(actor, gravite, localisation = '', attackerToken) { | ||||
| @@ -125,10 +128,10 @@ export class RdDItemBlessure extends RdDItem { | ||||
|     } | ||||
|     if (this.system.gravite > 0) { | ||||
|       const update = { system: { premierssoins: { bonus: 0 }, soinscomplets: { bonus: 0 } } } | ||||
|       const gravite = this.system.gravite; | ||||
|       const graviteMoindre = gravite - 2; | ||||
|       const gravite = this.system.gravite | ||||
|       const graviteMoindre = gravite - 2 | ||||
|       const moindres = blessures.filter(it => it.system.gravite == graviteMoindre, 'blessures').length | ||||
|       const label = this.getLabelGravite(); | ||||
|       const label = RdDItemBlessure.getLabelGravite(this.system.gravite) | ||||
|  | ||||
|       let rolled = await actor.jetRecuperationConstitution(this.system.soinscomplets.bonus, message); | ||||
|  | ||||
| @@ -158,11 +161,11 @@ export class RdDItemBlessure extends RdDItem { | ||||
|   } | ||||
|  | ||||
|   peutRetrograder(graviteMoindre, moindres) { | ||||
|     return moindres < RdDItemBlessure.getDefinition(graviteMoindre).max | ||||
|     return moindres < RdDItemBlessure.maxBlessures(graviteMoindre) | ||||
|   } | ||||
|  | ||||
|   async calculerFinPeriodeTemporel(debut) { | ||||
|     return await debut.nouveauJour().addJours(this.system.gravite); | ||||
|     return debut.nouveauJour().addJours(this.system.gravite); | ||||
|   } | ||||
|  | ||||
|   async onFinPeriode(oldTimestamp, newTimestamp) { | ||||
| @@ -182,16 +185,16 @@ export class RdDItemBlessure extends RdDItem { | ||||
|     return `systems/foundryvtt-reve-de-dragon/icons/sante/${soins ? 'blessure-soins' : img}.webp` | ||||
|   } | ||||
|  | ||||
|   getLabelGravite() { | ||||
|     return RdDItemBlessure.getDefinition(this.system.gravite).label | ||||
|   static getLabelGravite(gravite) { | ||||
|     return definitionsBlessures.find(it => it.gravite >= gravite).label | ||||
|   } | ||||
|  | ||||
|   static getDefinition(gravite) { | ||||
|     return definitionsBlessures.sort(Misc.ascending(it => it.gravite)) | ||||
|       .find(it => it.gravite >= gravite); | ||||
|     return definitionsBlessures.find(it => it.gravite >= gravite) | ||||
|   } | ||||
|  | ||||
|   static maxBlessures(gravite) { | ||||
|     return RdDItemBlessure.getDefinition(gravite).max | ||||
|     return definitionsBlessures.find(it => it.gravite >= gravite).max | ||||
|   } | ||||
|  | ||||
|   isContusion() { | ||||
| @@ -216,7 +219,7 @@ export class RdDItemBlessure extends RdDItem { | ||||
|       `<b>Heure et Date</b>: ${new RdDTimestamp(this.system.temporel.debut).formatDateHeure()}`, | ||||
|       RdDItem.propertyIfDefined('Blessé', this.parent?.name, this.parent), | ||||
|       `<b>Localisation</b>: ${this.system.localisation}`, | ||||
|       `<b>Gravité</b>: ${RdDItemBlessure.getDefinition(this.system.gravite).label}`, | ||||
|       `<b>Gravité</b>: ${this.system.label}`, | ||||
|       `<b>Difficulté des soins</b>: ${this.system.difficulte}`, | ||||
|       (this.system.soinscomplets.done ? | ||||
|         `<b>Bonus soins complets</b>: ${this.system.soinscomplets.bonus}` : | ||||
|   | ||||
							
								
								
									
										112
									
								
								module/item/gemme.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								module/item/gemme.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| import { RdDItem } from "../item.js"; | ||||
| import { ACTION_ITEM_ENCHANTER } from "../enchantement/dialog-enchanter.js"; | ||||
|  | ||||
| const tableGemmes = { | ||||
|   "almaze": { label: "Almaze", couleur: "Blanc" }, | ||||
|   "aquafane": { label: "Aquafane", couleur: "Vert Profond" }, | ||||
|   "asterite": { label: "Astérite", couleur: "Bleu, Violet ou Blanc" }, | ||||
|   "cyanolithe": { label: "Cyanolithe", couleur: "Bleu Intense" }, | ||||
|   "larmededragon": { label: "Larme de Dragon", couleur: "Rouge Intense" }, | ||||
|   "muska": { label: "Muska", couleur: "Violet Profond" }, | ||||
|   "nebuleuse": { label: "Nébuleuse", couleur: "Brouillard Intense" }, | ||||
|   "nebuleuse": { label: "Nébuleuse", couleur: "Brouillard Intense, Rose, Vert ou Bleu Pâle" }, | ||||
|   "oeildetigre": { label: "Oeil de Tigre", couleur: "Jaune" }, | ||||
|   "scarlatine": { label: "Scarlatine", couleur: "Rouge Clair ou Orangé" }, | ||||
|   "seliphane": { label: "Séliphane", couleur: "Vert Lumineux" }, | ||||
|   "tournelune": { label: "Tournelune", couleur: "Violet ou Bleu" }, | ||||
|   "zebraide": { label: "Zebraïde", couleur: "Bandes Bicolores, toutes couleurs" } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * un pépin de gemme = 1/10 cm3 = 1/1000 l = 3.5/1000 kg = 7/2000 kg = 7/1000 enc | ||||
|  * densité 3.5 (~2.3 à 4, parfois plus) -- https://www.juwelo.fr/guide-des-pierres/faits-et-chiffres/  | ||||
|  */ | ||||
| const encPepin = 0.0007; | ||||
|  | ||||
| /** | ||||
|  * Item pour gérer les gemmes | ||||
|  */ | ||||
| export class RdDItemGemme extends RdDItem { | ||||
|  | ||||
|   static getGemmeTypeOptionList() { | ||||
|     // TODO: look how to map object key-value pairs | ||||
|     let options = "" | ||||
|     for (let gemmeKey in tableGemmes) { | ||||
|       options += `<option value="${gemmeKey}">${tableGemmes[gemmeKey].label}</option>` | ||||
|     } | ||||
|     return options; | ||||
|   } | ||||
|  | ||||
|   static get defaultIcon() { | ||||
|     return "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp" | ||||
|   } | ||||
|  | ||||
|   get isEnchantementPossible() { | ||||
|     return this.enchantabilite > 0 | ||||
|   } | ||||
|  | ||||
|   get inertie() { return 7 - Number(this.system.purete) } | ||||
|   get enchantabilite() { return this.system.taille - this.inertie } | ||||
|  | ||||
|   getEnc() { | ||||
|     return encPepin * this.system.taille; | ||||
|   } | ||||
|  | ||||
|   itemSpecificActions() { | ||||
|     return [ACTION_ITEM_ENCHANTER] | ||||
|   } | ||||
|  | ||||
|   prepareDerivedData() { | ||||
|     super.prepareDerivedData() | ||||
|     this.system.cout = (this.system.taille * this.system.purete) + this.system.qualite | ||||
|     this.system.inertie = this.inertie | ||||
|     this.system.enchantabilite = this.enchantabilite | ||||
|   } | ||||
|  | ||||
|   getUtilisation() { | ||||
|     switch (this.system.categorie) { | ||||
|       case 'Alchimie': case 'Autre': case 'AlchimieAutre': | ||||
|         // TODO: distinguer les remèdes alchimiques enchantables/non | ||||
|         return 'alchimie' | ||||
|       case 'Cuisine': | ||||
|         return 'cuisine' | ||||
|       case 'Remede': case 'Repos': case 'Soin': | ||||
|         return 'soins' | ||||
|     } | ||||
|     return '' | ||||
|   } | ||||
|  | ||||
|   getProprietes() { | ||||
|     const proprietes = [ | ||||
|       `<b>Taille</b>: ${this.system.taille}`, | ||||
|       `<b>Pureté</b>: ${this.system.purete}`, | ||||
|       `<b>Inertie</b>: ${this.system.inertie}`, | ||||
|       `<b>Enchantabilité</b>: ${this.system.enchantabilite}` | ||||
|     ] | ||||
|     const proprietesMagiques = this.system.magique ? [ | ||||
|       `<b>Enchantée</b> <i class="fa-solid fa-sparkles"></i> ${this.system.purifie ? ', purifiée' : ''} ${this.system.prpermanent ? 'permanente' : ''} `, | ||||
|       `<b>Points de rêve</b>: ${this.system.pr}`, | ||||
|       `<b>Puissance</b>: ${this.system.puissance}`, | ||||
|     ] : [] | ||||
|     return proprietes | ||||
|       .concat(proprietesMagiques) | ||||
|       .concat(this._inventaireTemplateChatData()) | ||||
|       .filter(it => it != undefined) | ||||
|   } | ||||
|  | ||||
|   perteReveChateauDormant() { | ||||
|     if (this.system.magique && !this.system.prpermanent && this.system.pr > 0) { | ||||
|       const nouveauReve = Math.max(this.system.pr - 1, 0) | ||||
|       return { | ||||
|         alias: this.parent.getAlias(), | ||||
|         item: this, | ||||
|         update: { | ||||
|           _id: this.id, | ||||
|           'system.pr': nouveauReve, | ||||
|           'system.magique': nouveauReve > 0 | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     return undefined | ||||
|   } | ||||
| } | ||||
							
								
								
									
										146
									
								
								module/item/item-actions.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										146
									
								
								module/item/item-actions.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,146 @@ | ||||
| import { Misc } from "../misc.js" | ||||
| import { RdDSheetUtility } from "../rdd-sheet-utility.js" | ||||
| import { RdDUtility } from "../rdd-utility.js" | ||||
|  | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * TODO: | ||||
|  * options.editable ? | ||||
|  *  | ||||
|  */ | ||||
| const _SPACEHOLDER = { placeholder: true } | ||||
|  | ||||
| const _VENDRE = { | ||||
|   code: 'item-vendre', label: 'Vendre ou donner', icon: it => 'fa-solid fa-comments-dollar', | ||||
|   filter: it => Misc.toInt(it.system.quantite) > 0, | ||||
|   optionsFilter: options => options.editable, | ||||
|   action: (item, actor) => item.proposerVente() | ||||
| } | ||||
| const _ACHAT_SERVICE = { | ||||
|   code: 'item-service-acheter', label: 'Acheter', icon: it => 'fa-regular fa-coins', | ||||
|   //filter: it => Misc.toInt(it.system.quantite) > 0, | ||||
|   //optionsFilter: options => options.editable, | ||||
|   //action: (item, actor) => item.proposerVente() | ||||
| } | ||||
| const _MONTRER = { | ||||
|   code: 'item-montrer', label: 'Montrer', icon: it => 'fa-solid fa-comment', | ||||
|   action: (item, actor) => item.postItemToChat() | ||||
| } | ||||
| const _SPLIT = { | ||||
|   code: 'item-split', label: 'Séparer le goupe', icon: it => 'fa-solid fa-unlink', | ||||
|   filter: it => Misc.toInt(it.system.quantite) > 1, | ||||
|   action: (item, actor) => RdDSheetUtility.splitItem(item, actor) | ||||
| } | ||||
|  | ||||
| const _EDIT = { | ||||
|   code: 'item-edit', label: 'Editer', icon: it => 'fa-solid fa-edit', | ||||
|   action: (item, actor) => item.sheet.render(true) | ||||
| } | ||||
| const _DELETE = { | ||||
|   code: 'item-delete', label: 'Supprimer', icon: it => 'fa-solid fa-trash', | ||||
|   optionsFilter: options => options.editable && options.isOwner, | ||||
|   action: (item, actor) => RdDUtility.confirmActorItemDelete(item, actor) | ||||
| } | ||||
| const _EQUIPER = { | ||||
|   code: 'item-equip', label: 'Equiper', icon: it => it.system.equipe ? 'fa-solid fa-hand-rock' : 'fa-regular fa-hand-paper', | ||||
|   filter: it => !it.estContenu && it.isEquipable(), | ||||
|   action: (item, actor) => actor.equiperObjet(item) | ||||
| } | ||||
|  | ||||
| const _CUISINER = { | ||||
|   code: 'item-cuisiner', label: 'Cuisiner', icon: it => 'fa-solid fa-utensils', | ||||
|   filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0, | ||||
|   optionsFilter: options => options.editable, | ||||
|   action: (item, actor) => actor.preparerNourriture(item) | ||||
| } | ||||
| const _MANGER_CRU = { | ||||
|   code: 'item-manger-cru', label: 'Manger cru', icon: it => 'fa-solid fa-drumstick-bite', | ||||
|   filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0, | ||||
|   optionsFilter: options => options.editable, | ||||
|   action: (item, actor) => actor.mangerNourriture(item) | ||||
| } | ||||
| const _MANGER = { | ||||
|   code: 'item-manger', label: 'Manger', icon: it => 'fa-solid fa-utensils', | ||||
|   filter: it => !(it.system.boisson), | ||||
|   optionsFilter: options => options.editable, | ||||
|   action: (item, actor) => actor.mangerNourriture(item) | ||||
| } | ||||
| const _BOIRE = { | ||||
|   code: 'item-boire', label: 'Boire', icon: it => 'fa-solid fa-glass-water', | ||||
|   filter: it => it.system.boisson, | ||||
|   optionsFilter: options => options.editable, | ||||
|   action: (item, actor) => actor.mangerNourriture(item) | ||||
| } | ||||
| const _DECOCTION = { | ||||
|   code: 'item-decoction', label: 'Décoction', icon: it => 'fa-solid fa-flask-vial', | ||||
|   optionsFilter: options => options.editable, | ||||
|   action: (item, actor) => actor.fabriquerDecoctionHerbe(item) | ||||
| } | ||||
| const _OUVRIR = { | ||||
|   code: 'item-edit', label: 'Ouvrir', icon: it => 'fa-solid fa-eye', | ||||
|   action: (item, actor) => item.sheet.render(true) | ||||
| } | ||||
|  | ||||
| const _LIRE = { | ||||
|   code: 'item-lire', label: 'Lire', icon: it => 'fa-solid fa-book-open', | ||||
|   optionsFilter: options => options.editable, | ||||
|   action: (item, actor) => actor.actionLire(item) | ||||
| } | ||||
|  | ||||
| const _REFOULER = { | ||||
|   code: 'item-refouler', label: 'Refouler', icon: it => 'fa-solid fa-burst', | ||||
|   filter: it => it.system.refoulement > 0, | ||||
|   optionsFilter: options => options.editable, | ||||
|   action: (item, actor) => actor.actionRefoulement(item) | ||||
| } | ||||
|  | ||||
| const _SORT_RESERVE = { | ||||
|   code: 'item-sortreserve-add', label: 'Ajouter en réserve', icon: it => 'fa-solid fa-sparkles', | ||||
|   filter: it => game.user.isGM && !it.system.isrituel, | ||||
|   action: (item, actor) => actor.addSortReserve(item) | ||||
| } | ||||
|  | ||||
| export const COMMON_ACTIONS = [_EQUIPER] | ||||
| export const DEFAULT_ACTIONS = [_SPACEHOLDER, _SPLIT, _VENDRE, _MONTRER, _EDIT, _DELETE] | ||||
|  | ||||
| export const ITEM_ACTIONS = { | ||||
|   faune: [_CUISINER, _MANGER_CRU], | ||||
|   ingredient: [_CUISINER, _MANGER_CRU], | ||||
|   conteneur: [_OUVRIR], | ||||
|   herbe: [_DECOCTION, _CUISINER, _MANGER_CRU], | ||||
|   livre: [_LIRE], | ||||
|   nourritureboisson: [_MANGER, _BOIRE], | ||||
|   ombre: [_REFOULER], | ||||
|   plante: [_CUISINER, _MANGER_CRU], | ||||
|   queue: [_REFOULER], | ||||
|   sort: [_SORT_RESERVE], | ||||
|   service: [_ACHAT_SERVICE] | ||||
| } | ||||
|  | ||||
|  | ||||
| export class ItemAction { | ||||
|  | ||||
|   static applies(action, item, options) { | ||||
|     return action && item | ||||
|       && item.isActionAllowed(action.code) | ||||
|       && (!action.filter || action.filter(item)) | ||||
|       && (!action.optionsFilter || action.optionsFilter(options)) | ||||
|   } | ||||
|  | ||||
|   static icon(action, item) { | ||||
|     if (action && action.icon) { | ||||
|       return action.icon(item) | ||||
|     } | ||||
|     return undefined | ||||
|   } | ||||
|  | ||||
|   static async onActionItem(event, actor, options) { | ||||
|     const item = RdDSheetUtility.getItem(event, actor) | ||||
|     const code = $(event.currentTarget).data('code') | ||||
|     const action = item?.itemActions().find(it => it.code == code) | ||||
|     if (action && (!action.optionsFilter || action.optionsFilter(options))) { | ||||
|       await action.action(item, actor) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -10,7 +10,7 @@ export class RdDItemMaladie extends RdDItem { | ||||
|   } | ||||
|  | ||||
|   async calculerFinPeriodeTemporel(debut) { | ||||
|     return await debut.addPeriode(this.system.periode.nombre, this.system.periode.unite); | ||||
|     return debut.addPeriode(this.system.periode.nombre, this.system.periode.unite); | ||||
|   } | ||||
|  | ||||
|   async onFinPeriode(oldTimestamp, newTimestamp) { | ||||
|   | ||||
| @@ -1,11 +1,8 @@ | ||||
| import { RdDItem } from "../item.js"; | ||||
| import { RdDItemQueue } from "./queue.js"; | ||||
|  | ||||
| export class RdDItemOmbre extends RdDItemQueue { | ||||
|  | ||||
| export class RdDItemOmbre extends RdDItem { | ||||
|   static get defaultIcon() { | ||||
|     return "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp"; | ||||
|   } | ||||
|  | ||||
|   async calculerFinPeriodeTemporel(debut) { | ||||
|     return await debut.appliquerDuree(this.system.duree, this.parent); | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -8,7 +8,7 @@ export class RdDItemPoison extends RdDItem { | ||||
|   } | ||||
|  | ||||
|   async calculerFinPeriodeTemporel(debut) { | ||||
|     return await debut.addPeriode(this.system.periode.nombre, this.system.periode.unite) ; | ||||
|     return debut.addPeriode(this.system.periode.nombre, this.system.periode.unite) ; | ||||
|   } | ||||
|  | ||||
|   async onFinPeriode(oldTimestamp, newTimestamp) { | ||||
|   | ||||
							
								
								
									
										105
									
								
								module/item/potion.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								module/item/potion.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| import { Grammar } from "../grammar.js"; | ||||
| import { RdDItem } from "../item.js"; | ||||
| import { SystemCompendiums } from "../settings/system-compendiums.js"; | ||||
| import { ACTION_ITEM_ENCHANTER } from "../enchantement/dialog-enchanter.js"; | ||||
|  | ||||
| // --- Actions sur les "potions" | ||||
| const _CONSOMMER_POTION = { | ||||
|   code: 'item-potion-consommer', label: 'Consommer', icon: it => 'fa-solid fa-vial', | ||||
|   optionsFilter: options => options.editable, | ||||
|   action: (item, actor) => actor.consommerPotion(item) | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Item pour gérer les potions | ||||
|  */ | ||||
| export class RdDItemPotion extends RdDItem { | ||||
|  | ||||
|   static async herbesSoins() { | ||||
|     return await RdDItemPotion.$listHerbes(it => Grammar.equalsInsensitive(it.system.categorie, 'Soin') && it.system.niveau > 0) | ||||
|   } | ||||
|   static async herbesRepos() { | ||||
|     return await RdDItemPotion.$listHerbes(it => Grammar.equalsInsensitive(it.system.categorie, 'Repos') && it.system.niveau > 0) | ||||
|   } | ||||
|  | ||||
|   static async $listHerbes(filter) { | ||||
|     const herbes = await SystemCompendiums.getWorldOrCompendiumItems('herbe', 'faune-flore-mineraux'); | ||||
|     return herbes.filter(filter) | ||||
|   } | ||||
|  | ||||
|   static get defaultIcon() { | ||||
|     return "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp" | ||||
|   } | ||||
|  | ||||
|   get isEnchantementPossible() { | ||||
|     return this.system.etat == 'Liquide' | ||||
|   } | ||||
|  | ||||
|   itemSpecificActions() { | ||||
|     return [_CONSOMMER_POTION, ACTION_ITEM_ENCHANTER] | ||||
|   } | ||||
|  | ||||
|   prepareDerivedData() { | ||||
|     super.prepareDerivedData() | ||||
|     this.system.puissance = this.system.magique ? this.calculPuissance() : 0 | ||||
|   } | ||||
|  | ||||
|   getUtilisation() { | ||||
|     switch (this.system.categorie) { | ||||
|       case 'Alchimie': case 'Autre': case 'AlchimieAutre': | ||||
|         // TODO: distinguer les remèdes alchimiques enchantables/non | ||||
|         return 'alchimie' | ||||
|       case 'Cuisine': | ||||
|         return 'cuisine' | ||||
|       case 'Remede': case 'Repos': case 'Soin': | ||||
|         return 'soins' | ||||
|     } | ||||
|     return '' | ||||
|   } | ||||
|  | ||||
|   getProprietes() { | ||||
|     const proprietes = [ | ||||
|       `<b>Rareté</b>: ${this.system.rarete} `, | ||||
|       `<b>Catégorie</b>: ${this.system.categorie}`, | ||||
|       `<b>Etat</b>: ${this.system.etat}` | ||||
|     ] | ||||
|     const proprietesMagiques = this.system.magique ? [ | ||||
|       `<b>Enchantée</b> <i class="fa-solid fa-sparkles"></i> ${this.system.purifie ? ', purifiée' : ''} ${this.system.prpermanent ? 'permanente' : ''} `, | ||||
|       `<b>Points de rêve</b>: ${this.system.pr}`, | ||||
|     ] : [] | ||||
|     return proprietes | ||||
|       .concat(proprietesMagiques) | ||||
|       .concat(this._inventaireTemplateChatData()) | ||||
|       .filter(it => it != undefined) | ||||
|   } | ||||
|  | ||||
|   perteReveChateauDormant() { | ||||
|     if (this.system.magique && !this.system.prpermanent && this.system.pr > 0) { | ||||
|       const nouveaupr = Math.max(this.system.pr - 1, 0) | ||||
|       return { | ||||
|         alias: this.parent.getAlias(), | ||||
|         item: this, | ||||
|         nouveaupr: nouveaupr, | ||||
|         update: { | ||||
|           _id: this.id, | ||||
|           'system.pr': nouveaupr, | ||||
|           'system.magique': nouveaupr > 0 | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     return undefined | ||||
|   } | ||||
|  | ||||
|   calculPuissance() { return this.system.herbebonus * this.system.pr } | ||||
|  | ||||
|   static buildHerbesList(listeHerbes, max) { | ||||
|     let list = {} | ||||
|     for (let herbe of listeHerbes) { | ||||
|       let brins = max - herbe.system.niveau; | ||||
|       list[herbe.name] = `${herbe.name} (Bonus: ${herbe.system.niveau}, Brins: ${brins})`; | ||||
|     } | ||||
|     list['Autre'] = 'Autre (Bonus: variable, Brins: variable)' | ||||
|     return list; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -6,8 +6,9 @@ export class RdDItemQueue extends RdDItem { | ||||
|     return "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp"; | ||||
|   } | ||||
|  | ||||
|   async calculerFinPeriodeTemporel(debut) { | ||||
|   async calculerFinPeriodeTemporel(timestamp) { | ||||
|     // décaller le début pour calcul correct si la queue dure 12h | ||||
|     const debut = timestamp.addMinutes(timestamp.indexMinute == 0 ? -1 : 0); | ||||
|     return await debut.appliquerDuree(this.system.duree, this.parent); | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -1,6 +1,7 @@ | ||||
| import { ITEM_TYPES, RdDItem } from "../item.js"; | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { RdDItem } from "../item.js"; | ||||
| import { Misc } from "../misc.js"; | ||||
| import { LIST_CARAC, RdDCarac } from "../rdd-carac.js"; | ||||
| import { LIST_CARAC_PERSONNAGE, RdDCarac } from "../rdd-carac.js"; | ||||
|  | ||||
| export class RdDItemRace extends RdDItem { | ||||
|  | ||||
| @@ -12,16 +13,18 @@ export class RdDItemRace extends RdDItem { | ||||
|  | ||||
|   static checkRacialMax(actor, code, value) { | ||||
|     const race = RdDItemRace.getRace(actor) | ||||
|     if (code == LIST_CARAC.force.code) { | ||||
|     if (code == LIST_CARAC_PERSONNAGE.force.code) { | ||||
|       if (!race.isForceValid(actor, value)) { | ||||
|         ui.notifications.warn(race.system.carac.force.limitmessage) | ||||
|         return false | ||||
|       } | ||||
|     } | ||||
|     const carac = RdDCarac.carac(code) | ||||
|     if (race.isMax(actor, code, value - 1)) { | ||||
|       ui.notifications.warn(`${value} est supérieure au maximum de ${carac.label}`) | ||||
|       return false | ||||
|     if (code == LIST_CARAC_PERSONNAGE.taille.code) { | ||||
|       const carac = RdDCarac.carac(code) | ||||
|       if (race.isMax(actor, code, value - 1)) { | ||||
|         ui.notifications.warn(`${value} est supérieure au maximum de ${carac.label}`) | ||||
|         return false | ||||
|       } | ||||
|     } | ||||
|     return true | ||||
|   } | ||||
| @@ -52,13 +55,18 @@ export class RdDItemRace extends RdDItem { | ||||
|  | ||||
|   isMax(actor, code, value = undefined) { | ||||
|     const path = RdDCarac.carac(code)?.path | ||||
|     if (path == undefined) { | ||||
|       // cas des caractéristiques dérivées, pas de max | ||||
|       return false | ||||
|     } | ||||
|     if (value == undefined) { | ||||
|       value = path ? foundry.utils.getProperty(actor, path) : 0 | ||||
|     } | ||||
|     if (code == LIST_CARAC.force.code) { | ||||
|     if (code == LIST_CARAC_PERSONNAGE.force.code) { | ||||
|       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) | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -4,9 +4,9 @@ const RARETE_FREQUENTE = { code: 'Frequente', label: 'Fréquente', frequence: 18 | ||||
| const RARETE_RARE = { code: 'Rare', label: 'Rare', frequence: 6, min: 3, max: 12 }; | ||||
| const RARETE_RARISSIME = { code: 'Rarissime', label: 'Rarissime', frequence: 2, min: 1, max: 4 }; | ||||
| const RARETE_INEXISTANT = { code: 'Inexistant', label: 'Inexistant', frequence: 0, min: 0, max: 0 }; | ||||
| const RARETE_EGALE = { code: 'eqal', label: 'Egal', frequence: 1, min: 1, max: 1 }; | ||||
| const RARETE_EGALE = { code: 'egal', label: 'Egal', frequence: 1, min: 1, max: 1 }; | ||||
|  | ||||
| const RARETES = [ | ||||
| export const RARETES = [ | ||||
|   RARETE_COMMUNE, | ||||
|   RARETE_FREQUENTE, | ||||
|   RARETE_RARE, | ||||
|   | ||||
| @@ -74,7 +74,7 @@ export class RdDRencontre extends RdDItem { | ||||
|   } | ||||
|  | ||||
|   async calculerFinPeriodeTemporel(debut) { | ||||
|     return await debut.nouvelleHeure().addHeures(12); | ||||
|     return debut.nouvelleHeure().addHeures(12); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -34,8 +34,8 @@ export class RdDItemInventaireSheet extends RdDItemSheet { | ||||
|     HtmlUtility.showControlWhen(this.html.find("div.description-milieu"), TYPE_ITEMS_NATURELS.includes(this.item.type)); | ||||
|  | ||||
|     if (!this.options.editable) return; | ||||
|     this.html.find("a.preparer-nourriture").click(event => this.preparerNourriture(event)); | ||||
|     this.html.find("a.manger-nourriture").click(event => this.mangerNourriture(event)); | ||||
|     this.html.find("a.preparer-nourriture").click(async event => await this.preparerNourriture(event)); | ||||
|     this.html.find("a.manger-nourriture").click(async event => await this.mangerNourriture(event)); | ||||
|  | ||||
|     this.html.find("input.input-selection-milieu").keypress(event => { | ||||
|       if (event.keyCode == '13') { | ||||
| @@ -43,11 +43,11 @@ export class RdDItemInventaireSheet extends RdDItemSheet { | ||||
|       } | ||||
|       event.stopPropagation(); | ||||
|     }) | ||||
|     this.html.find("a.milieu-add").click(event => this.onAddMilieu(event)); | ||||
|     this.html.find("div.environnement-milieu a.milieu-delete").click(event => this.onDeleteMilieu(event)); | ||||
|     this.html.find("div.environnement-milieu select.environnement-rarete").change(event => this.onChange(event, | ||||
|     this.html.find("a.milieu-add").click(async event => await this.onAddMilieu(event)); | ||||
|     this.html.find("div.environnement-milieu a.milieu-delete").click(async event => await this.onDeleteMilieu(event)); | ||||
|     this.html.find("div.environnement-milieu select.environnement-rarete").change(async event => await this.onChange(event, | ||||
|       updated => this.$changeRarete(event, updated))); | ||||
|     this.html.find("div.environnement-milieu input[name='environnement-frequence']").change(event => this.onChange(event, | ||||
|     this.html.find("div.environnement-milieu input[name='environnement-frequence']").change(async event => await this.onChange(event, | ||||
|       updated => this.$changeFrequence(event, updated))); | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -15,15 +15,15 @@ export class RdDBlessureItemSheet extends RdDItemSheet { | ||||
|  | ||||
|     if (!this.options.editable) return; | ||||
|  | ||||
|     this.html.find('[name="premierssoins-done"]').change(async event => { | ||||
|       await this.item.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } }); | ||||
|     }); | ||||
|     this.html.find('[name="soinscomplets-done"]').change(async event => { | ||||
|     this.html.find('[name="premierssoins-done"]').change(async event => | ||||
|       await this.item.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } }) | ||||
|     ) | ||||
|     this.html.find('[name="soinscomplets-done"]').change(async event => | ||||
|       await this.item.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } }) | ||||
|     }); | ||||
|     ) | ||||
|     this.html.find('[name="system-gravite"]').change(async event => { | ||||
|       const gravite = Number(event.currentTarget.value) | ||||
|       await this.item.setSoinsBlessure({ gravite: gravite, difficulte: - gravite }) | ||||
|     }); | ||||
|     }) | ||||
|   } | ||||
| } | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| import { RdDBaseActorSheet } from "../actor/base-actor-sheet.js"; | ||||
| import { ITEM_TYPES } from "../item.js"; | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { RdDSheetUtility } from "../rdd-sheet-utility.js"; | ||||
| import { RdDUtility } from "../rdd-utility.js"; | ||||
| import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js"; | ||||
| @@ -29,9 +29,10 @@ export class RdDConteneurItemSheet extends RdDItemInventaireSheet { | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   prepareConteneurData(formData) { | ||||
|     RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes); | ||||
|     RdDUtility.filterItemsPerTypeForSheet(formData, this.actor.itemTypes); | ||||
|     this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires); | ||||
|     formData.subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems; | ||||
|     const subItems = formData.conteneurs.find(it => it._id == this.item.id)?.subItems; | ||||
|     formData.subItems = subItems | ||||
|   } | ||||
|  | ||||
|   async _onDragStart(event) { | ||||
|   | ||||
| @@ -9,7 +9,7 @@ export class RdDFauneItemSheet extends RdDItemInventaireSheet { | ||||
|  | ||||
|     if (!this.options.editable) return; | ||||
|  | ||||
|     html.find("a.linked-actor-delete").click(event => this.onDeleteLinkedActor()); | ||||
|     html.find("a.linked-actor-delete").click(async event => await this.onDeleteLinkedActor()); | ||||
|   } | ||||
|  | ||||
|   async _onDropActor(event, dragData) { | ||||
|   | ||||
							
								
								
									
										38
									
								
								module/item/sheet-gemme.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								module/item/sheet-gemme.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { DialogEnchanter } from "../enchantement/dialog-enchanter.js"; | ||||
| import { RdDTimestamp } from "../time/rdd-timestamp.js"; | ||||
| import { RdDItemGemme } from "./gemme.js"; | ||||
| import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js"; | ||||
|  | ||||
| export class RdDGemmeItemSheet extends RdDItemInventaireSheet { | ||||
|  | ||||
|   static get ITEM_TYPE() { return ITEM_TYPES.gemme }; | ||||
|  | ||||
|   async getData() { | ||||
|     const formData = foundry.utils.mergeObject(await super.getData(), | ||||
|       { | ||||
|         inertie: this.item.inertie, | ||||
|         enchantabilite: this.item.enchantabilite, | ||||
|         isEnchantementPossible: this.item.isEnchantementPossible, | ||||
|         gemmeTypeList: RdDItemGemme.getGemmeTypeOptionList(), | ||||
|         dateActuelle: game.system.rdd.calendrier.dateCourante(), | ||||
|         enchantement: RdDTimestamp.splitIndexDate(this.item.system.prdate) | ||||
|       }) | ||||
|     return formData | ||||
|   } | ||||
|  | ||||
|   activateListeners(html) { | ||||
|     super.activateListeners(html); | ||||
|  | ||||
|     this.html.find('.item-enchanter').click((event) => DialogEnchanter.enchanter(this.item)) | ||||
|  | ||||
|     this.html.find('.date-enchantement').change((event) => { | ||||
|       const jour = Number(this.html.find('input.date-enchantement[name="enchantement.jour"]').val()) | ||||
|       const mois = RdDTimestamp.definition(this.html.find('select.date-enchantement[name="enchantement.mois"]').val()) | ||||
|       const indexDate = game.system.rdd.calendrier.getIndexFromDate(jour, mois.heure) | ||||
|       this.item.update({ 'system.prdate': indexDate }) | ||||
|       console.warn(`Date d'enchantement modifiée ${jour}/${mois.heure}: ${indexDate}`) | ||||
|     }); | ||||
|  | ||||
|   } | ||||
| } | ||||
							
								
								
									
										57
									
								
								module/item/sheet-potion.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								module/item/sheet-potion.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { DialogEnchanter } from "../enchantement/dialog-enchanter.js"; | ||||
| import { RdDTimestamp } from "../time/rdd-timestamp.js"; | ||||
| import { RdDItemPotion } from "./potion.js"; | ||||
| import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js"; | ||||
|  | ||||
|  | ||||
| export class RdDPotionItemSheet extends RdDItemInventaireSheet { | ||||
|  | ||||
|   static get ITEM_TYPE() { return ITEM_TYPES.potion }; | ||||
|  | ||||
|   static $calculBonusHerbe(formData, herbesList, max) { | ||||
|     if (Number(formData.system.herbebrins)) { | ||||
|       let herbe = herbesList.find(h => h.name.toLowerCase() == formData.system.herbe.toLowerCase()); | ||||
|       if (herbe) { | ||||
|         const brinsRequis = max - herbe.system.niveau; | ||||
|         const brinsManquants = Math.max(brinsRequis - formData.system.herbebrins, 0); | ||||
|         formData.system.herbebonus = Math.max(herbe.system.niveau - brinsManquants, 0); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   async getData() { | ||||
|     const formData = await super.getData() | ||||
|     formData.isEnchantementPossible = this.item.isEnchantementPossible | ||||
|     formData.isSoins = this.item.categorie == 'Soin' | ||||
|     formData.isRepos = this.item.categorie == 'Repos' | ||||
|     if (formData.isSoins) { | ||||
|       const herbesSoins = await RdDItemPotion.herbesSoins() | ||||
|       RdDPotionItemSheet.$calculBonusHerbe(formData, herbesSoins, 12); | ||||
|       formData.herbesSoins = RdDItemPotion.buildHerbesList(herbesSoins, 12) | ||||
|     } | ||||
|     if (formData.isRepos) { | ||||
|       const herbesRepos = await RdDItemPotion.herbesRepos() | ||||
|       RdDPotionItemSheet.$calculBonusHerbe(formData, herbesRepos, 7); | ||||
|       formData.herbesRepos = RdDItemPotion.buildHerbesList(herbesRepos, 7) | ||||
|     } | ||||
|     formData.dateActuelle = game.system.rdd.calendrier.dateCourante() | ||||
|     formData.enchantement = RdDTimestamp.splitIndexDate(this.item.system.prdate) | ||||
|     return formData | ||||
|   } | ||||
|  | ||||
|   activateListeners(html) { | ||||
|     super.activateListeners(html); | ||||
|  | ||||
|     this.html.find('.item-enchanter').click((event) => DialogEnchanter.enchanter(this.item)) | ||||
|  | ||||
|     this.html.find('.date-enchantement').change((event) => { | ||||
|       const jour = Number(this.html.find('input.date-enchantement[name="enchantement.jour"]').val()) | ||||
|       const mois = RdDTimestamp.definition(this.html.find('select.date-enchantement[name="enchantement.mois"]').val()) | ||||
|       const indexDate = game.system.rdd.calendrier.getIndexFromDate(jour, mois.heure) | ||||
|       this.item.update({ 'system.prdate': indexDate }) | ||||
|       console.warn(`Date d'enchantement modifiée ${jour}/${mois.heure}: ${indexDate}`) | ||||
|     }); | ||||
|  | ||||
|   } | ||||
| } | ||||
| @@ -44,8 +44,8 @@ export class RdDRencontreItemSheet extends RdDItemSheet { | ||||
|   activateListeners(html) { | ||||
|     super.activateListeners(html); | ||||
|     if (!this.options.editable) return; | ||||
|     this.html.find("a.effet-add").click(event => this.onAddEffet(event)); | ||||
|     this.html.find("a.effet-delete").click(event => this.onDeleteEffet(event)); | ||||
|     this.html.find("a.effet-add").click(async event => await this.onAddEffet(event)); | ||||
|     this.html.find("a.effet-delete").click(async event => await this.onDeleteEffet(event)); | ||||
|   } | ||||
|  | ||||
|   async onAddEffet(event) { | ||||
|   | ||||
| @@ -36,9 +36,9 @@ export class RdDSigneDraconiqueItemSheet extends RdDItemSheet { | ||||
|  | ||||
|     if (!this.options.editable) return; | ||||
|  | ||||
|     html.find(".signe-aleatoire").click(event => this.setSigneAleatoire()); | ||||
|     html.find("input.select-tmr").change(event => this.onSelectTmr(event)); | ||||
|     html.find(".signe-xp-sort").change(event => this.onValeurXpSort(event.currentTarget.attributes['data-typereussite']?.value, Number(event.currentTarget.value))); | ||||
|     html.find(".signe-aleatoire").click(async event => await this.setSigneAleatoire()); | ||||
|     html.find("input.select-tmr").change(async event => await this.onSelectTmr(event)); | ||||
|     html.find(".signe-xp-sort").change(async event => await this.onValeurXpSort(event.currentTarget.attributes['data-typereussite']?.value, Number(event.currentTarget.value))); | ||||
|   } | ||||
|  | ||||
|   async setSigneAleatoire() { | ||||
|   | ||||
| @@ -106,7 +106,7 @@ export class RdDItemSigneDraconique extends RdDItem { | ||||
|   } | ||||
|  | ||||
|   static async randomSigneDescription() { | ||||
|     return await RdDRollTables.drawTextFromRollTable("Signes draconiques", false); | ||||
|     return await RdDRollTables.drawTextFromRollTable("Signes draconiques", {toChat:false}); | ||||
|    } | ||||
|  | ||||
| } | ||||
| @@ -1,5 +1,6 @@ | ||||
| import { ITEM_TYPES } from "../constants.js"; | ||||
| import { RdDItem } from "../item.js"; | ||||
| import { Grammar } from "../grammar.js" | ||||
| import { ITEM_TYPES, RdDItem } from "../item.js" | ||||
| import { SystemCompendiums } from "../settings/system-compendiums.js" | ||||
|  | ||||
| const DON_HAUT_REVE = "Don de Haut-Rêve" | ||||
|   | ||||
							
								
								
									
										29
									
								
								module/journal/journal-sheet.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								module/journal/journal-sheet.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js"; | ||||
| import { SYSTEM_RDD } from "../constants.js"; | ||||
| import { Misc } from "../misc.js"; | ||||
|  | ||||
|  | ||||
| export class RdDJournalSheet extends JournalTextPageSheet { | ||||
|   static register() { | ||||
|     DocumentSheetConfig.unregisterSheet(JournalEntryPage, "core", JournalTextPageSheet) | ||||
|     DocumentSheetConfig.registerSheet(JournalEntryPage, | ||||
|       SYSTEM_RDD, | ||||
|       RdDJournalSheet, { | ||||
|       types: ["text"], | ||||
|       makeDefault: true, | ||||
|     }); | ||||
|   } | ||||
|  | ||||
|   async getData(options) { | ||||
|     const journalData = await super.getData(options); | ||||
|     journalData.editor.content = await RdDTextEditor.enrichHTML(journalData.document.text.content, this.object) | ||||
|     return journalData | ||||
|   } | ||||
|  | ||||
|   activateListeners(html) { | ||||
|     super.activateListeners(html); | ||||
|  | ||||
|     html.find('.roll-text').click(async event => await RdDTextEditor.rollText(event, this.actor)) | ||||
|     html.find('.chat-roll-text').click(async event => await RdDTextEditor.chatRollText(event)) | ||||
|   } | ||||
| } | ||||
| @@ -2,7 +2,8 @@ import { RdDBaseActor } from "./actor/base-actor.js"; | ||||
| import { LOG_HEAD, SYSTEM_RDD } from "./constants.js"; | ||||
| import { Grammar } from "./grammar.js"; | ||||
| import { Monnaie } from "./item-monnaie.js"; | ||||
| import { RdDItem, ITEM_TYPES, ACTOR_TYPES } from "./item.js"; | ||||
| import { ITEM_TYPES, ACTOR_TYPES } from "./constants.js"; | ||||
| import { RdDItem } from "./item.js"; | ||||
| import { RdDTimestamp } from "./time/rdd-timestamp.js"; | ||||
| import { RdDRaretes } from "./item/raretes.js"; | ||||
| import { VOIES_DRACONIC } from "./item-sort.js"; | ||||
| @@ -588,6 +589,55 @@ class _12_0_32_MigrationRaces extends Migration { | ||||
|   } | ||||
| } | ||||
|  | ||||
| class _12_0_37_MigrationAlchimieEtat extends Migration { | ||||
|   get code() { return "migration-alchimie-etat" } | ||||
|   get version() { return "12.0.37" } | ||||
|  | ||||
|   async migrate() { | ||||
|     await this.applyItemsUpdates(items => items | ||||
|       .filter(it => [ITEM_TYPES.potion].includes(it.type)) | ||||
|       .map(it => this.migratePotion(it)) | ||||
|     ) | ||||
|   } | ||||
|  | ||||
|   mappingCategorie(categorie) { | ||||
|     switch (categorie) { | ||||
|       case 'AlchimieEnchante': return 'Alchimie' | ||||
|       case 'ReposEnchante': return 'Repos' | ||||
|       case 'SoinEnchante': return 'Soin' | ||||
|       case 'AutreEnchante': return 'Autre' | ||||
|     } | ||||
|     return categorie | ||||
|   } | ||||
|  | ||||
|   mappingEtat(categorie) { | ||||
|     return ['Alchimie', 'Repos', 'Soin', 'Autre'].includes(categorie) ? 'Liquide' : 'Autre' | ||||
|   } | ||||
|  | ||||
|   migratePotion(potion) { | ||||
|     const newCategorie = this.mappingCategorie(potion.system.categorie) | ||||
|     return { | ||||
|       _id: potion.id, | ||||
|       'system.etat': this.mappingEtat(potion.system.categorie), | ||||
|       'system.magique': potion.system.pr > 0, | ||||
|       'system.categorie': newCategorie | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| class _12_0_38_TachesEcriture extends Migration { | ||||
|   get code() { return "migration-tache-ecriture" } | ||||
|   get version() { return "12.0.38" } | ||||
|  | ||||
|   async migrate() { | ||||
|     await this.applyItemsUpdates(items => items | ||||
|       .filter(it => [ITEM_TYPES.tache, ITEM_TYPES.livre, ITEM_TYPES.oeuvre, ITEM_TYPES.meditation].includes(it.type) ) | ||||
|       .filter(it => it.system.competence == 'Ecriture') | ||||
|       .map(it => { return { _id: it.id, 'system.competence': 'Écriture' } }) | ||||
|     ) | ||||
|   } | ||||
| } | ||||
|  | ||||
| export class Migrations { | ||||
|   static getMigrations() { | ||||
|     return [ | ||||
| @@ -609,6 +659,8 @@ export class Migrations { | ||||
|       new _11_2_20_MigrationAstrologie(), | ||||
|       new _12_0_26_MigrationVoieSorts(), | ||||
|       new _12_0_32_MigrationRaces(), | ||||
|       new _12_0_37_MigrationAlchimieEtat(), | ||||
|       new _12_0_38_TachesEcriture() | ||||
|     ]; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -238,7 +238,7 @@ export class Misc { | ||||
|   /* -------------------------------------------- */ | ||||
|   static findFirstLike(value, elements, options = {}) { | ||||
|     options = foundry.utils.mergeObject(DEFAULT_FIND_OPTIONS, options, { overwrite: true, inplace: false }); | ||||
|     const subset = this.findAllLike(value, elements, options); | ||||
|     const subset = this.findAllLike(value, elements, options) | ||||
|     if (subset.length == 0) { | ||||
|       console.log(`Aucune ${options.description} pour ${value}`); | ||||
|       return undefined | ||||
| @@ -263,8 +263,9 @@ export class Misc { | ||||
|     } | ||||
|     value = Grammar.toLowerCaseNoAccent(value); | ||||
|     const subset = elements.filter(options.preFilter) | ||||
|       .filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value)); | ||||
|     if (subset.length == 0) { | ||||
|       .filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value)) | ||||
|       .sort(Misc.ascending(it => options.mapper(it))) | ||||
|     if (subset.length == 0 && options?.onMessage) { | ||||
|       options.onMessage(`Pas de ${options.description} correspondant à ${value}`); | ||||
|     } | ||||
|     return subset; | ||||
|   | ||||
| @@ -1,48 +1,8 @@ | ||||
| /* -------------------------------------------- */ | ||||
| import { Misc } from "./misc.js"; | ||||
|  | ||||
| const matchOperations = new RegExp(/@(\w*){([\w\-]+)}/ig); | ||||
| const matchOperationTerms = new RegExp(/@(\w*){([\w\-]+)}/i); | ||||
| /* -------------------------------------------- */ | ||||
| export class RdDAlchimie { | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static processManipulation(recette, actorId = undefined) { | ||||
|     let manip = recette.system.manipulation; | ||||
|     let matchArray = manip.match(matchOperations); | ||||
|     if (matchArray) { | ||||
|       for (let matchStr of matchArray) { | ||||
|         let result = matchStr.match(matchOperationTerms); | ||||
|         if (result[1] && result[2]) { | ||||
|           let commande = Misc.upperFirst(result[1]); | ||||
|           let replacement = this[`_alchimie${commande}`](recette, result[2], actorId); | ||||
|           manip = manip.replace(result[0], replacement); | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|     recette.system.manipulation_update = manip; | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static _alchimieCouleur(recette, couleurs, actorId) { | ||||
|     return RdDAlchimie._alchimieLink(recette, couleurs, actorId,  'couleur',  'Température'); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static _alchimieConsistance(recette, consistances, actorId) { | ||||
|     return RdDAlchimie._alchimieLink(recette, consistances, actorId,  'consistance',  'Consistance'); | ||||
|   } | ||||
|  | ||||
|   static _alchimieLink(recette, termes, actorId, tacheAlchimie, labelTache) { | ||||
|     const difficulte = RdDAlchimie.getDifficulte(termes); | ||||
|     const link = actorId ? ` <a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="${tacheAlchimie}" data-alchimie-data="${termes}">` : ''; | ||||
|     const endLink = actorId ? '</a>' : ''; | ||||
|     return `<span class="alchimie-tache">${link}${labelTache} ${termes} (${difficulte})${endLink}</span>`; | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static getDifficulte(aspects) { | ||||
|     let elements = aspects.split('-'); | ||||
|   static getDifficulte(termes) { | ||||
|     let elements = termes.split('-'); | ||||
|     let composantes = elements.length; | ||||
|     let distincts = Object.keys(Misc.classifyFirst(elements, it => it)).length; | ||||
|     if (distincts == 1) { | ||||
| @@ -58,5 +18,4 @@ export class RdDAlchimie { | ||||
|     } | ||||
|     return 'intellect'; | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -37,7 +37,7 @@ const TABLE_CARACTERISTIQUES_DERIVEES = { | ||||
|   32: { xp: 180, niveau: 11, poids: "1501-2000", poidsMin: 1501, poidsMax: 2000, plusdom: +11, sconst: 10, sust: 17 } | ||||
| }; | ||||
|  | ||||
| export const LIST_CARAC = { | ||||
| export const LIST_CARAC_PERSONNAGE = { | ||||
|   'taille': { code: 'taille', label: 'Taille', isCarac: true, path: 'system.carac.taille.value' }, | ||||
|   'apparence': { code: 'apparence', label: 'Apparence', isCarac: true, path: 'system.carac.apparence.value' }, | ||||
|   'constitution': { code: 'constitution', label: 'Constitution', isCarac: true, path: 'system.carac.constitution.value' }, | ||||
| @@ -56,18 +56,43 @@ export const LIST_CARAC = { | ||||
|   'beaute': { code: 'beaute', label: 'Beauté', isCarac: false, path: 'system.background.beaute.value' } | ||||
| } | ||||
|  | ||||
| export const LIST_CARAC_AUTRES = { | ||||
|   'perception': { code: 'perception', label: 'Perception', path: 'system.carac.perception.value' }, | ||||
| } | ||||
|  | ||||
| const LIST_CARAC_DERIVEE = { | ||||
|   'melee': { code: "melee", label: 'Mêlée', path: 'system.carac.melee.value' }, | ||||
|   'tir': { code: "tir", label: 'Tir', path: 'system.carac.tir.value' }, | ||||
|   'lancer': { code: "lancer", label: 'Lancer', path: 'system.carac.lancer.value' }, | ||||
|   'derobee': { code: "derobee", label: 'Dérobée', path: 'system.carac.derobee.value' }, | ||||
|   'chance-actuelle': { code: "chance-actuelle", label: 'Chance actuelle', path: 'system.carac.lancer.value' }, | ||||
|   'reve-actuel': { code: "reve-actuel", label: 'Rêve actuel', path: 'system.reve.reve.value' }, | ||||
| } | ||||
|  | ||||
| const LIST_CARAC_ROLL = Object.values(LIST_CARAC_PERSONNAGE).filter(it => it.isCarac && it.code != 'taille') | ||||
|   .concat(Object.values(LIST_CARAC_AUTRES)) | ||||
|   .concat(Object.values(LIST_CARAC_DERIVEE)) | ||||
|  | ||||
| export class RdDCarac { | ||||
|  | ||||
|   static caracDetails(name, options = { onMessage: undefined }) { | ||||
|     let entry = Misc.findFirstLike(name, LIST_CARAC_ROLL, { mapper: it => it.code, description: 'caractéristique', onMessage: m => { } }) | ||||
|     if (entry) { | ||||
|       return entry | ||||
|     } | ||||
|     return Misc.findFirstLike(name, LIST_CARAC_ROLL, { mapper: it => it.label, description: 'caractéristique', onMessage: options.onMessage }) | ||||
|   } | ||||
|  | ||||
|   static carac(code) { | ||||
|     return LIST_CARAC[code] | ||||
|     return LIST_CARAC_PERSONNAGE[code] | ||||
|   } | ||||
|  | ||||
|   static label(code) { | ||||
|     return  RdDCarac.carac(code)?.label ?? '---' | ||||
|   }   | ||||
|     return RdDCarac.carac(code)?.label ?? '---' | ||||
|   } | ||||
|  | ||||
|   static caracs(filter = it => it.isCarac) { | ||||
|     return Object.values(LIST_CARAC).filter(filter) | ||||
|     return Object.values(LIST_CARAC_PERSONNAGE).filter(filter) | ||||
|   } | ||||
|  | ||||
|   static isAgiliteOuDerobee(selectedCarac) { | ||||
|   | ||||
| @@ -13,6 +13,7 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; | ||||
| import { STATUSES } from "./settings/status-effects.js"; | ||||
| import { Targets } from "./targets.js"; | ||||
| import { RdDEmpoignade } from "./rdd-empoignade.js"; | ||||
| import { RdDRollResult } from "./rdd-roll-result.js"; | ||||
|  | ||||
| /* -------------------------------------------- */ | ||||
| const premierRoundInit = [ | ||||
| @@ -361,7 +362,7 @@ export class RdDCombatManager extends Combat { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static listActionsActorCombatant( actor) { | ||||
|   static listActionsActorCombatant(actor) { | ||||
|     const possessions = actor.listActionsPossessions() | ||||
|     const actions = possessions.length > 0 | ||||
|       ? possessions | ||||
| @@ -472,15 +473,15 @@ export class RdDCombat { | ||||
|   /* -------------------------------------------- */ | ||||
|   static registerChatCallbacks(html) { | ||||
|     for (let button of [ | ||||
|       '#parer-button', | ||||
|       '#esquiver-button', | ||||
|       '#particuliere-attaque', | ||||
|       '#encaisser-button', | ||||
|       '#appel-chance-defense', | ||||
|       '#appel-destinee-defense', | ||||
|       '#appel-chance-attaque', | ||||
|       '#appel-destinee-attaque', | ||||
|       '#echec-total-attaque', | ||||
|       '.parer-button', | ||||
|       '.esquiver-button', | ||||
|       '.particuliere-attaque', | ||||
|       '.encaisser-button', | ||||
|       '.appel-chance-defense', | ||||
|       '.appel-destinee-defense', | ||||
|       '.appel-chance-attaque', | ||||
|       '.appel-destinee-attaque', | ||||
|       '.echec-total-attaque', | ||||
|     ]) { | ||||
|       html.on("click", button, event => { | ||||
|         const rddCombat = RdDCombat.rddCombatForAttackerAndDefender( | ||||
| @@ -539,22 +540,22 @@ export class RdDCombat { | ||||
|     const compId = event.currentTarget.attributes['data-compid']?.value; | ||||
|  | ||||
|     switch (button) { | ||||
|       case '#particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value); | ||||
|       case '#parer-button': return this.parade(attackerRoll, armeParadeId); | ||||
|       case '#esquiver-button': return this.esquive(attackerRoll, compId, competence); | ||||
|       case '#encaisser-button': return this.encaisser(attackerRoll, defenderRoll); | ||||
|       case '#echec-total-attaque': return this._onEchecTotal(attackerRoll); | ||||
|       case '.particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value); | ||||
|       case '.parer-button': return this.parade(attackerRoll, armeParadeId); | ||||
|       case '.esquiver-button': return this.esquive(attackerRoll, compId, competence); | ||||
|       case '.encaisser-button': return this.encaisser(attackerRoll, defenderRoll); | ||||
|       case '.echec-total-attaque': return this._onEchecTotal(attackerRoll); | ||||
|  | ||||
|       case '#appel-chance-attaque': return this.attacker.rollAppelChance( | ||||
|       case '.appel-chance-attaque': return this.attacker.rollAppelChance( | ||||
|         () => this.attaqueChanceuse(attackerRoll), | ||||
|         () => this._onEchecTotal(attackerRoll)); | ||||
|       case '#appel-chance-defense': return this.defender.rollAppelChance( | ||||
|       case '.appel-chance-defense': return this.defender.rollAppelChance( | ||||
|         () => this.defenseChanceuse(attackerRoll, defenderRoll), | ||||
|         () => this.afficherOptionsDefense(attackerRoll, defenderRoll, { defenseChance: true })); | ||||
|       case '#appel-destinee-attaque': return this.attacker.appelDestinee( | ||||
|       case '.appel-destinee-attaque': return this.attacker.appelDestinee( | ||||
|         () => this.attaqueSignificative(attackerRoll), | ||||
|         () => { }); | ||||
|       case '#appel-destinee-defense': return this.defender.appelDestinee( | ||||
|       case '.appel-destinee-defense': return this.defender.appelDestinee( | ||||
|         () => this.defenseDestinee(defenderRoll), | ||||
|         () => { }); | ||||
|     } | ||||
| @@ -667,7 +668,7 @@ export class RdDCombat { | ||||
|         const activite = this._ajustementMouvement(this.defender) | ||||
|         const total = [portee, taille, activite].map(it => it.diff).filter(d => !Number.isNaN(d)).reduce(Misc.sum(), 0) | ||||
|         ChatMessage.create({ | ||||
|           content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.html', { | ||||
|           content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.hbs', { | ||||
|             rollData: rollData, | ||||
|             attacker: _token, | ||||
|             isVisible: isVisible, | ||||
| @@ -734,7 +735,7 @@ export class RdDCombat { | ||||
|     await this.proposerAjustementTirLancer(rollData) | ||||
|  | ||||
|     const dialog = await RdDRoll.create(this.attacker, rollData, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' }, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs' }, | ||||
|       { | ||||
|         name: 'jet-attaque', | ||||
|         label: 'Attaque: ' + (arme?.name ?? competence.name), | ||||
| @@ -742,11 +743,8 @@ export class RdDCombat { | ||||
|           this.attacker.createCallbackExperience(), | ||||
|           this.attacker.createCallbackAppelAuMoral(), | ||||
|           { action: r => this.removeChatMessageActionsPasseArme(r.passeArme) }, | ||||
|           { condition: r => arme && !RdDCombat.isParticuliere(r), action: r => this.attacker.incDecItemUse(arme._id) }, | ||||
|           { condition: r => (RdDCombat.isReussite(r) && !RdDCombat.isParticuliere(r)), action: r => this._onAttaqueNormale(r) }, | ||||
|           { condition: RdDCombat.isParticuliere, action: r => this._onAttaqueParticuliere(r) }, | ||||
|           { condition: RdDCombat.isEchec, action: r => this._onAttaqueEchec(r) }, | ||||
|           { condition: RdDCombat.isEchecTotal, action: r => this._onAttaqueEchecTotal(r) }, | ||||
|           { action: async r => await this.attacker.incDecItemUse(arme._id, arme && !RdDCombat.isParticuliere(r)) }, | ||||
|           { action: r => this._onAttaque(r) }, | ||||
|         ] | ||||
|       }); | ||||
|     dialog.render(true); | ||||
| @@ -782,9 +780,23 @@ export class RdDCombat { | ||||
|     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) { | ||||
|  | ||||
|     const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0; | ||||
|     // force toujours, sauf empoignade | ||||
|     // finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum | ||||
| @@ -806,7 +818,7 @@ export class RdDCombat { | ||||
|     const choixParticuliere = await ChatMessage.create({ | ||||
|       alias: this.attacker.getAlias(), | ||||
|       whisper: ChatUtility.getOwners(this.attacker), | ||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.html', { | ||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-particuliere.hbs', { | ||||
|         alias: this.attacker.getAlias(), | ||||
|         attackerId: this.attackerId, | ||||
|         attackerToken: this.attackerToken, | ||||
| @@ -830,13 +842,13 @@ export class RdDCombat { | ||||
|       cible: this.defender?.getAlias() ?? 'la cible', | ||||
|       isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge') | ||||
|     } | ||||
|     await RdDResolutionTable.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.html'); | ||||
|     await RdDRollResult.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.hbs'); | ||||
|  | ||||
|     if (!await this.attacker.accorder(this.defender, 'avant-defense')) { | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     if (this.target) { | ||||
|     if (this.defender) { | ||||
|       await this._sendMessageDefense(attackerRoll, defenderRoll); | ||||
|     } | ||||
|   } | ||||
| @@ -895,7 +907,7 @@ export class RdDCombat { | ||||
|       speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)), | ||||
|       alias: this.attacker?.getAlias(), | ||||
|       whisper: ChatUtility.getOwners(this.defender), | ||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html', paramDemandeDefense), | ||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', paramDemandeDefense), | ||||
|     }); | ||||
|     // flag pour garder les jets d'attaque/defense | ||||
|     ChatUtility.setMessageData(choixDefense, 'defender-roll', defenderRoll); | ||||
| @@ -940,7 +952,7 @@ export class RdDCombat { | ||||
|   async _onAttaqueEchecTotal(attackerRoll) { | ||||
|     const choixEchecTotal = await ChatMessage.create({ | ||||
|       whisper: ChatUtility.getOwners(this.attacker), | ||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', { | ||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.hbs', { | ||||
|         attackerId: this.attackerId, | ||||
|         attacker: this.attacker, | ||||
|         attackerToken: this.attackerToken, | ||||
| @@ -964,23 +976,20 @@ export class RdDCombat { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async _onAttaqueEchec(rollData) { | ||||
|     console.log("RdDCombat.onAttaqueEchec >>>", rollData); | ||||
|     await RdDResolutionTable.displayRollData(rollData, this.attacker, 'chat-resultat-attaque.html'); | ||||
|  | ||||
|   async _onAttaqueEchec(attackerRoll) { | ||||
|     console.log("RdDCombat.onAttaqueEchec >>>", attackerRoll); | ||||
|     await RdDRollResult.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.hbs'); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async choixParticuliere(rollData, choix) { | ||||
|     console.log("RdDCombat.choixParticuliere >>>", rollData, choix); | ||||
|  | ||||
|     if (choix != "rapidite") { | ||||
|       this.attacker.incDecItemUse(rollData.arme.id); | ||||
|     } | ||||
|     await this.attacker.incDecItemUse(rollData.arme.id, choix != "rapidite") | ||||
|  | ||||
|     this.removeChatMessageActionsPasseArme(rollData.passeArme); | ||||
|     rollData.particuliere = choix; | ||||
|     await this._onAttaqueNormale(rollData); | ||||
|     await this._onAttaqueNormale(rollData) | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
| @@ -996,7 +1005,7 @@ export class RdDCombat { | ||||
|     let rollData = this._prepareParade(attackerRoll, arme, competence); | ||||
|  | ||||
|     const dialog = await RdDRoll.create(this.defender, rollData, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' }, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs' }, | ||||
|       { | ||||
|         name: 'jet-parade', | ||||
|         label: 'Parade: ' + (arme ? arme.name : rollData.competence.name), | ||||
| @@ -1004,10 +1013,8 @@ export class RdDCombat { | ||||
|           this.defender.createCallbackExperience(), | ||||
|           this.defender.createCallbackAppelAuMoral(), | ||||
|           { action: r => this.removeChatMessageActionsPasseArme(r.passeArme) }, | ||||
|           { condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(armeParadeId) }, | ||||
|           { condition: RdDCombat.isReussite, action: r => this._onParadeNormale(r) }, | ||||
|           { condition: RdDCombat.isParticuliere, action: r => this._onParadeParticuliere(r) }, | ||||
|           { condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) }, | ||||
|           { action: async r => await this.defender.incDecItemUse(armeParadeId, !RdDCombat.isParticuliere(r)) }, | ||||
|           { action: r => this._onParade(r) }, | ||||
|         ] | ||||
|       }); | ||||
|     dialog.render(true); | ||||
| @@ -1038,8 +1045,19 @@ export class RdDCombat { | ||||
|     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); | ||||
|     if (!defenderRoll.attackerRoll.isPart) { | ||||
|       // TODO: attaquant doit jouer résistance et peut être désarmé p132 | ||||
| @@ -1048,14 +1066,13 @@ export class RdDCombat { | ||||
|         this.defender) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async _onParadeNormale(defenderRoll) { | ||||
|     console.log("RdDCombat._onParadeNormale >>>", defenderRoll); | ||||
|  | ||||
|     await this.computeRecul(defenderRoll); | ||||
|     await this.computeDeteriorationArme(defenderRoll); | ||||
|     await RdDResolutionTable.displayRollData(defenderRoll, this.defender, 'chat-resultat-parade.html'); | ||||
|     await RdDRollResult.displayRollData(defenderRoll, this.defender, 'chat-resultat-parade.hbs'); | ||||
|     this.removeChatMessageActionsPasseArme(defenderRoll.passeArme); | ||||
|   } | ||||
|  | ||||
| @@ -1063,7 +1080,7 @@ export class RdDCombat { | ||||
|   async _onParadeEchec(defenderRoll) { | ||||
|     console.log("RdDCombat._onParadeEchec >>>", defenderRoll); | ||||
|  | ||||
|     await RdDResolutionTable.displayRollData(defenderRoll, this.defender, 'chat-resultat-parade.html'); | ||||
|     await RdDRollResult.displayRollData(defenderRoll, this.defender, 'chat-resultat-parade.hbs'); | ||||
|  | ||||
|     this.removeChatMessageActionsPasseArme(defenderRoll.passeArme); | ||||
|     this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true }); | ||||
| @@ -1080,18 +1097,16 @@ export class RdDCombat { | ||||
|     let rollData = this._prepareEsquive(attackerRoll, esquive); | ||||
|  | ||||
|     const dialog = await RdDRoll.create(this.defender, rollData, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' }, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs' }, | ||||
|       { | ||||
|         name: 'jet-esquive', | ||||
|         label: 'Esquiver', | ||||
|         callbacks: [ | ||||
|           this.defender.createCallbackExperience(), | ||||
|           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) }, | ||||
|           { condition: RdDCombat.isReussite, action: r => this._onEsquiveNormale(r) }, | ||||
|           { condition: RdDCombat.isParticuliere, action: r => this._onEsquiveParticuliere(r) }, | ||||
|           { condition: RdDCombat.isEchec, action: r => this._onEsquiveEchec(r) }, | ||||
|           { action: r => this._onEsquive(r) }, | ||||
|         ] | ||||
|       }); | ||||
|     dialog.render(true); | ||||
| @@ -1119,9 +1134,18 @@ export class RdDCombat { | ||||
|     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) { | ||||
|     console.log("RdDCombat._onEsquiveParticuliere >>>", rollData); | ||||
|   async _onEsquiveParticuliere(defenderRoll) { | ||||
|     console.log("RdDCombat._onEsquiveParticuliere >>>", defenderRoll); | ||||
|     ChatUtility.createChatWithRollMode( | ||||
|       { content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" }, | ||||
|       this.defender); | ||||
| @@ -1130,7 +1154,7 @@ export class RdDCombat { | ||||
|   /* -------------------------------------------- */ | ||||
|   async _onEsquiveNormale(defenderRoll) { | ||||
|     console.log("RdDCombat._onEsquiveNormal >>>", defenderRoll); | ||||
|     await RdDResolutionTable.displayRollData(defenderRoll, this.defender, 'chat-resultat-esquive.html'); | ||||
|     await RdDRollResult.displayRollData(defenderRoll, this.defender, 'chat-resultat-esquive.hbs'); | ||||
|     this.removeChatMessageActionsPasseArme(defenderRoll.passeArme); | ||||
|   } | ||||
|  | ||||
| @@ -1138,7 +1162,7 @@ export class RdDCombat { | ||||
|   async _onEsquiveEchec(defenderRoll) { | ||||
|     console.log("RdDCombat._onEsquiveEchec >>>", defenderRoll); | ||||
|  | ||||
|     await RdDResolutionTable.displayRollData(defenderRoll, this.defender, 'chat-resultat-esquive.html'); | ||||
|     await RdDRollResult.displayRollData(defenderRoll, this.defender, 'chat-resultat-esquive.hbs'); | ||||
|  | ||||
|     this.removeChatMessageActionsPasseArme(defenderRoll.passeArme); | ||||
|     this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true }) | ||||
|   | ||||
| @@ -18,6 +18,7 @@ import { FenetreRechercheTirage } from "./tirage/fenetre-recherche-tirage.js"; | ||||
| import { TMRUtility } from "./tmr-utility.js"; | ||||
| import { DialogFatigueVoyage } from "./voyage/dialog-fatigue-voyage.js"; | ||||
| import { ChatUtility } from "./chat-utility.js"; | ||||
| import { RdDRollResult } from "./rdd-roll-result.js"; | ||||
|  | ||||
| const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/; | ||||
|  | ||||
| @@ -128,6 +129,16 @@ export class RdDCommands { | ||||
|           <br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés | ||||
|           ` | ||||
|     }); | ||||
|     this.registerCommand({ | ||||
|       path: ["/jet"], func: (content, msg, params) => this.askRollRdd(msg, params), | ||||
|       descr: `Poste dans le tchat un jet de dés à effectuer. Exemples: | ||||
|           <br><strong>/jet Vue Vigilance</strong> poste une demande de jet de VUE / Vigilance à 0 | ||||
|           <br><strong>/jet Vue</strong> poste une demande de jet de VUE à 0 | ||||
|           <br><strong>/jet Vue -2</strong> poste une demande de jet de VUE à -2 | ||||
|           <br><strong>/jet Vue Vigilance -2</strong> poste une demande de jet de VUE / Vigilance à -2 | ||||
|           <br><strong>/jet vol déser +2</strong> poste une demande de jet de VOLONTÉ / Survie en désert à +2 | ||||
|           ` | ||||
|     }); | ||||
|     this.registerCommand({ path: ["/ddr"], func: (content, msg, params) => this.rollDeDraconique(msg), descr: "Lance un Dé Draconique" }); | ||||
|  | ||||
|     this.registerCommand({ | ||||
| @@ -256,7 +267,7 @@ export class RdDCommands { | ||||
|     let commands = [] | ||||
|     this._buildSubTableHelp(commands, table ?? this.commandsTable); | ||||
|  | ||||
|     let html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/settings/dialog-aide-commands.html", { commands: commands }); | ||||
|     let html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/settings/dialog-aide-commands.hbs", { commands: commands }); | ||||
|     let d = new Dialog( | ||||
|       { | ||||
|         title: "Commandes disponibles dans le tchat", | ||||
| @@ -339,6 +350,25 @@ export class RdDCommands { | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   async askRollRdd(msg, params) { | ||||
|     if (params.length == 0) { | ||||
|       return false | ||||
|     } | ||||
|     else { | ||||
|       let length = params.length; | ||||
|       let diff = Number(params[length - 1]); | ||||
|       if (Number.isInteger(Number(diff))) { | ||||
|         length--; | ||||
|       } | ||||
|       else { | ||||
|         diff = 0; | ||||
|       } | ||||
|  | ||||
|       const carac = params[0]; | ||||
|       const competence = length > 1 ? '/' + Misc.join(params.slice(1, length), ' ') : '' | ||||
|       ChatMessage.create({ content: `@roll[${carac}${competence}/${diff}]` }) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async rollRdDNumeric(msg, carac, diff, significative = false) { | ||||
| @@ -349,7 +379,7 @@ export class RdDCommands { | ||||
|       show: { title: "Table de résolution" } | ||||
|     }; | ||||
|     await RdDResolutionTable.rollData(rollData); | ||||
|     return RdDCommands._chatAnswer(msg, await RdDResolutionTable.buildRollDataHtml(rollData)); | ||||
|     return RdDCommands._chatAnswer(msg, await RdDRollResult.buildRollDataHtml(rollData)); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
| @@ -361,13 +391,14 @@ export class RdDCommands { | ||||
|   async getTMRAleatoire(msg, params) { | ||||
|     if (params.length < 2) { | ||||
|       let type = params[0] | ||||
|       const solvedTerrain = TMRUtility.findTMRLike(type)?.type | ||||
|       if (solvedTerrain){ | ||||
|         const tmr = await TMRUtility.getTMRAleatoire(type ? (it => it.type == solvedTerrain) : (it => true)) | ||||
|       const solvedTerrain = type ? TMRUtility.findTMRLike(type)?.type : undefined | ||||
|       const filter = solvedTerrain ? (it => it.type == solvedTerrain) : (it => true) | ||||
|       if (type == undefined || solvedTerrain != undefined) { | ||||
|         const tmr = await TMRUtility.getTMRAleatoire(filter) | ||||
|         return RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`) | ||||
|       } | ||||
|     } | ||||
|     return false; | ||||
|     return false | ||||
|   } | ||||
|  | ||||
|   async findTMR(msg, params) { | ||||
|   | ||||
| @@ -1,13 +1,10 @@ | ||||
| /* -------------------------------------------- */ | ||||
| import { RdDResolutionTable } from "./rdd-resolution-table.js"; | ||||
| import { RdDRoll } from "./rdd-roll.js"; | ||||
| import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; | ||||
| import { ChatUtility } from "./chat-utility.js"; | ||||
| import { STATUSES } from "./settings/status-effects.js"; | ||||
| import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; | ||||
| import { ITEM_TYPES } from "./item.js"; | ||||
|  | ||||
| /* -------------------------------------------- */ | ||||
| import { ITEM_TYPES } from "./constants.js"; | ||||
| import { RdDRollResult } from "./rdd-roll-result.js"; | ||||
|  | ||||
| /* -------------------------------------------- */ | ||||
| export class RdDEmpoignade { | ||||
| @@ -160,7 +157,7 @@ export class RdDEmpoignade { | ||||
|     if ((isNouvelle || empoignade.system.pointsemp == 0) && defender.hasArmeeMeleeEquipee()) { | ||||
|       ChatUtility.createChatWithRollMode( | ||||
|         { | ||||
|           content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-valider.html`, { attacker: attacker, defender: defender }) | ||||
|           content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-valider.hbs`, { attacker: attacker, defender: defender }) | ||||
|         }, | ||||
|         attacker | ||||
|       ) | ||||
| @@ -193,7 +190,7 @@ export class RdDEmpoignade { | ||||
|     } | ||||
|     if (empoignade.system.pointsemp >= 2) { | ||||
|       if (!empoignade.system.ausol) { | ||||
|         let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.html'); | ||||
|         let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.hbs'); | ||||
|         RdDEmpoignade.$storeRollEmpoignade(msg, rollData); | ||||
|       } | ||||
|     } else { | ||||
| @@ -217,7 +214,7 @@ export class RdDEmpoignade { | ||||
|     } | ||||
|     const msg = await ChatMessage.create({ | ||||
|       whisper: ChatUtility.getOwners(attacker), | ||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-immobilise.html`, rollData) | ||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-immobilise.hbs`, rollData) | ||||
|     }) | ||||
|     RdDEmpoignade.$storeRollEmpoignade(msg, rollData); | ||||
|   } | ||||
| @@ -225,7 +222,7 @@ export class RdDEmpoignade { | ||||
|   /* -------------------------------------------- */ | ||||
|   static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) { | ||||
|     const dialog = await RdDRoll.create(attacker, rollData, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' }, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs' }, | ||||
|       { | ||||
|         name: 'jet-empoignade', | ||||
|         label: 'Empoigner', | ||||
| @@ -251,7 +248,7 @@ export class RdDEmpoignade { | ||||
|     if (rollData.rolled.isPart) { | ||||
|       rollData.particuliere = "finesse"; | ||||
|     } | ||||
|     let msg = await RdDResolutionTable.displayRollData(rollData, defender, 'chat-empoignade-resultat.html'); | ||||
|     let msg = await RdDRollResult.displayRollData(rollData, defender, 'chat-empoignade-resultat.hbs'); | ||||
|     RdDEmpoignade.$storeRollEmpoignade(msg, rollData); | ||||
|   } | ||||
|  | ||||
| @@ -288,7 +285,7 @@ export class RdDEmpoignade { | ||||
|   /* -------------------------------------------- */ | ||||
|   static async $rollDefenseEmpoignade(defender, defenderRoll) { | ||||
|     const dialog = await RdDRoll.create(defender, defenderRoll, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-empoignade.html' }, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-empoignade.hbs' }, | ||||
|       { | ||||
|         name: 'empoignade', | ||||
|         label: 'Contrer', | ||||
| @@ -313,9 +310,9 @@ export class RdDEmpoignade { | ||||
|       RdDEmpoignade.$updateEtatEmpoignade(empoignade) | ||||
|     } | ||||
|  | ||||
|     await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-empoignade-resultat.html') | ||||
|     await RdDRollResult.displayRollData(rollData, rollData.defender, 'chat-empoignade-resultat.hbs') | ||||
|     if (empoignade.system.pointsemp >= 2) { | ||||
|       let msg = await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-empoignade-entrainer.html'); | ||||
|       let msg = await RdDRollResult.displayRollData(rollData, rollData.attacker, 'chat-empoignade-entrainer.hbs'); | ||||
|       RdDEmpoignade.$storeRollEmpoignade(msg, rollData); | ||||
|     } | ||||
|   } | ||||
| @@ -359,7 +356,7 @@ export class RdDEmpoignade { | ||||
|     await attacker.setEffect(STATUSES.StatusProne, true); | ||||
|     await defender.setEffect(STATUSES.StatusProne, true); | ||||
|  | ||||
|     let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.html'); | ||||
|     let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.hbs'); | ||||
|     RdDEmpoignade.$storeRollEmpoignade(msg, rollData); | ||||
|   } | ||||
|  | ||||
| @@ -375,7 +372,7 @@ export class RdDEmpoignade { | ||||
|     await defender.setEffect(STATUSES.StatusProne, true); | ||||
|     await this.$deleteEmpoignade(empoignade) | ||||
|  | ||||
|     let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-projeter-sol.html'); | ||||
|     let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-projeter-sol.hbs'); | ||||
|     RdDEmpoignade.$storeRollEmpoignade(msg, rollData); | ||||
|   } | ||||
|  | ||||
| @@ -402,7 +399,7 @@ export class RdDEmpoignade { | ||||
|     if (perteMode == "endquart") { | ||||
|       await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4))); | ||||
|     } | ||||
|     let msg = await RdDResolutionTable.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.html'); | ||||
|     let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.hbs'); | ||||
|     RdDEmpoignade.$storeRollEmpoignade(msg, rollData); | ||||
|   } | ||||
|  | ||||
| @@ -429,7 +426,6 @@ export class RdDEmpoignade { | ||||
|     return await Item.create({ | ||||
|       name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name, | ||||
|       type: 'empoignade', | ||||
|       img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp", | ||||
|       system: { description: "", empoignadeid: foundry.utils.randomID(16), compteempoigne: 0, empoigneurid: attacker.id, empoigneid: defender.id, ptsemp: 0, empoigneurname: attacker.name, empoignename: defender.name } | ||||
|     }, | ||||
|       { | ||||
|   | ||||
| @@ -1,36 +0,0 @@ | ||||
|  | ||||
| const tableGemmes = { | ||||
|   "almaze": { label: "Almaze", couleur: "Blanc"}, | ||||
|   "aquafane": { label: "Aquafane", couleur: "Vert Profond"}, | ||||
|   "asterite": { label: "Astérite", couleur: "Bleu, Violet ou Blanc"}, | ||||
|   "cyanolithe": { label: "Cyanolithe", couleur: "Bleu Intense"}, | ||||
|   "larmededragon": { label: "Larme de Dragon", couleur: "Rouge Intense"}, | ||||
|   "muska": { label: "Muska", couleur: "Violet Profond"}, | ||||
|   "nebuleuse": { label: "Nébuleuse", couleur: "Brouillard Intense"}, | ||||
|   "nebuleuse": { label: "Nébuleuse", couleur: "Brouillard Intense, Rose, Vert ou Bleu Pâle"}, | ||||
|   "oeildetigre": { label: "Oeil de Tigre", couleur: "Jaune"}, | ||||
|   "scarlatine": { label: "Scarlatine", couleur: "Rouge Clair ou Orangé"}, | ||||
|   "seliphane": { label: "Séliphane", couleur: "Vert Lumineux"}, | ||||
|   "tournelune": { label: "Tournelune", couleur: "Violet ou Bleu"}, | ||||
|   "zebraide": { label: "Zebraïde", couleur: "Bandes Bicolores, toutes couleurs"} | ||||
| } | ||||
|  | ||||
| export class RdDGemme extends Item { | ||||
|  | ||||
|   static getGemmeTypeOptionList() { | ||||
|     // TODO: look how to map object key-value pairs | ||||
|     let options = "" | ||||
|     for (let gemmeKey in tableGemmes) { | ||||
|       options += `<option value="${gemmeKey}">${tableGemmes[gemmeKey].label}</option>` | ||||
|     } | ||||
|     return options; | ||||
|   } | ||||
|  | ||||
|  | ||||
|   static calculDataDerivees(gemme) { | ||||
|     gemme.system.cout = (gemme.system.taille * gemme.system.purete) + gemme.system.qualite; | ||||
|     gemme.system.inertie = 7 - gemme.system.purete; | ||||
|     gemme.system.enchantabilite = gemme.system.taille - gemme.system.inertie; | ||||
|   } | ||||
|  | ||||
| } | ||||
| @@ -1,73 +0,0 @@ | ||||
| import { Grammar } from "./grammar.js"; | ||||
| import { SystemCompendiums } from "./settings/system-compendiums.js"; | ||||
| import { RdDTimestamp } from "./time/rdd-timestamp.js"; | ||||
|  | ||||
| /* -------------------------------------------- */ | ||||
| export class RdDHerbes extends Item { | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static async onReady() { | ||||
|     this.herbesSoins = await RdDHerbes.listCategorieHerbes('Soin'); | ||||
|     this.herbesRepos = await RdDHerbes.listCategorieHerbes('Repos'); | ||||
|   } | ||||
|  | ||||
|   static async listCategorieHerbes(categorie) { | ||||
|     const herbes = await SystemCompendiums.getWorldOrCompendiumItems('herbe', 'faune-flore-mineraux'); | ||||
|     return herbes.filter(it => Grammar.equalsInsensitive(it.system.categorie, categorie)); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static buildHerbesList(listeHerbes, max) { | ||||
|     let list = {} | ||||
|     for (let herbe of listeHerbes) { | ||||
|       let brins = max - herbe.system.niveau; | ||||
|       list[herbe.name] = `${herbe.name} (Bonus: ${herbe.system.niveau}, Brins: ${brins})`; | ||||
|     } | ||||
|     list['Autre'] = 'Autre (Bonus: variable, Brins: variable)' | ||||
|     return list; | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static calculFormData(formData, item) { | ||||
|     formData.isSoins = item.system.categorie.includes('Soin'); | ||||
|     formData.isRepos = item.system.categorie.includes('Repos'); | ||||
|     if (formData.isSoins) { | ||||
|       RdDHerbes.calculBonusHerbe(formData, this.herbesSoins, 12); | ||||
|     } | ||||
|     if (formData.isRepos) { | ||||
|       RdDHerbes.calculBonusHerbe(formData, this.herbesRepos, 7); | ||||
|     } | ||||
|     formData.herbesSoins = RdDHerbes.buildHerbesList(this.herbesSoins, 12); | ||||
|     formData.herbesRepos = RdDHerbes.buildHerbesList(this.herbesRepos, 7); | ||||
|     formData.dateActuelle = game.system.rdd.calendrier.dateCourante(); | ||||
|     formData.enchantement = RdDTimestamp.splitIndexDate(item.system.prdate); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static calculPuissancePotion(potion) { | ||||
|     return potion.system.herbebonus * potion.system.pr; | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static calculPointsRepos(potion) { | ||||
|     return potion.system.herbebonus * potion.system.pr; | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static calculPointsGuerison(potion) { | ||||
|     return potion.system.herbebonus * potion.system.pr; | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static calculBonusHerbe(formData, herbesList, max) { | ||||
|     if (Number(formData.system.herbebrins)) { | ||||
|       let herbe = herbesList.find(item => item.name.toLowerCase() == formData.system.herbe.toLowerCase()); | ||||
|       if (herbe) { | ||||
|         const brinsRequis = max - herbe.system.niveau; | ||||
|         const brinsManquants = Math.max(brinsRequis - formData.system.herbebrins, 0); | ||||
|         formData.system.herbebonus = Math.max(herbe.system.niveau - brinsManquants, 0); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
| }   | ||||
| @@ -1,6 +1,6 @@ | ||||
| import { RdDItemArme } from "./item-arme.js"; | ||||
| import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; | ||||
| import { ITEM_TYPES } from "./item.js"; | ||||
| import { ITEM_TYPES } from "./constants.js"; | ||||
|  | ||||
| export class RdDHotbar { | ||||
|  | ||||
|   | ||||
| @@ -18,7 +18,6 @@ import { RdDCompendiumOrganiser } from "./rdd-compendium-organiser.js" | ||||
| import { ReglesOptionnelles } from "./settings/regles-optionnelles.js" | ||||
| import { RdDHotbar } from "./rdd-hotbar-drop.js" | ||||
| import { EffetsDraconiques } from "./tmr/effets-draconiques.js" | ||||
| import { RdDHerbes } from "./rdd-herbes.js" | ||||
| import { RdDDice } from "./rdd-dice.js" | ||||
| import { RdDPossession } from "./rdd-possession.js" | ||||
| import { Misc } from "./misc.js" | ||||
| @@ -75,6 +74,11 @@ import { ExportScriptarium } from "./actor/export-scriptarium/export-scriptarium | ||||
| import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js" | ||||
| import { RdDActorExportSheet } from "./actor/export-scriptarium/actor-encart-sheet.js" | ||||
| import { RdDStatBlockParser } from "./apps/rdd-import-stats.js" | ||||
| import { RdDJournalSheet } from "./journal/journal-sheet.js" | ||||
| import { RdDPotionItemSheet } from "./item/sheet-potion.js" | ||||
| import { RdDItemPotion } from "./item/potion.js" | ||||
| import { RdDItemGemme } from "./item/gemme.js" | ||||
| import { RdDGemmeItemSheet } from "./item/sheet-gemme.js" | ||||
|  | ||||
| /** | ||||
|  * RdD system | ||||
| @@ -85,9 +89,9 @@ export class SystemReveDeDragon { | ||||
|  | ||||
|   static start() { | ||||
|     const system = new SystemReveDeDragon() | ||||
|     Hooks.once('init', async () => await system.onInit()) | ||||
|     Hooks.once('init', () => system.onInit()) | ||||
|     Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d)) | ||||
|     Hooks.once('ready', async () => await system.onReady()) | ||||
|     Hooks.once('ready', () => system.onReady()) | ||||
|   } | ||||
|  | ||||
|   constructor() { | ||||
| @@ -98,16 +102,18 @@ export class SystemReveDeDragon { | ||||
|     this.itemClasses = { | ||||
|       armure: RdDItemArmure, | ||||
|       blessure: RdDItemBlessure, | ||||
|       gemme: RdDItemGemme, | ||||
|       maladie: RdDItemMaladie, | ||||
|       ombre: RdDItemOmbre, | ||||
|       poison: RdDItemPoison, | ||||
|       potion: RdDItemPotion, | ||||
|       queue: RdDItemQueue, | ||||
|       tete: RdDItemTete, | ||||
|       race: RdDItemRace, | ||||
|       rencontre: RdDRencontre, | ||||
|       service: RdDItemService, | ||||
|       signedraconique: RdDItemSigneDraconique, | ||||
|       souffle: RdDItemSouffle, | ||||
|       tete: RdDItemTete, | ||||
|     } | ||||
|     this.actorClasses = { | ||||
|       commerce: RdDCommerce, | ||||
| @@ -121,7 +127,7 @@ export class SystemReveDeDragon { | ||||
|   /* -------------------------------------------- */ | ||||
|   /*  Foundry VTT Initialization                  */ | ||||
|   /* -------------------------------------------- */ | ||||
|   async onInit() { | ||||
|   onInit() { | ||||
|     game.system.rdd = this | ||||
|     this.AppAstrologie = AppAstrologie | ||||
|  | ||||
| @@ -185,23 +191,14 @@ export class SystemReveDeDragon { | ||||
|     Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true }) | ||||
|     Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true }) | ||||
|     Items.unregisterSheet("core", ItemSheet) | ||||
|     await RdDActorExportSheet.init() | ||||
|  | ||||
|     RdDItemSheet.register(RdDSigneDraconiqueItemSheet) | ||||
|     RdDItemSheet.register(RdDRencontreItemSheet) | ||||
|     RdDItemSheet.register(RdDConteneurItemSheet) | ||||
|     RdDItemSheet.register(RdDHerbeItemSheet) | ||||
|     RdDItemSheet.register(RdDFauneItemSheet) | ||||
|     RdDItemSheet.register(RdDPlanteItemSheet) | ||||
|     RdDItemSheet.register(RdDIngredientItemSheet) | ||||
|     RdDItemSheet.register(RdDServiceItemSheet) | ||||
|     RdDItemSheet.register(RdDBlessureItemSheet) | ||||
|     RdDActorExportSheet.init() | ||||
|  | ||||
|     Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, { | ||||
|       types: [ | ||||
|         "objet", "arme", "armure", "livre", "potion", "munition", | ||||
|         "monnaie", "nourritureboisson", "gemme", | ||||
|       ], makeDefault: true | ||||
|         "objet", "arme", "armure", "livre", "munition", | ||||
|         "monnaie", "nourritureboisson", | ||||
|       ], | ||||
|       makeDefault: true | ||||
|     }) | ||||
|     Items.registerSheet(SYSTEM_RDD, RdDItemSheet, { | ||||
|       types: [ | ||||
| @@ -211,8 +208,22 @@ export class SystemReveDeDragon { | ||||
|         "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve", | ||||
|         "nombreastral", "tache", "maladie", "poison", "possession", | ||||
|         "tarot", "extraitpoetique", "empoignade" | ||||
|       ], makeDefault: true | ||||
|       ], | ||||
|       makeDefault: true | ||||
|     }) | ||||
|      | ||||
|     RdDItemSheet.register(RdDBlessureItemSheet) | ||||
|     RdDItemSheet.register(RdDConteneurItemSheet) | ||||
|     RdDItemSheet.register(RdDFauneItemSheet) | ||||
|     RdDItemSheet.register(RdDGemmeItemSheet) | ||||
|     RdDItemSheet.register(RdDHerbeItemSheet) | ||||
|     RdDItemSheet.register(RdDIngredientItemSheet) | ||||
|     RdDItemSheet.register(RdDPlanteItemSheet) | ||||
|     RdDItemSheet.register(RdDPotionItemSheet) | ||||
|     RdDItemSheet.register(RdDRencontreItemSheet) | ||||
|     RdDItemSheet.register(RdDServiceItemSheet) | ||||
|     RdDItemSheet.register(RdDSigneDraconiqueItemSheet) | ||||
|     RdDJournalSheet.register() | ||||
|  | ||||
|     // préparation des différents modules | ||||
|     console.log(`Initializing Reve de Dragon Hooks and handlers`) | ||||
| @@ -313,7 +324,6 @@ export class SystemReveDeDragon { | ||||
|     } | ||||
|  | ||||
|     StatusEffects.onReady() | ||||
|     RdDHerbes.onReady() | ||||
|     RdDDice.onReady() | ||||
|  | ||||
|     RdDStatBlockParser.parseStatBlock() | ||||
|   | ||||
| @@ -117,7 +117,7 @@ export class RdDMeteo { | ||||
|     meteo.pluie.description = RdDMeteo.pluie(meteo.pluie.force); | ||||
|  | ||||
|     ChatMessage.create({ | ||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-meteo.html', meteo), | ||||
|       content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-meteo.hbs', meteo), | ||||
|       whisper: ChatUtility.getGMs() | ||||
|     }); | ||||
|   } | ||||
|   | ||||
| @@ -13,7 +13,7 @@ const words = ['pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i', | ||||
| export class RdDNameGen { | ||||
|  | ||||
|   static async proposeName(msg, params) { | ||||
|     const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-command-nom.html`, { | ||||
|     const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-command-nom.hbs`, { | ||||
|       nom: await RdDNameGen.generate() | ||||
|     }); | ||||
|     ChatMessage.create({ content: html, whisper: ChatUtility.getGMs() }); | ||||
|   | ||||
| @@ -1,9 +1,9 @@ | ||||
| /* -------------------------------------------- */ | ||||
| import { RdDResolutionTable } from "./rdd-resolution-table.js"; | ||||
| import { RdDRoll } from "./rdd-roll.js"; | ||||
| import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; | ||||
| import { Targets } from "./targets.js"; | ||||
| import { ITEM_TYPES } from "./item.js"; | ||||
| import { ITEM_TYPES } from "./constants.js"; | ||||
| import { RdDRollResult } from "./rdd-roll-result.js"; | ||||
| import { Grammar } from "./grammar.js"; | ||||
|  | ||||
| /* -------------------------------------------- */ | ||||
| /* On part du principe qu'une entité démarre tjs  | ||||
| @@ -91,18 +91,21 @@ export class RdDPossession { | ||||
|     } | ||||
|     RdDPossession.selectCompetenceDraconicOuPossession(rollData, defender) | ||||
|     rollData.diffLibre = RdDPossession.getInfoAttaque(rollData).diffLibre | ||||
|      | ||||
|  | ||||
|     await RdDPossession.$rollDefensePossession(defender, rollData); | ||||
|   } | ||||
|    | ||||
|  | ||||
|   static selectCompetenceDraconicOuPossession(rollData, rollingActor) { | ||||
|     rollData.competence = rollingActor.getDraconicOuPossession(); | ||||
|     if (rollingActor.isCreatureEntite()) { | ||||
|       RdDItemCompetenceCreature.setRollDataCreature(rollData) | ||||
|       const carac = rollingActor.system.carac | ||||
|       rollData.carac = carac | ||||
|       rollData.competence.system.defaut_carac = 'reve' | ||||
|       rollData.selectedCarac = carac.reve | ||||
|     } | ||||
|     else { | ||||
|       rollData.selectedCarac = rollingActor.system.carac.reve | ||||
|       rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } } | ||||
|       rollData.selectedCarac = rollData.forceCarac['reve-actuel'] | ||||
|       rollData.competence.system.defaut_carac = 'reve-actuel' | ||||
|     } | ||||
|   } | ||||
| @@ -110,7 +113,7 @@ export class RdDPossession { | ||||
|   /* -------------------------------------------- */ | ||||
|   static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) { | ||||
|     const dialog = await RdDRoll.create(attacker, rollData, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html' }, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs' }, | ||||
|       { | ||||
|         name: 'jet-possession', | ||||
|         label: rollData.isECNIDefender ? 'Conjurer la possession' : 'Possession', | ||||
| @@ -131,13 +134,13 @@ export class RdDPossession { | ||||
|     } | ||||
|     const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid) | ||||
|     RdDPossession.storePossessionAttaque(possession, rollData) | ||||
|     await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html'); | ||||
|     await RdDRollResult.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.hbs'); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static async $rollDefensePossession(defender, rollData) { | ||||
|     const dialog = await RdDRoll.create(defender, rollData, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.html' }, | ||||
|       { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-defense-possession.hbs' }, | ||||
|       { | ||||
|         name: 'possession', | ||||
|         label: 'Conjurer une Possession', | ||||
| @@ -171,10 +174,10 @@ export class RdDPossession { | ||||
|     rollData.possession = possession | ||||
|     RdDPossession.$updateEtatPossession(rollData.possession) | ||||
|  | ||||
|     await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html') | ||||
|     await RdDRollResult.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.hbs') | ||||
|     if (rollData.possession.isPosseder || rollData.possession.isConjurer) { | ||||
|       // conjuration | ||||
|       victime.deleteEmbeddedDocuments("Item", [rollData.possession._id]) | ||||
|       await victime.deleteEmbeddedDocuments("Item", [rollData.possession._id]) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
| import { ChatUtility } from "./chat-utility.js"; | ||||
| import { Misc } from "./misc.js"; | ||||
| import { RdDDice } from "./rdd-dice.js"; | ||||
| import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; | ||||
| @@ -54,7 +53,6 @@ export class RdDResolutionTable { | ||||
|     return this._computeCell(level, percentage); | ||||
|   } | ||||
|  | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static _computeRow(caracValue) { | ||||
|     let dataRow = [ | ||||
| @@ -89,24 +87,10 @@ export class RdDResolutionTable { | ||||
|     return resultat; | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.html') { | ||||
|     return await ChatUtility.createChatWithRollMode( | ||||
|       { content: await RdDResolutionTable.buildRollDataHtml(rollData, template) }, | ||||
|       actor | ||||
|     ) | ||||
|   } | ||||
|  | ||||
|   static actorChatName(actor) { | ||||
|     return actor ?? game.user.name; | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static async buildRollDataHtml(rollData, template = 'chat-resultat-general.html') { | ||||
|     rollData.show = rollData.show || {}; | ||||
|     return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/${template}`, rollData); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static async rollData(rollData) { | ||||
|     rollData.rolled = await this.roll(rollData.caracValue, rollData.finalLevel, rollData); | ||||
| @@ -284,7 +268,7 @@ export class RdDResolutionTable { | ||||
|     maxCarac = Math.min(maxCarac, minCarac + 20); | ||||
|     minLevel = Math.max(minLevel, -10); | ||||
|     maxLevel = Math.max(Math.min(maxLevel, 30), minLevel + colonnes); | ||||
|     return await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/resolution-table.html', { | ||||
|     return await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/resolution-table.hbs', { | ||||
|       carac: carac, | ||||
|       difficulte: level, | ||||
|       min: minLevel, | ||||
|   | ||||
| @@ -8,7 +8,7 @@ import { RdDUtility } from "./rdd-utility.js"; | ||||
| export class RdDEncaisser extends Dialog { | ||||
|  | ||||
|   static async encaisser(actor) { | ||||
|     let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html', | ||||
|     let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.hbs', | ||||
|       { ajustementsEncaissement: RdDUtility.getAjustementsEncaissement() } | ||||
|     ); | ||||
|     new RdDEncaisser(html, actor).render(true); | ||||
|   | ||||
| @@ -15,7 +15,7 @@ export class RdDRollResolutionTable extends Dialog { | ||||
|     if (RdDRollResolutionTable.resolutionTable == undefined) { | ||||
|       const rollData = {} | ||||
|       RdDRollResolutionTable._setDefaultOptions(rollData); | ||||
|       let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html', rollData); | ||||
|       let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.hbs', rollData); | ||||
|       RdDRollResolutionTable.resolutionTable = new RdDRollResolutionTable(rollData, html); | ||||
|       RdDRollResolutionTable.resolutionTable.render(true); | ||||
|     } | ||||
|   | ||||
							
								
								
									
										17
									
								
								module/rdd-roll-result.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								module/rdd-roll-result.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| import { ChatUtility } from "./chat-utility.js"; | ||||
|  | ||||
| export class RdDRollResult { | ||||
|  | ||||
|   static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.hbs') { | ||||
|     const chatMessage = await ChatUtility.createChatWithRollMode( | ||||
|       { content: await RdDRollResult.buildRollDataHtml(rollData, template) }, | ||||
|       actor | ||||
|     ) | ||||
|     return chatMessage | ||||
|   } | ||||
|  | ||||
|   static async buildRollDataHtml(rollData, template = 'chat-resultat-general.hbs') { | ||||
|     rollData.show = rollData.show || {}; | ||||
|     return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/${template}`, rollData); | ||||
|   } | ||||
| } | ||||
| @@ -8,6 +8,7 @@ import { RdDCarac } from "./rdd-carac.js"; | ||||
| import { RdDResolutionTable } from "./rdd-resolution-table.js"; | ||||
| import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; | ||||
| import { Grammar } from "./grammar.js"; | ||||
| import { ACTOR_TYPES } from "./constants.js"; | ||||
|  | ||||
| /** | ||||
|  * Extend the base Dialog entity to select roll parameters | ||||
| @@ -62,7 +63,7 @@ export class RdDRoll extends Dialog { | ||||
|       forceDiceResult: -1 | ||||
|     } | ||||
|     // Mini patch :Ajout du rêve actuel | ||||
|     if (actor.system.type == "personnage") { | ||||
|     if (actor.type == ACTOR_TYPES.personnage) { | ||||
|       defaultRollData.carac["reve-actuel"] = actor.system.reve.reve | ||||
|     } | ||||
|  | ||||
| @@ -131,11 +132,16 @@ export class RdDRoll extends Dialog { | ||||
|     console.log('RdDRoll.activateListeners', this.rollData); | ||||
|  | ||||
|     // Update html, according to rollData | ||||
|     if (this.rollData.competence) { | ||||
|       const defaut_carac = this.rollData.competence.system.defaut_carac | ||||
|     if (!this.rollData.selectedCarac && this.rollData.competence) { | ||||
|       // Set the default carac from the competence item | ||||
|       this.rollData.selectedCarac = this.rollData.carac[defaut_carac]; | ||||
|       this.html.find("[name='carac']").val(defaut_carac); | ||||
|       this.rollData.selectedCarac = this.rollData.carac[this.actor.mapCarac(this.rollData.competence.system.defaut_carac)] | ||||
|     } | ||||
|     if (this.rollData.selectedCarac) { | ||||
|       this.html.find("[name='carac']").val( | ||||
|         RdDCarac.caracDetails(this.rollData.selectedCarac.label, { onMessage: m => { } })?.code | ||||
|         ?? this.rollData.selectedCarac.code | ||||
|         ?? Grammar.toLowerCaseNoAccentNoSpace(this.rollData.selectedCarac.label) | ||||
|       ) | ||||
|     } | ||||
|     if (this.rollData.selectedSort) { | ||||
|       this.setSelectedSort(this.rollData.selectedSort); | ||||
| @@ -173,7 +179,7 @@ export class RdDRoll extends Dialog { | ||||
|       this.updateRollResult(html); | ||||
|       this.html.find("[name='diffLibre']").val(this.rollData.diffLibre); | ||||
|     }); | ||||
|     this.html.find('.roll-carac-competence').change((event) => { | ||||
|     this.html.find('.roll-text').change((event) => { | ||||
|       const competence = event.currentTarget.value | ||||
|       this.rollData.competence = this.rollData.competences.find(it => Grammar.equalsInsensitive(it.name, competence)) | ||||
|       this.updateRollResult(html); | ||||
| @@ -263,24 +269,21 @@ export class RdDRoll extends Dialog { | ||||
|   } | ||||
|  | ||||
|   async onAction(action) { | ||||
|     this.rollData.forceDiceResult = Number.parseInt(this.html.find("[name='force-dice-result']").val()) ?? -1; | ||||
|     await RdDResolutionTable.rollData(this.rollData); | ||||
|     console.log("RdDRoll -=>", this.rollData, this.rollData.rolled); | ||||
|     if (action.callbacks) | ||||
|       for (let callback of action.callbacks) { | ||||
|         if (callback.condition == undefined || callback.condition(this.rollData)) { | ||||
|           await callback.action(this.rollData); | ||||
|         } | ||||
|       } | ||||
|     this.rollData.forceDiceResult = Number.parseInt(this.html.find("[name='force-dice-result']").val()) ?? -1 | ||||
|     await RdDResolutionTable.rollData(this.rollData) | ||||
|  | ||||
|     for (let callback of action.callbacks) { | ||||
|       await callback.action(this.rollData) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   async setSelectedSort(sort) { | ||||
|     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.diffLibre = RdDItemSort.getDifficulte(sort, -7); | ||||
|     RdDItemSort.setCoutReveReel(sort); | ||||
|     const htmlSortDescription = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html", { sort: sort }); | ||||
|     const htmlSortDescription = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.hbs", { sort: sort }); | ||||
|     this.html.find(".sort-ou-rituel").text(sort.system.isrituel ? "rituel" : "sort"); | ||||
|     this.html.find(".bonus-case").text(`${this.rollData.bonus}%`); | ||||
|     this.html.find(".placeholder-description-sort").children().remove(); | ||||
| @@ -341,7 +344,7 @@ export class RdDRoll extends Dialog { | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async buildAjustements(rollData) { | ||||
|     return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html`, rollData); | ||||
|     return await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.hbs`, rollData); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   | ||||
| @@ -28,8 +28,8 @@ export class RdDRollTables { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static async drawTextFromRollTable(tableName, toChat) { | ||||
|     const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat); | ||||
|   static async drawTextFromRollTable(tableName, options = {}) { | ||||
|     const drawResult = await RdDRollTables.genericGetTableResult(tableName, options.toChat); | ||||
|     return drawResult.text; | ||||
|   } | ||||
|  | ||||
| @@ -103,7 +103,7 @@ export class RdDRollTables { | ||||
|   static async getMaladresse(options = { toChat: false, arme: false }) { | ||||
|     return await RdDRollTables.drawTextFromRollTable( | ||||
|       options.arme ? "Maladresse armé" : "Maladresses non armé", | ||||
|       options.toChat); | ||||
|       options) | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
| @@ -66,11 +66,13 @@ export class RdDSheetUtility { | ||||
|   } | ||||
|  | ||||
|   static async splitItem(item, actor, onSplit = () => { }) { | ||||
|     const dialog = await DialogSplitItem.create(item, async (item, split) => { | ||||
|     const _onSplit = async (item, split) => { | ||||
|       await RdDSheetUtility._onSplitItem(item, split, actor); | ||||
|       onSplit(); | ||||
|     }); | ||||
|     dialog.render(true); | ||||
|       await RdDSheetUtility.renderItemBranch(actor, item) | ||||
|     } | ||||
|     const dialog = await DialogSplitItem.create(item, _onSplit) | ||||
|     dialog.render(true) | ||||
|   } | ||||
|  | ||||
|   static async _onSplitItem(item, split, actor) { | ||||
| @@ -82,4 +84,11 @@ export class RdDSheetUtility { | ||||
|       await actor.createEmbeddedDocuments('Item', [splitItem]) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   static async renderItemBranch(actor, item) { | ||||
|     while (item) { | ||||
|       await item.sheet?.render() | ||||
|       item = actor.getContenant(item) | ||||
|     } | ||||
|   } | ||||
| } | ||||
| @@ -15,8 +15,7 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; | ||||
| import { RdDDice } from "./rdd-dice.js"; | ||||
| import { STATUSES } from "./settings/status-effects.js"; | ||||
| import { RdDRencontre } from "./item/rencontre.js"; | ||||
| import { RdDTimestamp } from "./time/rdd-timestamp.js"; | ||||
| import { ITEM_TYPES } from "./item.js"; | ||||
| import { ITEM_TYPES } from "./constants.js"; | ||||
| import { Misc } from "./misc.js"; | ||||
|  | ||||
| const TMR_DISPLAY_SIZE = { | ||||
| @@ -48,7 +47,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|  | ||||
|   static async create(actor, tmrData) { | ||||
|     await PixiTMR.init() | ||||
|     let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', tmrData); | ||||
|     let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.hbs', tmrData); | ||||
|     if (tmrData.mode != 'visu' && !game.user.isGM) { | ||||
|       ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatUtility.getGMs() }); | ||||
|     } | ||||
| @@ -83,7 +82,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|     this.subdialog = undefined | ||||
|     this.displaySize = undefined | ||||
|     if (!this.viewOnly && !game.user.isGM) { | ||||
|       this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); | ||||
|       this.$tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); | ||||
|     } | ||||
|     this.callbacksOnAnimate = []; | ||||
|     const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def); | ||||
| @@ -139,7 +138,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|     this.cumulFatigue += this.fatigueParCase; | ||||
|  | ||||
|     // Le reste... | ||||
|     this.updateValuesDisplay(); | ||||
|     this.$updateValuesDisplay(); | ||||
|   } | ||||
|  | ||||
|   lancerUnSort() { | ||||
| @@ -190,7 +189,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|   forceTMRContinueAction() { | ||||
|     ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR'); | ||||
|     this.bringSubDialogToTop(); | ||||
|     return; | ||||
|     return false | ||||
|   } | ||||
|  | ||||
|   setTMRPendingAction(dialog) { | ||||
| @@ -212,7 +211,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|   } | ||||
|  | ||||
|   getSortsReserve(coord) { | ||||
|     return this.actor.itemTypes[ITEM_TYPES.sortreserve].filter(// Reserve sur une case fleuve ou normale | ||||
|     return this.sortsReserve.filter(// Reserve sur une case fleuve ou normale | ||||
|       TMRUtility.getTMR(coord).type == 'fleuve' | ||||
|         ? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve' | ||||
|         : it => it.system.coord == coord | ||||
| @@ -241,7 +240,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|     this._getTokensRencontres().forEach(t => this._trackToken(t)) | ||||
|     this._getTokensSortsReserve().forEach(t => this._trackToken(t)) | ||||
|   } | ||||
|    | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   updateTokens() { | ||||
|     this._removeTokens(t => true); | ||||
| @@ -271,8 +270,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|   } | ||||
|  | ||||
|   _getTokensSortsReserve() { | ||||
|     const sortsReserve = this.actor.itemTypes[ITEM_TYPES.sortreserve]; | ||||
|     return Misc.concat(sortsReserve.map(sortReserve => | ||||
|     return Misc.concat(this.sortsReserve.map(sortReserve => | ||||
|       EffetsDraconiques.sortReserve.tokens(this.pixiTMR, sortReserve, () => sortReserve.system.coord))) | ||||
|   } | ||||
|  | ||||
| @@ -298,7 +296,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|     const coordOrig = this._getCoordActor(); | ||||
|     const coordTarget = TMRUtility.deplacement(coordOrig, move); | ||||
|     await this._deplacerDemiReve(coordTarget, 'normal'); | ||||
|     this.checkQuitterTMR(); | ||||
|     await this.$checkQuitterTMR(); | ||||
|   } | ||||
|  | ||||
|   calculCoutMonteeTMR() { | ||||
| @@ -306,7 +304,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async updateValuesDisplay() { | ||||
|   async $updateValuesDisplay() { | ||||
|     if (this.viewOnly || !this.rendered) { | ||||
|       return; | ||||
|     } | ||||
| @@ -337,22 +335,30 @@ export class RdDTMRDialog extends Dialog { | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async close() { | ||||
|     await this.$forceClose(this.actor.name + " a quitté les terres médianes") | ||||
|   } | ||||
|  | ||||
|   async $forceClose(message) { | ||||
|     if (this.subdialog) { | ||||
|       return this.forceTMRContinueAction() | ||||
|       this.forceTMRContinueAction() | ||||
|       return false | ||||
|     } | ||||
|     this.descenteTMR = true; | ||||
|     if (this.actor.tmrApp) { | ||||
|       this.actor.tmrApp = undefined; // Cleanup reference | ||||
|       if (!this.viewOnly) { | ||||
|         await this.actor.setEffect(STATUSES.StatusDemiReve, false) | ||||
|         this._tellToGM(this.actor.name + " a quitté les terres médianes"); | ||||
|         await this.actor.setEffect(STATUSES.StatusDemiReve, false); | ||||
|         this.$tellToUserAndGM(message) | ||||
|       } | ||||
|       await this.actor.santeIncDec((ReglesOptionnelles.isUsing("appliquer-fatigue") ? "fatigue" : "endurance"), | ||||
|         this.cumulFatigue) | ||||
|       const appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue"); | ||||
|       await this.actor.santeIncDec( | ||||
|         appliquerFatigue ? "fatigue" : "endurance", | ||||
|         (appliquerFatigue ? 1 : -1) * this.cumulFatigue); | ||||
|     } | ||||
|     await super.close(); | ||||
|     this.pixiTMR.close() | ||||
|     this.pixiTMR.close(); | ||||
|     this.pixiTMR = undefined | ||||
|     await super.close(); | ||||
|     return true | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
| @@ -364,48 +370,53 @@ export class RdDTMRDialog extends Dialog { | ||||
|     } | ||||
|     switch (action) { | ||||
|       case 'derober': | ||||
|         await this.derober(); | ||||
|         this.restoreTMRAfterAction(); | ||||
|         return; | ||||
|         await this.$derober() | ||||
|         this.restoreTMRAfterAction() | ||||
|         return | ||||
|       case 'refouler': | ||||
|         await this.refouler(); | ||||
|         break; | ||||
|         await this.$refouler() | ||||
|         break | ||||
|       case 'maitriser': | ||||
|         await this.maitriserRencontre(); | ||||
|         break; | ||||
|         await this.$maitriserRencontre() | ||||
|         break | ||||
|       case 'ignorer': | ||||
|         await this.ignorerRencontre(); | ||||
|         break; | ||||
|         await this.$ignorerRencontre() | ||||
|         break | ||||
|     } | ||||
|     await this.postRencontre(tmr); | ||||
|     this.restoreTMRAfterAction(); | ||||
|   } | ||||
|  | ||||
|   async derober() { | ||||
|     console.log("-> derober", this.currentRencontre); | ||||
|     await this.actor.addTMRRencontre(this.currentRencontre); | ||||
|     this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR."); | ||||
|     this.close(); | ||||
|   async $derober() { | ||||
|     if (this.currentRencontre) { | ||||
|       console.log("-> derober", this.currentRencontre); | ||||
|       await this.actor.addTMRRencontre(this.currentRencontre); | ||||
|       this.$forceClose(`${this.actor.name} s'est dérobé face à la rencontre ${this.currentRencontre.name}, et quitte les TMR.`) | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async refouler() { | ||||
|     console.log("-> refouler", this.currentRencontre); | ||||
|     await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`); | ||||
|     await this.actor.deleteRencontreTMRAtPosition() | ||||
|     this.updateTokens(); | ||||
|     this.updateValuesDisplay(); | ||||
|     this.nettoyerRencontre(); | ||||
|   async $refouler() { | ||||
|     if (this.currentRencontre) { | ||||
|       console.log("-> refouler", this.currentRencontre); | ||||
|       await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`); | ||||
|       await this.$deleteRencontreTMRAtPosition() | ||||
|       this.updateTokens(); | ||||
|       this.$updateValuesDisplay(); | ||||
|       this.$nettoyerRencontre(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async ignorerRencontre() { | ||||
|     console.log("-> ignorer", this.currentRencontre); | ||||
|     this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name); | ||||
|     await this.actor.deleteRencontreTMRAtPosition() | ||||
|     this.updateTokens(); | ||||
|     this.updateValuesDisplay(); | ||||
|     this.nettoyerRencontre(); | ||||
|   async $ignorerRencontre() { | ||||
|     if (this.currentRencontre) { | ||||
|       console.log("-> ignorer", this.currentRencontre); | ||||
|       this.$tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name); | ||||
|       await this.$deleteRencontreTMRAtPosition() | ||||
|       this.updateTokens(); | ||||
|       this.$updateValuesDisplay(); | ||||
|       this.$nettoyerRencontre(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
| @@ -422,41 +433,29 @@ export class RdDTMRDialog extends Dialog { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   checkQuitterTMR() { | ||||
|     if (this.actor.isDead()) { | ||||
|       this._tellToGM("Vous êtes mort : vous quittez les Terres médianes !"); | ||||
|       this.close(); | ||||
|       return true; | ||||
|   async $checkQuitterTMR() { | ||||
|     const reason = this.actor.isDead() | ||||
|       ? "est mort" | ||||
|       : this.actor.isCumulFatigueCauseSommeil(this.cumulFatigue) | ||||
|         ? "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 | ||||
|     } | ||||
|  | ||||
|     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; | ||||
|     return false | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async quitterLesTMRInconscient() { | ||||
|     await this.refouler(); | ||||
|     this.close(); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   async maitriserRencontre() { | ||||
|   async $maitriserRencontre() { | ||||
|     console.log("-> maitriser", this.currentRencontre); | ||||
|  | ||||
|     await this.actor.deleteRencontreTMRAtPosition() | ||||
|     await this.$deleteRencontreTMRAtPosition(); | ||||
|     this.updateTokens(); | ||||
|  | ||||
|     let rencontreData = { | ||||
| @@ -471,11 +470,21 @@ export class RdDTMRDialog extends Dialog { | ||||
|       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'; | ||||
|  | ||||
|     rencData.reve = this.actor.getReveActuel(); | ||||
| @@ -484,7 +493,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|     RollDataAjustements.calcul(rencData, this.actor); | ||||
|  | ||||
|     rencData.rolled = rencData.presentCite | ||||
|       ? this._rollPresentCite(rencData) | ||||
|       ? this.$rollPresentCite(rencData) | ||||
|       : await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements)); | ||||
|  | ||||
|     const result = rencData.rolled.isSuccess | ||||
| @@ -494,38 +503,41 @@ export class RdDTMRDialog extends Dialog { | ||||
|     await RdDRencontre.appliquer(result.effets, this, rencData); | ||||
|  | ||||
|     rencData.poesie = { extrait: result.poesie, reference: result.reference }; | ||||
|     rencData.message = this.formatMessageRencontre(rencData, result.message); | ||||
|     rencData.message = this.$formatMessageRencontre(rencData, result.message); | ||||
|  | ||||
|     ChatMessage.create({ | ||||
|       whisper: ChatUtility.getOwners(this.actor), | ||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencData) | ||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.hbs`, rencData) | ||||
|     }); | ||||
|  | ||||
|     this.updateValuesDisplay(); | ||||
|     if (this.checkQuitterTMR()) { | ||||
|     this.$updateValuesDisplay(); | ||||
|     if (await this.$checkQuitterTMR()) { | ||||
|       return; | ||||
|     } | ||||
|     if (this.rencontreState == 'persistant') { | ||||
|       this._nouvelleTentativeMaitrise(rencData); | ||||
|       this.$nouvelleTentativeMaitrise(rencData); | ||||
|     } | ||||
|     else if (!this.isRencontreDeplacement()) { | ||||
|       this.nettoyerRencontre(); | ||||
|       this.$nettoyerRencontre(); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   _nouvelleTentativeMaitrise(rencData) { | ||||
|   $nouvelleTentativeMaitrise(rencData) { | ||||
|     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++; | ||||
|       if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { | ||||
|         this.cumulFatigue += this.fatigueParCase; | ||||
|       } | ||||
|       this._tentativeMaitrise(rencData); | ||||
|       this._deleteTmrMessages(rencData.actor, rencData.nbRounds); | ||||
|       this.$tentativeMaitrise(rencData); | ||||
|       this.$deleteTmrMessages(rencData.actor, rencData.nbRounds); | ||||
|     }, 2000); | ||||
|   } | ||||
|  | ||||
|   formatMessageRencontre(rencData, template) { | ||||
|   $formatMessageRencontre(rencData, template) { | ||||
|     let messageDuree = '' | ||||
|     if (rencData.nbRounds > 1) { | ||||
|       if (rencData.rolled.isSuccess) { | ||||
| @@ -544,7 +556,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   _rollPresentCite(rencData) { | ||||
|   $rollPresentCite(rencData) { | ||||
|     let rolled = RdDResolutionTable.computeChances(rencData.reve, 0); | ||||
|     foundry.utils.mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score }); | ||||
|     RdDResolutionTable.succesRequis(rolled); | ||||
| @@ -552,7 +564,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   _deleteTmrMessages(actor, nbRounds = -1) { | ||||
|   $deleteTmrMessages(actor, nbRounds = -1) { | ||||
|     setTimeout(() => { | ||||
|       if (nbRounds < 0) { | ||||
|         ChatUtility.removeChatMessageContaining(`<h4 data-categorie="tmr" data-actor-id="${actor._id}"`); | ||||
| @@ -571,7 +583,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   _tellToGM(message) { | ||||
|   $tellToGM(message) { | ||||
|     ChatMessage.create({ | ||||
|       user: game.user.id, | ||||
|       content: message, | ||||
| @@ -580,7 +592,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   _tellToUserAndGM(message) { | ||||
|   $tellToUserAndGM(message) { | ||||
|     ChatMessage.create({ | ||||
|       user: game.user.id, | ||||
|       content: message, | ||||
| @@ -602,7 +614,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|     if (this.currentRencontre) { | ||||
|       if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)) { | ||||
|         // rencontre en attente suite à dérobade | ||||
|         await this.maitriserRencontre(); | ||||
|         await this.$maitriserRencontre(); | ||||
|       } | ||||
|       else { | ||||
|         const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr); | ||||
| @@ -649,7 +661,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|       tmr: tmr, | ||||
|       presentCite: presentCite | ||||
|     }; | ||||
|     await this._tentativeMaitrise(rencontreData); | ||||
|     await this.$tentativeMaitrise(rencontreData); | ||||
|     this.postRencontre(tmr); | ||||
|   } | ||||
|  | ||||
| @@ -725,10 +737,10 @@ export class RdDTMRDialog extends Dialog { | ||||
|     rollData.poesie = await Poetique.getExtrait(); | ||||
|     ChatMessage.create({ | ||||
|       whisper: ChatUtility.getOwners(this.actor), | ||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData) | ||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData) | ||||
|     }); | ||||
|     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); | ||||
|   } | ||||
| @@ -783,7 +795,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|         onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), | ||||
|         onConqueteEchec: r => { | ||||
|           this.souffleSiEchecTotal(rollData); | ||||
|           this.close() | ||||
|           this.$forceClose(`${this.actor.name} n'a pas maîtrisé la ${tmr.label}, et quitte les TMR.`) | ||||
|         }, | ||||
|         canClose: false | ||||
|       }); | ||||
| @@ -798,7 +810,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|         onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), | ||||
|         onConqueteEchec: r => { | ||||
|           this.souffleSiEchecTotal(rollData); | ||||
|           this.close() | ||||
|           this.$forceClose(`${this.actor.name} n'a pas purifié la ${tmr.label}, et quitte les TMR.`) | ||||
|         }, | ||||
|         canClose: false | ||||
|       }); | ||||
| @@ -812,7 +824,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|         difficulte: -7, | ||||
|         action: 'Conquérir', | ||||
|         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 | ||||
|       }); | ||||
|     } | ||||
| @@ -842,7 +854,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|     rollData.poesie = await Poetique.getExtrait(); | ||||
|     ChatMessage.create({ | ||||
|       whisper: ChatUtility.getOwners(this.actor), | ||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData) | ||||
|       content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData) | ||||
|     }); | ||||
|     if (rollData.rolled.isEchec) { | ||||
|       options.onConqueteEchec(rollData, options.effetDraconique); | ||||
| @@ -858,7 +870,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|     rollData.isTMRCache = rollData.actor.isTMRCache(); | ||||
|     const dialog = await RdDRoll.create(this.actor, rollData, | ||||
|       { | ||||
|         html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html', | ||||
|         html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.hbs', | ||||
|       }, | ||||
|       { | ||||
|         name: rollData.maitrise.verbe, label: rollData.maitrise.action, | ||||
| @@ -908,8 +920,8 @@ export class RdDTMRDialog extends Dialog { | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   lancerSortEnReserve(coord, sortId) { | ||||
|     let sorts = this.getSortsReserve(coord); | ||||
|     let sort = sorts.find(it => it.id == sortId); | ||||
|     const sort = this.getSortsReserve(coord) | ||||
|       .find(it => it.id == sortId); | ||||
|     if (sort) { | ||||
|       this.processSortReserve(sort); | ||||
|     } else { | ||||
| @@ -923,19 +935,15 @@ export class RdDTMRDialog extends Dialog { | ||||
|   /* -------------------------------------------- */ | ||||
|   async processSortReserve(sortReserve) { | ||||
|     await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]); | ||||
|     console.log("declencheSortEnReserve", sortReserve); | ||||
|     const heureCible = RdDTimestamp.definition(sortReserve.system.heurecible).label; | ||||
|     this._tellToUserAndGM(`Vous avez déclenché  | ||||
|         ${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"} | ||||
|         en réserve <strong>${sortReserve.name}</strong> | ||||
|         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(); | ||||
|     console.log("declencheSortEnReserve", sortReserve) | ||||
|     const sort = sortReserve.system.sortid ? this.actor.items.get(sortReserve.system.sortid) : undefined | ||||
|     const message = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-lancement-sortreserve.hbs`, | ||||
|       { sortReserve, sort }) | ||||
|     await this.$forceClose(message) | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   nettoyerRencontre() { | ||||
|   $nettoyerRencontre() { | ||||
|     // Suppression des dessins des zones possibles | ||||
|     this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic)) | ||||
|     // Nettoyage de la structureet de l'état | ||||
| @@ -1022,7 +1030,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|         console.log("STATUS :", this.rencontreState, this.currentRencontre); | ||||
|     } | ||||
|  | ||||
|     this.checkQuitterTMR(); | ||||
|     await this.$checkQuitterTMR(); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
| @@ -1055,13 +1063,13 @@ export class RdDTMRDialog extends Dialog { | ||||
|     */ | ||||
|     this.notifierResonanceSigneDraconique(targetCoord); | ||||
|     await this.actor.rollUnSort(targetCoord); | ||||
|     this.nettoyerRencontre(); | ||||
|     this.$nettoyerRencontre(); | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   externalRefresh() { | ||||
|     this.createPixiSprites(); | ||||
|     this.updateValuesDisplay(); | ||||
|     this.$updateValuesDisplay(); | ||||
|     this.updateTokens(); | ||||
|     console.log("TMR REFRESHED !!!"); | ||||
|   } | ||||
| @@ -1072,7 +1080,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|       return this.forceTMRContinueAction() | ||||
|     } | ||||
|     if (this.currentRencontre != 'normal') { | ||||
|       this.nettoyerRencontre(); | ||||
|       this.$nettoyerRencontre(); | ||||
|     } | ||||
|     let tmr = TMRUtility.getTMR(targetCoord); | ||||
|     // Gestion cases spéciales type Trou noir, etc | ||||
| @@ -1084,7 +1092,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|     if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { | ||||
|       this.cumulFatigue += this.fatigueParCase; | ||||
|     } | ||||
|     this.updateValuesDisplay(); | ||||
|     this.$updateValuesDisplay(); | ||||
|     this.actor.notifyRefreshTMR(); | ||||
|  | ||||
|     if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... | ||||
| @@ -1099,7 +1107,7 @@ export class RdDTMRDialog extends Dialog { | ||||
|     if (!this.viewOnly && this.actor.isResonanceSigneDraconique(coord)) { | ||||
|       ChatMessage.create({ | ||||
|         whisper: ChatUtility.getOwners(this.actor), | ||||
|         content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-resonance.html`, { | ||||
|         content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-resonance.hbs`, { | ||||
|           alias: this.actor.getAlias(), | ||||
|           typeTMR: TMRUtility.getTMRType(coord) | ||||
|         }) | ||||
|   | ||||
| @@ -52,7 +52,7 @@ export class RdDTokenHud { | ||||
|     }; | ||||
|     const controlIconCombat = html.find('.control-icon[data-action=combat]'); | ||||
|     await RdDTokenHud._configureSubMenu(controlIconCombat, | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.hbs', | ||||
|       hudData, | ||||
|       (event) => { | ||||
|         let initCommand = event.currentTarget.attributes['data-command']?.value; | ||||
| @@ -70,7 +70,7 @@ export class RdDTokenHud { | ||||
|   static async addExtensionHudCombat(html, combatant, token, actions) { | ||||
|     const hudData = { combatant, token, actions, commandes: [] }; | ||||
|     const controlIconTarget = html.find('.control-icon[data-action=target]'); | ||||
|     await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData, | ||||
|     await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.hbs', hudData, | ||||
|       (event) => { | ||||
|         const actionIndex = event.currentTarget.attributes['data-action-index']?.value; | ||||
|         const action = hudData.actions[actionIndex]; | ||||
|   | ||||
| @@ -19,9 +19,12 @@ import { RdDEmpoignade } from "./rdd-empoignade.js"; | ||||
| import { ExperienceLog } from "./actor/experience-log.js"; | ||||
| import { RdDCoeur } from "./coeur/rdd-coeur.js"; | ||||
| import { APP_ASTROLOGIE_REFRESH } from "./sommeil/app-astrologie.js"; | ||||
| import { RDD_CONFIG } from "./constants.js"; | ||||
| import { ITEM_TYPES, RDD_CONFIG } from "./constants.js"; | ||||
| import { RdDBaseActor } from "./actor/base-actor.js"; | ||||
| import { RdDCarac } from "./rdd-carac.js"; | ||||
| import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js"; | ||||
| import { Monnaie } from "./item-monnaie.js"; | ||||
| import { ItemAction } from "./item/item-actions.js"; | ||||
|  | ||||
| /* -------------------------------------------- */ | ||||
| // This table starts at 0 -> niveau -10 | ||||
| @@ -106,102 +109,105 @@ export class RdDUtility { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static async preloadHandlebarsTemplates() { | ||||
|   static preloadHandlebarsTemplates() { | ||||
|     const templatePaths = [ | ||||
|       //Character Sheets | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor-sheet.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.hbs', | ||||
|       // sous-parties de feuilles de personnages | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-buttons.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-etat.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-hautreve.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/item-action-controls.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-buttons.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-etat.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/header-hautreve.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/archetype.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/vue-detaillee.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/armures.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/carac-entitee.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/competence.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/combat.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/blessures.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/carac-entitee.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/competence.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/combat.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/blessures.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/blessure.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/possessions.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/possessions.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/resonances.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/jeux.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/taches.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/jeus.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/haut-revant.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queue.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-signes-draconiques.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-rencontres.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts-reserve.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-meditations.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-casestmr.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/xp-journal.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/editor-notes-mj.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html', | ||||
|       "systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-monnaie.html", | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queue.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-signes-draconiques.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-rencontres.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts-reserve.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-meditations.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/hr-casetmrs.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/xp-journal.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/editor-notes-mj.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.hbs', | ||||
|       "systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-monnaie.hbs", | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/liens-animaux.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/liens-suivants.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.hbs', | ||||
|       //Items | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/boutons-comestible.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/boutons-comestible.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/icon-arme-broken.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/temporel.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/header-item.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/header-item.hbs', | ||||
|  | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/queue-sheet.hbs', | ||||
|       // partial enums | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-categories.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-mortalite.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-periode.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-categories.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/enum-categorie-alchimie.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/item/enum-etat-alchimie.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-competence.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-heures.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-mortalite.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-periode.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.hbs', | ||||
|       // Partials | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/enchantement/partial-enchantement.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/coeur/chat-effet-tendre-moment.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/coeur/afficher-coeur.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs', | ||||
| @@ -213,56 +219,55 @@ export class RdDUtility { | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-astrologique.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-coeur.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-competences.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffFixe.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffCondition.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-item-hautrevant.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-item-frequence.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-competences.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffFixe.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffCondition.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-item-hautrevant.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-item-frequence.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/partial-item-description.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/roll/explain.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/resolution-table.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/resolution-table.hbs', | ||||
|       // Dialogs | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/sommeil/sommeil-actor-moral.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-gardien.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-joueur.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-theme.hbs', | ||||
|       // HUD | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.hbs', | ||||
|       // messages tchat | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-description.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-infojet.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-description.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-acteur.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-potionenchantee-chateaudormant.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-fabriquer-potion-base.html', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html' | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-fabriquer-potion-base.hbs', | ||||
|       'systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.hbs' | ||||
|     ]; | ||||
|      | ||||
|  | ||||
|     // foundry et options | ||||
|     Handlebars.registerHelper('RDD_CONFIG', path => RDD_CONFIG[path]) | ||||
|     Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name)); | ||||
| @@ -277,7 +282,7 @@ export class RdDUtility { | ||||
|       const html = options.fn(this); | ||||
|       return html.replace(rgx, "$& selected"); | ||||
|     }) | ||||
|      | ||||
|  | ||||
|     // logic | ||||
|     Handlebars.registerHelper('either', (a, b) => a ?? b); | ||||
|     // string manipulation | ||||
| @@ -289,12 +294,13 @@ export class RdDUtility { | ||||
|     Handlebars.registerHelper('grammar-apostrophe', (article, str) => Grammar.apostrophe(article, str)); | ||||
|     Handlebars.registerHelper('grammar-un', str => Grammar.articleIndetermine(str)); | ||||
|     Handlebars.registerHelper('grammar-accord', (genre, ...args) => Grammar.accord(genre, args)); | ||||
|      | ||||
|     Handlebars.registerHelper('json-stringify', object => JSON.stringify(object)) | ||||
|  | ||||
|     // math | ||||
|     Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1))); | ||||
|     Handlebars.registerHelper('repeat', function(n, block) { | ||||
|     Handlebars.registerHelper('repeat', function (n, block) { | ||||
|       let accum = ''; | ||||
|       for(let i = 0; i < n; ++i){ | ||||
|       for (let i = 0; i < n; ++i) { | ||||
|         accum += block.fn(i) | ||||
|       } | ||||
|       return accum | ||||
| @@ -312,6 +318,7 @@ export class RdDUtility { | ||||
|     // gestion des dates et heures | ||||
|     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-definition', (heure) => RdDTimestamp.definition(heure)) | ||||
|     Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier()); | ||||
|     Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree()); | ||||
|     Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode()); | ||||
| @@ -332,6 +339,9 @@ export class RdDUtility { | ||||
|     Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field)); | ||||
|     // Items | ||||
|     Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field)); | ||||
|     Handlebars.registerHelper('item-action-applies', (action, item, options) => ItemAction.applies(action, item, options)) | ||||
|     Handlebars.registerHelper('item-action-icon', (action, item) => ItemAction.icon(action, item)) | ||||
|     Handlebars.registerHelper('item-name', (item) =>  item.nameDisplay) | ||||
|  | ||||
|     // TMRs | ||||
|     Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord)); | ||||
| @@ -339,7 +349,7 @@ export class RdDUtility { | ||||
|     Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type)); | ||||
|     Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord)); | ||||
|  | ||||
|     return loadTemplates(templatePaths); | ||||
|     loadTemplates(templatePaths); | ||||
|   } | ||||
|  | ||||
|   static getItem(itemId, actorId = undefined) { | ||||
| @@ -433,8 +443,8 @@ export class RdDUtility { | ||||
|     }; | ||||
|     if (!optionsArbre.templateItem) { | ||||
|       optionsArbre.templateItem = item.parent?.type == 'commerce' | ||||
|         ? "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.html" | ||||
|         : "systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html"; | ||||
|         ? "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.hbs" | ||||
|         : "systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.hbs"; | ||||
|     } | ||||
|     item.niveau = optionsArbre.profondeur; | ||||
|   } | ||||
| @@ -462,13 +472,38 @@ export class RdDUtility { | ||||
|     return ligneObjet; | ||||
|   } | ||||
|  | ||||
|   static filterItemsPerTypeForSheet(formData, itemTypes) { | ||||
|     Object.values(ITEM_TYPES).forEach(t => { | ||||
|       formData[t + 's'] = Misc.arrayOrEmpty(itemTypes[t]) | ||||
|       itemTypes[t].forEach(item => item.actions = item.itemActions()) | ||||
|     }) | ||||
|  | ||||
|     formData.maladiesPoisons = formData.maladies.concat(formData.poisons) | ||||
|     formData.competences = formData.competences.concat(formData.competencecreatures) | ||||
|     formData.monnaies = formData.monnaies.sort(Monnaie.triValeurEntiere()) | ||||
|  | ||||
|     formData.inventaires = RdDUtility.prepareInventaire(itemTypes) | ||||
|   } | ||||
|  | ||||
|   static buildInventaireConteneur(actorId, itemId, options) { | ||||
|     const actor = game.actors.get(actorId) | ||||
|     const item = actor?.items.get(itemId) | ||||
|     if (item) { | ||||
|       return RdDUtility.buildContenuConteneur(item, options, { ouvert: true, profondeur: 1 }); | ||||
|     if (item?.type == ITEM_TYPES.conteneur) { | ||||
|       const formData = {} | ||||
|       RdDUtility.filterItemsPerTypeForSheet(formData, actor.itemTypes); | ||||
|       RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires); | ||||
|       item.subItems = formData.conteneurs.find(it => it._id == itemId)?.subItems; | ||||
|  | ||||
|       return RdDUtility.buildContenuConteneur(item, options, { ouvert: true, profondeur: 1 }) | ||||
|     } | ||||
|     return ''; | ||||
|     return '' | ||||
|   } | ||||
|  | ||||
|   static prepareInventaire(itemTypes) { | ||||
|     return RdDItem.getItemTypesInventaire('all') | ||||
|       .map(t => Misc.arrayOrEmpty(itemTypes[t])) | ||||
|       .reduce((a, b) => a.concat(b), []) | ||||
|       .sort(Misc.ascending(it => it.name)) | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
| @@ -695,6 +730,7 @@ export class RdDUtility { | ||||
|     RdDCombat.registerChatCallbacks(html) | ||||
|     RdDEmpoignade.registerChatCallbacks(html) | ||||
|     RdDCoeur.registerChatCallbacks(html) | ||||
|     RdDTextEditor.registerChatCallbacks(html) | ||||
|  | ||||
|     // Gestion spécifique message passeurs | ||||
|     html.on("click", '.tmr-passeur-coord a', event => { | ||||
| @@ -869,7 +905,7 @@ export class RdDUtility { | ||||
|   } | ||||
|  | ||||
|   /* -------------------------------------------- */ | ||||
|   static async confirmActorItemDelete(sheet, item, htmlToDelete) { | ||||
|   static async confirmActorItemDelete(item, actor) { | ||||
|     const itemId = item.id; | ||||
|     const confirmationSuppression = { | ||||
|       settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(), | ||||
| @@ -878,8 +914,7 @@ export class RdDUtility { | ||||
|       buttonLabel: "Supprimer", | ||||
|       onAction: () => { | ||||
|         console.log('Delete : ', itemId); | ||||
|         sheet.actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false }); | ||||
|         RdDUtility.slideOnDelete(sheet, htmlToDelete); | ||||
|         actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false }); | ||||
|       } | ||||
|     }; | ||||
|     if (item.isConteneurNonVide()) { | ||||
| @@ -892,8 +927,7 @@ export class RdDUtility { | ||||
|             label: "Supprimer conteneur et contenu", | ||||
|             callback: () => { | ||||
|               console.log("Delete : ", itemId); | ||||
|               sheet.actor.deleteAllConteneur(itemId, { renderSheet: false }); | ||||
|               RdDUtility.slideOnDelete(sheet, htmlToDelete); | ||||
|               actor.deleteAllConteneur(itemId, { renderSheet: false }); | ||||
|             } | ||||
|           } | ||||
|         }); | ||||
| @@ -931,8 +965,8 @@ export class RdDUtility { | ||||
|   } | ||||
|  | ||||
|   /*-------------------------------------------- */ | ||||
|   static checkThanatosXP(compName) { | ||||
|     if (compName.includes('Thanatos')) { | ||||
|   static checkThanatosXP(item) { | ||||
|     if (item.isCompetencePersonnage() && item.name.includes('Thanatos')) { | ||||
|       let message = "Vous avez mis des points d'Expérience en Thanatos !<br>Vous devez réduire manuellement d'un même montant d'XP une autre compétence Draconique."; | ||||
|       ChatMessage.create({ | ||||
|         whisper: ChatUtility.getUserAndGMs(), | ||||
|   | ||||
| @@ -112,7 +112,7 @@ export class StatusEffects extends FormApplication { | ||||
|     const options = super.defaultOptions; | ||||
|     foundry.utils.mergeObject(options, { | ||||
|       id: "status-effects", | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/settings/status-effects.html", | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/settings/status-effects.hbs", | ||||
|       height: 800, | ||||
|       width: 350, | ||||
|       minimizable: false, | ||||
|   | ||||
| @@ -157,7 +157,7 @@ export class SystemCompendiums extends FormApplication { | ||||
|     const options = super.defaultOptions; | ||||
|     foundry.utils.mergeObject(options, { | ||||
|       id: "system-compendiums", | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/settings/system-compendiums.html", | ||||
|       template: "systems/foundryvtt-reve-de-dragon/templates/settings/system-compendiums.hbs", | ||||
|       height: 'fit-content', | ||||
|       width: 600, | ||||
|       minimizable: false, | ||||
|   | ||||
| @@ -15,7 +15,7 @@ export class DialogRepos extends Dialog { | ||||
|         "heures": 4 | ||||
|       } | ||||
|     } | ||||
|     const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-repos.html", actor); | ||||
|     const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-repos.hbs", actor); | ||||
|     const dialog = new DialogRepos(html, actor); | ||||
|     dialog.render(true); | ||||
|   } | ||||
|   | ||||
| @@ -15,7 +15,7 @@ export class DialogStress extends Dialog { | ||||
|         ) | ||||
|     }; | ||||
|  | ||||
|     const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-stress.html", dialogData); | ||||
|     const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-stress.hbs", dialogData); | ||||
|     new DialogStress(dialogData, html) | ||||
|       .render(true); | ||||
|   } | ||||
|   | ||||
| @@ -334,6 +334,10 @@ export class RdDTimestamp { | ||||
|     return this.nouvelleHeure().addHeures((12 + heure - this.heure) % 12); | ||||
|   } | ||||
|  | ||||
|   debutJournee() { | ||||
|     return RdDTimestamp.timestamp(this.annee, this.mois, this.jour) | ||||
|   } | ||||
|  | ||||
|   async appliquerDuree(duree, actor) { | ||||
|     const formule = FORMULES_DUREE.find(it => it.code == duree) ?? FORMULES_DUREE.find(it => it.code == ""); | ||||
|     return await formule.calcul(this, actor); | ||||
|   | ||||
| @@ -26,7 +26,7 @@ export class TMRRencontres { | ||||
|    * @param {*} forcedRoll  | ||||
|    */ | ||||
|   async rollRencontre(terrain, forcedRoll) { | ||||
|     const tmrType = TMRUtility.findTMRLike(terrain)?.type | ||||
|     const tmrType = TMRUtility.findTMRLike(terrain, { inclusMauvaise: true })?.type | ||||
|     if (tmrType == undefined) { | ||||
|       return undefined; | ||||
|     } | ||||
| @@ -38,7 +38,7 @@ export class TMRRencontres { | ||||
|     const frequence = it => it.system.frequence[tmrType]; | ||||
|     const row = await this.table.getRandom(frequence, filtreMauvaise, forcedRoll); | ||||
|     if (row) { | ||||
|       await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item', {showSource: false}); | ||||
|       await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item', { showSource: false }); | ||||
|     } | ||||
|  | ||||
|     return row?.document; | ||||
|   | ||||
| @@ -22,7 +22,7 @@ export const TMRType = { | ||||
| export const FLEUVE_COORD = 'Fleuve' | ||||
|  | ||||
| const TMRMapping = { | ||||
|   Fleuve: { type: TMRType.fleuve.type, label: "Fleuve de l'Oubli" }, | ||||
|   Fleuve: { type: TMRType.fleuve.type, label: "Fleuve de l'Oubli", generique: 'fleuve' }, | ||||
|   A1: { type: TMRType.cite.type, label: "Cité Vide" }, | ||||
|   B1: { type: TMRType.plaines.type, label: "Plaines d’Assorh" }, | ||||
|   C1: { type: TMRType.necropole.type, label: "Nécropole de Kroak" }, | ||||
| @@ -281,18 +281,18 @@ export class TMRUtility { | ||||
|     return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label; | ||||
|   } | ||||
|  | ||||
|   static findTMRLike(type, options = { inclusMauvaise: true }) { | ||||
|   static findTMRLike(type, options = { inclusMauvaise: false }) { | ||||
|     const choix = [...Object.values(TMRType)] | ||||
|     if (options.inclusMauvaise) { | ||||
|       choix.push({ name: 'Mauvaise', type: 'mauvaise'}); | ||||
|     } | ||||
|     const selection = Misc.findAllLike(type, choix) | ||||
|     if (selection.length == 0) { | ||||
|       ui.notifications.warn(`Un type de TMR doit être indiqué, '${type}' n'est pas trouvé dans ${choix}`); | ||||
|       ui.notifications.warn(`Un type de TMR doit être indiqué, '${type}' n'est pas trouvé dans ${choix.map(it => it.name).reduce(Misc.joining(', '))}`); | ||||
|       return undefined | ||||
|     } | ||||
|     if (selection.length > 1) { | ||||
|       ui.notifications.warn(`Plusieurs types de TMR pourraient correspondre à '${type}': ${selection.map(it => it.name)}`); | ||||
|       ui.notifications.warn(`Plusieurs types de TMR pourraient correspondre à '${type}': ${selection.map(it => it.name).reduce(Misc.joining(', '))}`); | ||||
|       return undefined; | ||||
|     } | ||||
|     return selection[0] | ||||
| @@ -357,7 +357,7 @@ export class TMRUtility { | ||||
|   } | ||||
|  | ||||
|   static filterTMR(filter) { | ||||
|     return Object.values(TMRMapping).filter(filter); | ||||
|     return Object.values(TMRMapping).filter(it => !it.generique && filter(it)) | ||||
|   } | ||||
|  | ||||
|   static getCasesType(type) { | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user