Compare commits

...

69 Commits

Author SHA1 Message Date
9dd905134b Correction sur les mise à jour en cascade + correction sur le force rendering après un changement de competence
All checks were successful
Release Creation / build (release) Successful in 2m25s
2025-04-06 23:15:10 +02:00
f32b6af7b6 Correction sur les mise à jour en cascade + correction sur le force rendering après un changement de competence 2025-04-06 23:13:59 +02:00
9b8a600e22 Merge pull request '## 12.0.46 - Le double demi d'Astrobazzarh' (#755) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
All checks were successful
Release Creation / build (release) Successful in 1m25s
Reviewed-on: #755
2025-03-18 20:48:20 +01:00
25db7e0712 Amélioration des fermetures de TMR
- un seul message lors de la fermeture au MJ et joueur
- le déclenchement de sort en réserve
2025-03-18 01:56:26 +01:00
776d4ce9ec correction des raffraîchissement lors du sommeil
On peut de nouveau dormir plusieurs heures
2025-03-18 01:50:00 +01:00
1de0806e37 Fix changelog 2025-03-16 00:20:48 +01:00
03366fdf26 Gestion armes naturelles sur defense
All checks were successful
Release Creation / build (release) Successful in 1m51s
2025-03-15 22:04:37 +01:00
14f324360d Merge pull request 'Fix: difficulté des médiations' (#754) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #754
2025-03-15 20:32:20 +01:00
d60c9f1b28 Renommage révéler/masquer le demi-rêve 2025-03-15 17:18:41 +01:00
cf514470fd Fix: difficulté des médiations
La difficulté des méditations n'augmente plus en cas de réussite
et d'échec normal
2025-03-15 17:17:29 +01:00
b09b095897 Formatage changelog
All checks were successful
Release Creation / build (release) Successful in 1m53s
2025-03-05 08:26:37 +01:00
d81965155c Correction sur heures de repos 2025-03-05 08:25:00 +01:00
9fa8a2e6f3 Merge pull request '12.0.44 - Les errements d'Astrobazzarh, suite' (#753) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #753
2025-03-05 08:24:13 +01:00
da7f87fd45 Changelog 12.0.44 2025-03-04 23:06:39 +01:00
6aba92900c Fix erreurs sorts variables
- correction de la sélection de la voie de draconique pour
  sort à voie variable
- en cas de sort avec un coût en rêve numérique, ce n'est pas variable
2025-03-04 23:01:04 +01:00
4939e5564e Fix possessions 2025-03-04 22:46:28 +01:00
40be65a94e Merge pull request 'v11 - sommeil' (#752) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #752
2025-03-04 22:11:00 +01:00
633638a9ab Fix récupération sommeil
Les différentsq updates pouvaient ne pas être visibles lors du sommeil

En forçant un render 20ms après la fin des actions qui impliquent un
sommeil, les mises à jour sont correctes
2025-03-04 22:04:52 +01:00
88a3464eed Add command to run debug server 2025-03-04 21:32:21 +01:00
921e470498 Petit fixes de synchro + essai pour corriger message XP + roll
All checks were successful
Release Creation / build (release) Successful in 2m32s
2025-02-27 22:53:06 +01:00
0009876a6d Merge pull request '12.0.42' (#751) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
All checks were successful
Release Creation / build (release) Successful in 1m39s
Reviewed-on: #751
2025-02-10 07:58:31 +01:00
54785f0c3a Version 12.0.42 2025-02-10 01:54:25 +01:00
df76c4bd78 Corrections automatisations combat
Visiblement des changements sur les callbacks n'avaient pas
été finalisés
2025-02-10 01:54:25 +01:00
5f3c678195 Fix: jet de caractéristique/difficulté
Les jets avec difficulté ne fonctionnaient plus à cause des armes
 à 1 main / à 2 mains
2025-02-09 22:51:06 +01:00
89bbe63340 Merge pull request 'La loupe d'Astrobazzar' (#748) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
All checks were successful
Release Creation / build (release) Successful in 1m27s
Reviewed-on: #748
2025-02-09 00:30:52 +01:00
149990e352 Correction: diminution stress transformé 2025-02-07 21:29:50 +01:00
3e355784c7 Message d'expérience en sort
Adaptation du message d'xp en sort au renommage des voies draconiques
2025-02-07 20:47:20 +01:00
b92055d5dd Commande /tirer cachée
Pour les messages sans actor, la méthode getOwners ne marchait
pas. En cas d'absence d'acteur, les gmroll doivent être pour le
joueur courant et les MJs
2025-02-07 20:47:20 +01:00
220f8142f5 Merge pull request 'v11 Fix choix particulière' (#746) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
All checks were successful
Release Creation / build (release) Successful in 1m45s
Reviewed-on: #746
2025-02-06 10:42:25 +01:00
a8bb00ad0b Fix choix particulière 2025-02-05 22:56:24 +01:00
78e30b5503 Correction message min/max de race 2025-02-02 00:06:38 +01:00
069fef4720 Merge pull request 'Support compétences avec chiffres/tirets' (#744) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
All checks were successful
Release Creation / build (release) Successful in 1m38s
Reviewed-on: #744
2025-02-01 21:12:26 +01:00
e32a7d7540 Tri alphabétique des choix
Permet d'avoir un choix prévisible quand plusieurs choix
s'appliquent (par exemple plusieurs compétences)
2025-01-31 20:36:52 +01:00
0773493851 Fix type rareté 'egal' 2025-01-31 20:21:52 +01:00
da982678b7 Fix: appel expérience sur /rdd 2025-01-31 20:20:55 +01:00
c1066d70f6 Commande '/jet' 2025-01-31 19:44:11 +01:00
5085ba5b54 Support compétences avec chiffres/tirets 2025-01-31 18:23:41 +01:00
f37483a61d Merge pull request '12.0.38 - Les prévisions d'Astrobazzarh' (#743) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
All checks were successful
Release Creation / build (release) Successful in 2m4s
Reviewed-on: #743
2025-01-28 15:07:08 +01:00
5357e53a5f Version 12.0.38 - Les prévisions d'Astrobazzarh 2025-01-27 22:22:28 +01:00
764dde6296 Correction compétence des tâche de lecture 2025-01-27 22:21:58 +01:00
681fbc3177 Use hbs extension 2025-01-27 22:13:33 +01:00
70e3e63001 Corrections compétences créatures 2025-01-26 23:04:12 +01:00
7ed9a4a12b Preparation callbacks pour nouveaux Rolls 2025-01-26 21:29:01 +01:00
acfab362a0 Migration des competence
Migration de Ecriture en Écriture, sinon les combo de sélection
de compétences ne trouvent pas la compétence
2025-01-24 20:28:19 +01:00
3d49a3de11 Utilisation d'async/await dans les listeners
Sans async await dans les feuilles, la feuille n'est pas
toujours mise à jour, laissant visible des informations obsoletes
2025-01-24 20:26:53 +01:00
24518642a7 Merge pull request '12.0.37 - Les enchantements d'Astrobazzarh' (#742) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
All checks were successful
Release Creation / build (release) Successful in 1m38s
Reviewed-on: #742
2025-01-21 09:37:15 +01:00
d917f80e88 Enchantement des gemmes et potions 2025-01-21 03:11:47 +01:00
b29027c61a Cleanup 2025-01-21 03:08:11 +01:00
6083dd41fa Amélioration du split
Bouton split géré avec itemActions

Ajout d'un bouton pour augmenter les piles (pour le MJ)
2025-01-21 03:08:11 +01:00
8969d5e0ed Merge pull request '12.0.36 - L'alchimie d'Astrobazzarh' (#740) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
All checks were successful
Release Creation / build (release) Successful in 1m22s
Reviewed-on: #740
2025-01-19 09:50:20 +01:00
7d135a214f Version 12.0.36 2025-01-19 01:21:12 +01:00
9d66a479c4 Heures des Queues lors de la nuit
L'heure des queues ajoutées à fin chateau dormant sont maintenant
décalées d'une minute dans le passé pour s'appliquer correctement
12 heures draconiques à partir de vaisseau (et non pas
2025-01-19 01:17:57 +01:00
800b4a2f32 Remove unused import 2025-01-19 00:49:58 +01:00
9fc21e6d97 Gestion des actions sur les items
- dans la liste d'équipement, liste d'actions fournie par code
- support d'actions multiples
- listener générique

Utilisation du mécanisme pour tous les items, standardisation de
l'apparence des boutons d'items
2025-01-19 00:38:24 +01:00
ce7f5381ca Fix update endurance/vie
Dans certains cas, les valeurs de vie/endurance n'étaient pas mises
à jour
2025-01-18 23:13:40 +01:00
48acdaaca6 Fix bouton tchat jet encaissement 2025-01-18 23:13:40 +01:00
425c6af672 Correction ouverture feuille de conteneur 2025-01-18 14:49:44 +01:00
4281f76dfb Simplification des actionPrincipales
Préparation pour supporter une liste d'actions sur les items
2025-01-18 14:49:44 +01:00
8ebd6ec771 Normalisation des listes d'items
Utiliser le type d'Item + 's'
2025-01-18 14:49:44 +01:00
14391daa0b Simplification monnaies
Note: bug étrange causé par la 12.0.34, mais le code était bon
2025-01-18 14:49:43 +01:00
ac29e1410e Correction de remedes enchantables
Les remedes ne sont pas enchantable, changement en Alchimie
2025-01-18 14:49:43 +01:00
442ffe9b3a Ajout de jets aux descriptions 2025-01-18 14:49:43 +01:00
d922e4fdd5 Move type constants
Prevent problems of circular dependencies when sepating actions from
items & sheets
2025-01-18 14:49:42 +01:00
a8dc07b4db Enchanter des Potions 2025-01-18 14:49:42 +01:00
40a47ee8a2 Ajout du symbole d20, pour les roll de formule 2025-01-14 22:24:20 +01:00
c5633a9fc5 Fix commande /tmra 2025-01-14 22:23:35 +01:00
7e8da49912 Fix Hook init usage in v12, upgrade version
All checks were successful
Release Creation / build (release) Successful in 2m33s
2025-01-14 00:40:42 +01:00
b524716ede Fix Hook init usage in v12 2025-01-14 00:39:28 +01:00
72a9752820 Fix Hook init usage in v12 2025-01-14 00:23:04 +01:00
389 changed files with 2998 additions and 2320 deletions

View File

@ -1,5 +1,89 @@
# 12.0 # 12.0
## 120.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 ## 12.0.34 - la tête d'Astrobazzarh
- support de liens "jets de dés" - support de liens "jets de dés"
- on peut ajouter des liens "jet de dés" dans les journaux, descriptions, notes, maladresses, ... - on peut ajouter des liens "jet de dés" dans les journaux, descriptions, notes, maladresses, ...
- avec la syntaxe `@roll[...]` on peut ajouter le lien vers: - avec la syntaxe `@roll[...]` on peut ajouter le lien vers:
@ -14,21 +98,26 @@
- gestion des blocs secrets dans les descriptions - gestion des blocs secrets dans les descriptions
## 12.0.33 - la vieillesse d'Astrobazzarh ## 12.0.33 - la vieillesse d'Astrobazzarh
- retour de l'expérience pour les joueurs - retour de l'expérience pour les joueurs
- suppression du message "Pas de caractéristique" sur les jets d'odorat-goût - suppression du message "Pas de caractéristique" sur les jets d'odorat-goût
## 12.0.32 - les rêveries d'Astrobazzarh ## 12.0.32 - les rêveries d'Astrobazzarh
- Ajout des Items Race pour gérer les ajustements liés aux races - Ajout des Items Race pour gérer les ajustements liés aux races
## 12.0.31 - le mausolée d'Astrobazzarh ## 12.0.31 - le mausolée d'Astrobazzarh
- Correction: les automatisation de combat jouer-MJ fonctionnentde nouveau - Correction: les automatisation de combat jouer-MJ fonctionnentde nouveau
## 12.0.30 - le cauchemar d'Astrobazzarh ## 12.0.30 - le cauchemar d'Astrobazzarh
- calcul automatique du niveau des entités selon leur rêve - calcul automatique du niveau des entités selon leur rêve
- la description des créatures venimeuses contient un lien vers leur venin - la description des créatures venimeuses contient un lien vers leur venin
- Correction: les messages de combats ne marchaient plus (Changement combiné Foundry + rêve de Dragon) - Correction: les messages de combats ne marchaient plus (Changement combiné Foundry + rêve de Dragon)
## 12.0.29 - L'indexation d'Astrobazzarh ## 12.0.29 - L'indexation d'Astrobazzarh
- les liens dans la descriptions des sorts pointent vers les sorts du compendium - les liens dans la descriptions des sorts pointent vers les sorts du compendium
- la description du chrasme contient le lien vers son venin plutôt qu'un tableau - la description du chrasme contient le lien vers son venin plutôt qu'un tableau

View File

@ -44,13 +44,13 @@ export class ChatVente {
vente.nbLots = Math.max(0, vente.nbLots - quantite) vente.nbLots = Math.max(0, vente.nbLots - quantite)
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots) 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.update({ content: html });
chatMessage.render(true); chatMessage.render(true);
} }
static async displayAchatVente(vente) { 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)) const chatMessage = await ChatMessage.create(RdDUtility.chatDataSetup(html))
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots) await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
await chatMessage.setFlag(SYSTEM_RDD, DETAIL_VENTE, { await chatMessage.setFlag(SYSTEM_RDD, DETAIL_VENTE, {

View File

@ -29,7 +29,7 @@ export class DialogItemAchat extends Dialog {
} }
DialogItemAchat.changeNombreLots(venteData, 1) 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) new DialogItemAchat(html, venteData).render(true)
} }

View File

@ -20,7 +20,7 @@ export class DialogItemVente extends Dialog {
quantiteIllimite: item.isItemCommerce() ? quantiteMax == undefined : !item.parent, quantiteIllimite: item.isItemCommerce() ? quantiteMax == undefined : !item.parent,
isOwned: 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); return new DialogItemVente(venteData, html).render(true);
} }

View File

@ -12,13 +12,13 @@ import { RdDSheetUtility } from "./rdd-sheet-utility.js";
import { STATUSES } from "./settings/status-effects.js"; import { STATUSES } from "./settings/status-effects.js";
import { MAINS_DIRECTRICES } from "./actor.js"; import { MAINS_DIRECTRICES } from "./actor.js";
import { RdDBaseActorReveSheet } from "./actor/base-actor-reve-sheet.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 { RdDItemBlessure } from "./item/blessure.js";
import { RdDEmpoignade } from "./rdd-empoignade.js"; import { RdDEmpoignade } from "./rdd-empoignade.js";
import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js"; import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.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"; import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -30,7 +30,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.hbs",
width: 550, width: 550,
showCompNiveauBase: false, showCompNiveauBase: false,
vueArchetype: false, vueArchetype: false,
@ -126,80 +126,73 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
}) })
this.html.find('.show-hide-competences').click(async event => { this.html.find('.show-hide-competences').click(async event => {
this.options.showCompNiveauBase = !this.options.showCompNiveauBase; this.options.showCompNiveauBase = !this.options.showCompNiveauBase
this.render(true); 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 // Everything below here is only needed if the sheet is editable
if (!this.options.editable) return; if (!this.options.editable) return;
this.html.find('.sheet-possession-attack').click(async event => { this.html.find('.sheet-possession-attack').click(async event => {
const poss = RdDSheetUtility.getItem(event, this.actor) 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 => { this.html.find('.subacteur-coeur-toggle a').click(async event => {
const subActorIdactorId = RdDSheetUtility.getEventItemData(event, 'subactor-id') const subActorIdactorId = RdDSheetUtility.getEventItemData(event, 'subactor-id')
const coeurNombre = $(event.currentTarget).data('numero-coeur') 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 => { this.html.find('.subacteur-tendre-moment').click(async event => {
const subActorId = RdDSheetUtility.getEventItemData(event, 'subactor-id') 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 => { this.html.find('.subacteur-delete').click(async event => {
const li = RdDSheetUtility.getEventElement(event); const li = RdDSheetUtility.getEventElement(event);
const subActorId = li.data("subactor-id"); const subActorId = li.data("subactor-id");
this.deleteSubActeur(subActorId, li); this.deleteSubActeur(subActorId, li);
}) })
this.html.find("input.derivee-value[name='system.compteurs.stress.value']").change(async event => { this.html.find("input.derivee-value[name='system.compteurs.stress.value']").change(async event =>
this.actor.updateCompteurValue("stress", parseInt(event.target.value)); await this.actor.updateCompteurValue("stress", parseInt(event.target.value))
}); );
this.html.find("input.derivee-value[name='system.compteurs.experience.value']").change(async event => { this.html.find("input.derivee-value[name='system.compteurs.experience.value']").change(async event =>
this.actor.updateCompteurValue("experience", parseInt(event.target.value)); await this.actor.updateCompteurValue("experience", parseInt(event.target.value))
}); );
this.html.find('.creer-tache').click(async event => this.createEmptyTache()); this.html.find('.creer-tache').click(async event => await this.createEmptyTache());
this.html.find('.creer-une-oeuvre').click(async event => this.selectTypeOeuvreToCreate()); this.html.find('.creer-une-oeuvre').click(async event => await this.selectTypeOeuvreToCreate());
this.html.find('.creer-tache-blessure-legere').click(async event => RdDItemBlessure.createTacheSoinBlessure(this.actor, 2)); 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 => RdDItemBlessure.createTacheSoinBlessure(this.actor, 4)); 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 => RdDItemBlessure.createTacheSoinBlessure(this.actor, 6)); 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 => { this.html.find('.blessure-premierssoins-done').change(async event => {
const blessure = this.getBlessure(event); await this.getBlessure(event)?.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } });
await blessure?.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } });
}); });
this.html.find('.blessure-soinscomplets-done').change(async event => { this.html.find('.blessure-soinscomplets-done').change(async event => {
const blessure = this.getBlessure(event); await this.getBlessure(event)?.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } })
await blessure?.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } })
}); });
this.html.find('.blessure-premierssoins-bonus').change(async event => { this.html.find('.blessure-premierssoins-bonus').change(async event => {
const blessure = this.getBlessure(event); await this.getBlessure(event)?.setSoinsBlessure({ premierssoins: { bonus: Number(event.currentTarget.value) } })
await blessure?.setSoinsBlessure({ premierssoins: { bonus: Number(event.currentTarget.value) } })
}); });
this.html.find('.blessure-soinscomplets-bonus').change(async event => { this.html.find('.blessure-soinscomplets-bonus').change(async event => {
const blessure = this.getBlessure(event); await this.getBlessure(event)?.setSoinsBlessure({ soinscomplets: { bonus: Number(event.currentTarget.value) } })
await blessure?.setSoinsBlessure({ soinscomplets: { bonus: Number(event.currentTarget.value) } })
}); });
// Equip Inventory Item this.html.find('.roll-chance-actuelle').click(async event => await this.actor.rollCarac('chance-actuelle'))
this.html.find('.item-equip').click(async event => this.actor.equiperObjet(RdDSheetUtility.getItemId(event))) this.html.find('.button-appel-chance').click(async event => await this.actor.rollAppelChance())
this.html.find('.roll-chance-actuelle').click(async event => this.actor.rollCarac('chance-actuelle'))
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('.action-chant').click(async event => await this.actor.rollChant(RdDSheetUtility.getItemId(event)))
this.html.find('.tache-label a').click(async event => this.actor.rollTache(RdDSheetUtility.getItemId(event))) this.html.find('.action-danse').click(async event => await this.actor.rollDanse(RdDSheetUtility.getItemId(event)))
this.html.find('.meditation-label a').click(async event => this.actor.rollMeditation(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('.chant-label a').click(async event => this.actor.rollChant(RdDSheetUtility.getItemId(event))) this.html.find('.action-jeu').click(async event => await this.actor.rollJeu(RdDSheetUtility.getItemId(event)))
this.html.find('.danse-label a').click(async event => this.actor.rollDanse(RdDSheetUtility.getItemId(event))) this.html.find('.action-recettecuisine').click(async event => await this.actor.rollRecetteCuisine(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('.description-aleatoire').click(async event => new AppPersonnageAleatoire(this.actor).render(true)) this.html.find('.description-aleatoire').click(async event => new AppPersonnageAleatoire(this.actor).render(true))
if (game.user.isGM) { if (game.user.isGM) {
@ -215,17 +208,16 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
await this.actor.deleteExperienceLog(0, key + 1); await this.actor.deleteExperienceLog(0, key + 1);
}); });
// Boutons spéciaux MJs // Boutons spéciaux MJs
this.html.find('.forcer-tmr-aleatoire').click(async event => this.actor.reinsertionAleatoire("Action MJ")) 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 => this.actor.addDonDeHautReve()) this.html.find('.don-de-haut-reve').click(async event => await 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 => await this.actor.changeTMRVisible())
this.html.find('.afficher-tmr').click(async event => this.actor.changeTMRVisible())
} }
// Points de reve actuel // Points de reve actuel
this.html.find('.roll-reve-actuel').click(async event => this.actor.rollCarac('reve-actuel', {resistance:true})) this.html.find('.roll-reve-actuel').click(async event => await this.actor.rollCarac('reve-actuel', { resistance: true }))
this.html.find('.empoignade-label a').click(async event => RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor))) 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 // Initiative pour l'arme
this.html.find('.roll-init-arme').click(async event => { this.html.find('.roll-init-arme').click(async event => {
@ -238,30 +230,34 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
}) })
// Display TMR // Display TMR
this.html.find('.button-tmr').click(async event => this.actor.displayTMR("normal")) this.html.find('.button-tmr').click(async event => await this.actor.displayTMR("normal"))
this.html.find('.button-tmr-rapide').click(async event => this.actor.displayTMR("rapide")) 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('.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('.carac-xp-augmenter').click(async event => await 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-xp-augmenter').click(async event => await this.actor.updateCompetenceXPAuto(RdDSheetUtility.getItemId(event)))
this.html.find('.competence-stress-augmenter').click(async event => this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event))) this.html.find('.competence-stress-augmenter').click(async event =>{
await this.actor.updateCompetenceStress(RdDSheetUtility.getItemId(event))
this.render(true)
}
)
if (this.options.vueDetaillee) { if (this.options.vueDetaillee) {
// On carac change // On carac change
this.html.find('input.carac-xp').change(async event => { this.html.find('input.carac-xp').change(async event => {
let caracName = event.currentTarget.name.replace(".xp", "").replace("system.carac.", ""); let caracName = event.currentTarget.name.replace(".xp", "").replace("system.carac.", "")
this.actor.updateCaracXP(caracName, parseInt(event.target.value)); await this.actor.updateCaracXP(caracName, parseInt(event.target.value))
}); })
// On competence xp change // On competence xp change
this.html.find('input.competence-xp').change(async event => { this.html.find('input.competence-xp').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value
this.actor.updateCompetenceXP(compName, parseInt(event.target.value)); await this.actor.updateCompetenceXP(compName, parseInt(event.target.value))
}); })
this.html.find('input.competence-xp-sort').change(async event => { this.html.find('input.competence-xp-sort').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value
this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value)); await this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value))
}); })
this.html.find('.toggle-archetype').click(async event => { this.html.find('.toggle-archetype').click(async event => {
this.options.vueArchetype = !this.options.vueArchetype; this.options.vueArchetype = !this.options.vueArchetype;
@ -270,27 +266,27 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
// On competence archetype change // On competence archetype change
this.html.find('.competence-archetype').change(async event => { this.html.find('.competence-archetype').change(async event => {
let compName = event.currentTarget.attributes.compname.value; 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 // 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('.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 => this.actor.setPointsDeSeuil(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('.stress-test').click(async event => await this.actor.transformerStress())
this.html.find('.moral-malheureux').click(async event => this.actor.jetDeMoral('malheureuse')) this.html.find('.moral-malheureux').click(async event => await this.actor.jetDeMoral('malheureuse'))
this.html.find('.moral-neutre').click(async event => this.actor.jetDeMoral('neutre')) this.html.find('.moral-neutre').click(async event => await this.actor.jetDeMoral('neutre'))
this.html.find('.moral-heureux').click(async event => this.actor.jetDeMoral('heureuse')) this.html.find('.moral-heureux').click(async event => await this.actor.jetDeMoral('heureuse'))
this.html.find('.button-ethylisme').click(async event => this.actor.jetEthylisme()) 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-plus').click(async event => await this.actor.reveActuelIncDec(1))
this.html.find('.ptreve-actuel-moins').click(async event => 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 => this.actor.chanceActuelleIncDec(1)) this.html.find('.chance-actuelle-plus').click(async event => await this.actor.chanceActuelleIncDec(1))
this.html.find('.chance-actuelle-moins').click(async event => 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 => this.actor.santeIncDec("fatigue", 1)) this.html.find('.fatigue-plus').click(async event => await this.actor.santeIncDec("fatigue", 1))
this.html.find('.fatigue-moins').click(async event => this.actor.santeIncDec("fatigue", -1)) this.html.find('.fatigue-moins').click(async event => await this.actor.santeIncDec("fatigue", -1))
} }
getBlessure(event) { getBlessure(event) {
@ -327,7 +323,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async selectTypeOeuvreToCreate() { async selectTypeOeuvreToCreate() {
let types = RdDItem.getTypesOeuvres(); 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) { for (let typeName of types) {
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>` content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
} }

File diff suppressed because it is too large Load Diff

View File

@ -1,6 +1,6 @@
import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js"; import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js";
import { Grammar } from "../grammar.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 { RdDSheetUtility } from "../rdd-sheet-utility.js";
import { RdDBaseActorSheet } from "./base-actor-sheet.js"; import { RdDBaseActorSheet } from "./base-actor-sheet.js";
@ -26,16 +26,17 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet {
// Everything below here is only needed if the sheet is editable // Everything below here is only needed if the sheet is editable
if (!this.options.editable) return; 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.html.find('.roll-carac').click(async event => {
this.actor.rollCarac(Grammar.toLowerCaseNoAccent(event.currentTarget.attributes['data-carac-name'].value))}) await 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('.roll-competence').click(async event => await this.actor.rollCompetence(RdDSheetUtility.getItemId(event)));
this.html.find('.endurance-moins').click(async event => this.actor.santeIncDec("endurance", -1)); 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) { if (game.user.isGM) {
this.html.find('.button-remise-a-neuf').click(async event => this.actor.remiseANeuf()) this.html.find('.button-remise-a-neuf').click(async event => await 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('.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('.enlever-tous-effets').click(async event => await this.actor.removeEffects());
} }
this.html.find('.competence-add').click(async event => this.html.find('.competence-add').click(async event =>
@ -55,14 +56,13 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet {
if (this.options.vueDetaillee) { if (this.options.vueDetaillee) {
// On carac change // On carac change
this.html.find('.carac-value').change(async event => { this.html.find('.carac-value').change(async event => {
let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", ""); let caracName = event.currentTarget.name.replace(".value", "").replace("system.carac.", "")
this.actor.updateCarac(caracName, parseInt(event.target.value)); await this.actor.updateCarac(caracName, parseInt(event.target.value))
}); });
// On competence change // On competence change
this.html.find('.competence-value').change(async event => { this.html.find('.competence-value').change(async event => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value
//console.log("Competence changed :", compName); await this.actor.updateCompetence(compName, parseInt(event.target.value))
this.actor.updateCompetence(compName, parseInt(event.target.value));
}); });
} }
} }

View File

@ -7,7 +7,7 @@ import { RdDRoll } from "../rdd-roll.js";
import { RdDUtility } from "../rdd-utility.js"; import { RdDUtility } from "../rdd-utility.js";
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
import { RdDBaseActor } from "./base-actor.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 { RdDItemCompetence } from "../item-competence.js";
import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
import { RdDItemArme } from "../item-arme.js"; import { RdDItemArme } from "../item-arme.js";
@ -15,6 +15,7 @@ import { StatusEffects } from "../settings/status-effects.js";
import { Targets } from "../targets.js"; import { Targets } from "../targets.js";
import { RdDConfirm } from "../rdd-confirm.js"; import { RdDConfirm } from "../rdd-confirm.js";
import { RdDCarac } from "../rdd-carac.js"; import { RdDCarac } from "../rdd-carac.js";
import { RdDRollResult } from "../rdd-roll-result.js";
import { ChatUtility } from "../chat-utility.js"; import { ChatUtility } from "../chat-utility.js";
import { DialogValidationEncaissement } from "../dialog-validation-encaissement.js"; import { DialogValidationEncaissement } from "../dialog-validation-encaissement.js";
@ -268,30 +269,17 @@ 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, const dialog = await RdDRoll.create(this, rollData,
{ html: template, close: async html => await this._onCloseRollDialog(html) }, { html: template, close: async html => await this._onCloseRollDialog(html) },
{ { name: name, label: label, callbacks: [this.createCallbackExperience(), this.createCallbackAppelAuMoral()].concat(callbacks) })
name: name, dialog.render(true)
label: label,
callbacks: [
this.createCallbackExperience(),
this.createCallbackAppelAuMoral(),
{ action: callbackAction }
]
});
dialog.render(true);
return dialog return dialog
} }
createEmptyCallback() { createCallbackExperience() { return { action: r => { } } }
return { createCallbackAppelAuMoral() { return { action: r => { } } }
condition: r => false,
action: r => { }
};
}
createCallbackExperience() { return this.createEmptyCallback(); }
createCallbackAppelAuMoral() { return this.createEmptyCallback(); }
async _onCloseRollDialog(html) { } async _onCloseRollDialog(html) { }
async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) { async rollCaracCompetence(caracName, compName, diff, options = { title: "" }) {
@ -299,8 +287,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
const competence = this.getCompetence(compName); const competence = this.getCompetence(compName);
await this.openRollDialog({ await this.openRollDialog({
name: 'jet-competence', name: 'jet-competence',
label: competence? 'Jet ' + Grammar.apostrophe('de', competence.name) : `Jet sans compétence (${compName})`, label: competence ? 'Jet ' + Grammar.apostrophe('de', competence.name) : `Jet sans compétence (${compName})`,
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html', template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs',
rollData: { rollData: {
alias: this.getAlias(), alias: this.getAlias(),
carac: this.system.carac, carac: this.system.carac,
@ -310,7 +298,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
competence: competence, competence: competence,
show: { title: options?.title ?? '' } show: { title: options?.title ?? '' }
}, },
callbackAction: r => this.$onRollCompetence(r, options) callbacks: [async r => this.$onRollCompetence(r, options)]
}); });
} }
/** /**
@ -353,16 +341,14 @@ export class RdDBaseActorReve extends RdDBaseActor {
const selectedCaracName = ['apparence', 'perception', 'force', 'reve'].find(it => carac[it] != undefined) const selectedCaracName = ['apparence', 'perception', 'force', 'reve'].find(it => carac[it] != undefined)
await this.openRollDialog({ await this.openRollDialog({
name: `jet-${this.id}`,
label: `Jet de ${this.getAlias()}`,
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll.html',
rollData: { rollData: {
alias: this.getAlias(),
carac: carac, carac: carac,
selectedCarac: carac[selectedCaracName], selectedCarac: carac[selectedCaracName],
selectedCaracName: selectedCaracName, selectedCaracName: selectedCaracName,
competences: this.itemTypes['competence'] competences: this.itemTypes['competence']
}, },
callbackAction: r => this.$onRollCaracResult(r) callbacks: [{ action: r => this.$onRollCaracResult(r) }]
}) })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -373,32 +359,38 @@ export class RdDBaseActorReve extends RdDBaseActor {
foundry.utils.mergeObject(options, { resistance: false, diff: 0 }, { overwrite: false }) foundry.utils.mergeObject(options, { resistance: false, diff: 0 }, { overwrite: false })
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
let selectedCarac = this.getCaracByName(caracName) 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({ await this.openRollDialog({
name: 'jet-' + caracName, name: 'jet-' + caracName,
label: 'Jet ' + Grammar.apostrophe('de', selectedCarac.label), label: title,
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html', template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.hbs',
rollData: { rollData: {
alias: this.getAlias(),
selectedCarac: selectedCarac, selectedCarac: selectedCarac,
competences: this.itemTypes['competence'], competences: this.itemTypes['competence'],
diffLibre: options.diff ?? 0, diffLibre: options.diff ?? 0,
jetResistance: options.resistance ? caracName : undefined jetResistance: jetResistance
}, },
callbackAction: r => this.$onRollCaracResult(r) callbacks: [{ action: r => this.$onRollCaracResult(r) }]
}); });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async $onRollCaracResult(rollData) { async $onRollCaracResult(rollData) {
// Final chat message // 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 }) { async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) {
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
const competence = this.getCompetence(idOrName); 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) { if (competence.type == ITEM_TYPES.competencecreature) {
const token = RdDUtility.getSelectedToken(this) const token = RdDUtility.getSelectedToken(this)
const arme = RdDItemCompetenceCreature.armeCreature(competence) const arme = RdDItemCompetenceCreature.armeCreature(competence)
@ -416,18 +408,18 @@ export class RdDBaseActorReve extends RdDBaseActor {
// Transformer la competence de créature // Transformer la competence de créature
RdDItemCompetenceCreature.setRollDataCreature(rollData) RdDItemCompetenceCreature.setRollDataCreature(rollData)
} }
const dialogLabel = 'Jet ' + Grammar.apostrophe('de', competence.name);
await this.openRollDialog({ await this.openRollDialog({
name: 'jet-competence', name: 'jet-competence',
label: 'Jet ' + Grammar.apostrophe('de', competence.name), label: dialogLabel,
template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html', template: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs',
rollData: rollData, rollData: rollData,
callbackAction: r => this.$onRollCompetence(r, options) callbacks: [{ action: r => this.$onRollCompetence(r, options) }]
}); });
} }
async $onRollCompetence(rollData, 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) { if (options?.onRollAutomate) {
options.onRollAutomate(rollData); options.onRollAutomate(rollData);
} }
@ -527,7 +519,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
await ChatUtility.createChatWithRollMode( await ChatUtility.createChatWithRollMode(
{ {
roll: encaissement.roll, 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 this
) )
@ -537,7 +529,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
encaissement.isGM = true encaissement.isGM = true
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getGMs(), 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)
}); });
} }
} }
@ -562,10 +554,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
await entite.setEntiteReveAccordee(this); await entite.setEntiteReveAccordee(this);
} }
await RdDResolutionTable.displayRollData(rollData, this, 'chat-resultat-accorder-cauchemar.html'); await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-accorder-cauchemar.hbs');
if (rolled.isPart) { await this.appliquerAjoutExperience(rollData, true);
await this.appliquerAjoutExperience(rollData, true);
}
return rolled.isSuccess; return rolled.isSuccess;
} }

View File

@ -17,20 +17,20 @@ export class RdDBaseActorSangSheet extends RdDBaseActorReveSheet {
// Everything below here is only needed if the sheet is editable // Everything below here is only needed if the sheet is editable
if (!this.options.editable) return; if (!this.options.editable) return;
this.html.find('.creer-blessure-legere').click(async event => RdDItemBlessure.createBlessure(this.actor, 2)); this.html.find('.creer-blessure-legere').click(async event => await RdDItemBlessure.createBlessure(this.actor, 2));
this.html.find('.creer-blessure-grave').click(async event => RdDItemBlessure.createBlessure(this.actor, 4)); this.html.find('.creer-blessure-grave').click(async event => await RdDItemBlessure.createBlessure(this.actor, 4));
this.html.find('.creer-blessure-critique').click(async event => RdDItemBlessure.createBlessure(this.actor, 6)); this.html.find('.creer-blessure-critique').click(async event => 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-contusion').click(async event => await RdDItemBlessure.applyFullBlessure(this.actor, 0));
this.html.find('.subir-blessure-legere').click(async event => RdDItemBlessure.applyFullBlessure(this.actor, 2)); this.html.find('.subir-blessure-legere').click(async event => await RdDItemBlessure.applyFullBlessure(this.actor, 2));
this.html.find('.subir-blessure-grave').click(async event => RdDItemBlessure.applyFullBlessure(this.actor, 4)); this.html.find('.subir-blessure-grave').click(async event => await RdDItemBlessure.applyFullBlessure(this.actor, 4));
this.html.find('.subir-blessure-critique').click(async event => RdDItemBlessure.applyFullBlessure(this.actor, 6)); 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('.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-plus').click(async event => await this.actor.santeIncDec("vie", 1))
this.html.find('.vie-moins').click(async event => this.actor.santeIncDec("vie", -1)) this.html.find('.vie-moins').click(async event => await this.actor.santeIncDec("vie", -1))
} }
async jetEndurance() { async jetEndurance() {

View File

@ -1,7 +1,7 @@
import { RdDUtility } from "../rdd-utility.js"; import { RdDUtility } from "../rdd-utility.js";
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
import { STATUSES } from "../settings/status-effects.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 { RdDBaseActorReve } from "./base-actor-reve.js";
import { RdDDice } from "../rdd-dice.js"; import { RdDDice } from "../rdd-dice.js";
import { RdDItemBlessure } from "../item/blessure.js"; import { RdDItemBlessure } from "../item/blessure.js";
@ -39,7 +39,12 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return 0; return 0;
} }
getFatigueRestante() { return this.getFatigueMax() - this.getFatigueActuelle() } isCumulFatigueCauseSommeil(cumulFatigue){
return ReglesOptionnelles.isUsing("appliquer-fatigue")
? (this.getFatigueRestante() <= cumulFatigue)
: (this.getEnduranceActuelle() <= cumulFatigue)
}
getFatigueRestante() {return this.getFatigueMax() - this.getFatigueActuelle() }
getFatigueMin() { return this.system.sante.endurance.max - this.system.sante.endurance.value } getFatigueMin() { return this.system.sante.endurance.max - this.system.sante.endurance.value }
malusFatigue() { malusFatigue() {

View File

@ -3,9 +3,11 @@ import { Misc } from "../misc.js";
import { DialogSplitItem } from "../dialog-split-item.js"; import { DialogSplitItem } from "../dialog-split-item.js";
import { RdDSheetUtility } from "../rdd-sheet-utility.js"; import { RdDSheetUtility } from "../rdd-sheet-utility.js";
import { Monnaie } from "../item-monnaie.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 { RdDItemCompetenceCreature } from "../item-competencecreature.js";
import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js"; import { RdDTextEditor } from "../apps/rdd-text-roll-editor.js";
import { ItemAction } from "../item/item-actions.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
/** /**
@ -26,7 +28,7 @@ export class RdDBaseActorSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
Monnaie.validerMonnaies(this.actor.itemTypes['monnaie']); Monnaie.validerMonnaies(this.actor)
this.actor.computeEtatGeneral(); this.actor.computeEtatGeneral();
let formData = { let formData = {
@ -42,7 +44,7 @@ export class RdDBaseActorSheet extends ActorSheet {
effects: this.actor.effects effects: this.actor.effects
} }
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes); RdDUtility.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
formData.calc = { formData.calc = {
fortune: Monnaie.toSolsDeniers(this.actor.getFortune()), fortune: Monnaie.toSolsDeniers(this.actor.getFortune()),
prixTotalEquipement: this.actor.computePrixTotalEquipement(), prixTotalEquipement: this.actor.computePrixTotalEquipement(),
@ -54,6 +56,7 @@ export class RdDBaseActorSheet extends ActorSheet {
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs); formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
formData.competences.filter(it => it.type == ITEM_TYPES.competencecreature) formData.competences.filter(it => it.type == ITEM_TYPES.competencecreature)
.forEach(it => it.isdommages = RdDItemCompetenceCreature.isDommages(it)) .forEach(it => it.isdommages = RdDItemCompetenceCreature.isDommages(it))
return formData; return formData;
} }
@ -77,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 */ /* -------------------------------------------- */ /** @override */
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
this.html = 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 => { this.html.find('.conteneur-name a').click(async event => {
RdDUtility.toggleAfficheContenu(this.getItemId(event)); RdDUtility.toggleAfficheContenu(this.getItemId(event))
this.render(true); 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('.actor-montrer').click(async event => await this.actor.postActorToChat());
this.html.find('.item-montrer').click(async event => this.getItem(event)?.postItemToChat());
this.html.find('.recherche') this.html.find('.recherche')
.each((index, field) => { .each((index, field) => {
this._rechercheSelectArea(field); this._rechercheSelectArea(field);
}) })
.keyup(async event => this._rechercherKeyup(event)) .keyup(async event => this._rechercherKeyup(event))
.change(async event => this._rechercherKeyup(event)); .change(async event => this._rechercherKeyup(event))
this.html.find('.recherche').prop("disabled", false);
this.html.find('.recherche').prop("disabled", false)
// Everything below here is only needed if the sheet is editable // Everything below here is only needed if the sheet is editable
if (!this.options.editable) return; if (!this.options.editable) return;
this.html.find('.item-action').click(async event => { this.html.find('.item-equip-armure').click(async event => await this.actor.equiperObjet(this.getItem(event)))
const item = RdDSheetUtility.getItem(event, this.actor); this.html.find('.item-delete').click(async event => await RdDUtility.confirmActorItemDelete(this.getItem(event), this.actor));
item?.actionPrincipale(this.actor, async () => this.render()) 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('.creer-un-objet').click(async event => await this.selectObjetTypeToCreate())
this.html.find('.item-split').click(async event => { this.html.find('.nettoyer-conteneurs').click(async event => await this.actor.nettoyerConteneurs())
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('.vue-detaillee').click(async event => { this.html.find('.vue-detaillee').click(async event => {
this.options.vueDetaillee = !this.options.vueDetaillee; this.options.vueDetaillee = !this.options.vueDetaillee
this.render(true); this.render(true)
}); });
} }
itemActionEdit(event) {
const item = this.getItem(event);
return item?.sheet.render(true);
}
_rechercherKeyup(event) { _rechercherKeyup(event) {
const currentTarget = event.currentTarget; const currentTarget = event.currentTarget;
const nouvelleRecherche = this._optionRecherche(currentTarget); const nouvelleRecherche = this._optionRecherche(currentTarget);
@ -246,7 +191,7 @@ export class RdDBaseActorSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async selectObjetTypeToCreate() { async selectObjetTypeToCreate() {
let types = this.getTypesInventaire().sort(Misc.ascending(type => Misc.typeName('Item', type))); 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) { for (let typeName of types) {
content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>` content += `<option value="${typeName}">${Misc.typeName('Item', typeName)}</option>`
} }

View File

@ -3,7 +3,7 @@ import { ChatUtility } from "../chat-utility.js";
import { SYSTEM_SOCKET_ID } from "../constants.js"; import { SYSTEM_SOCKET_ID } from "../constants.js";
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { Monnaie } from "../item-monnaie.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 { Misc } from "../misc.js";
import { RdDAudio } from "../rdd-audio.js"; import { RdDAudio } from "../rdd-audio.js";
import { RdDConfirm } from "../rdd-confirm.js"; import { RdDConfirm } from "../rdd-confirm.js";
@ -244,16 +244,19 @@ export class RdDBaseActor extends Actor {
async onUpdateActor(update, options, actorId) { } async onUpdateActor(update, options, actorId) { }
async onDeleteItem(item, options, id) { async onDeleteItem(item, options, id) {
if (item.isInventaire()) { if (item.isInventaire()) {
this._removeItemFromConteneur(item) await this._removeItemFromConteneur(item)
} }
} }
_removeItemFromConteneur(item) { async _removeItemFromConteneur(item) {
this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id)) const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id))
.forEach(conteneur => { .map(conteneur => {
const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id); const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id)
conteneur.update({ 'system.contenu': nouveauContenu }); return { _id: conteneur.id, 'system.contenu': nouveauContenu }
}); })
if (updates.length > 0) {
await this.updateEmbeddedDocuments('Item', updates)
}
} }
async onTimeChanging(oldTimestamp, newTimestamp) { async onTimeChanging(oldTimestamp, newTimestamp) {
@ -414,7 +417,7 @@ export class RdDBaseActor extends Actor {
user: achat.userId, user: achat.userId,
speaker: { alias: (acheteur ?? vendeur).getAlias() }, speaker: { alias: (acheteur ?? vendeur).getAlias() },
whisper: ChatUtility.getOwners(this), 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) { if (!achat.vente.quantiteIllimite) {
@ -731,31 +734,26 @@ export class RdDBaseActor extends Actor {
name: this.getAlias(), name: this.getAlias(),
system: { description: this.system.description } 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))); .then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
} }
actionImpossible(action) { actionImpossible(action) {
ui.notifications.info(`${this.getAlias()} ne peut pas faire cette action: ${action}`) ui.notifications.info(`${this.getAlias()} ne peut pas faire cette action: ${action}`)
} }
async jetEthylisme() { this.actionImpossible("jet d'éthylisme") } async jetEthylisme() { this.actionImpossible("jet d'éthylisme") }
async rollAppelChance() { this.actionImpossible("appel à la chance") } async rollAppelChance() { this.actionImpossible("appel à la chance") }
async jetDeMoral() { this.actionImpossible("jet de moral") } 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 resetItemUse() { }
async incDecItemUse(itemId, inc = 1) { } async incDecItemUse(itemId, shouldIncrease = true) { }
getItemUse(itemId) { return 0; } getItemUse(itemId) { return 0; }
async finDeRound(options = { terminer: false }) { } async finDeRound(options = { terminer: false }) { }
isActorCombat() { return false } isActorCombat() { return false }
getCaracInit(competence) { return 0 } getCaracInit(competence) { return 0 }
listActionsCombat() { return [] } listActionsCombat() { return [] }
listActionsPossessions() { listActionsPossessions() {
return this.itemTypes[ITEM_TYPES.possession] return this.itemTypes[ITEM_TYPES.possession]

View File

@ -12,7 +12,7 @@ export class RdDCommerceSheet extends RdDBaseActorSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.hbs",
width: 600, height: 720, width: 600, height: 720,
tabs: [] tabs: []
}, { inplace: false }) }, { inplace: false })
@ -45,6 +45,7 @@ export class RdDCommerceSheet extends RdDBaseActorSheet {
super.activateListeners(html); super.activateListeners(html);
this.html.find('a.item-acheter').click(async event => await this.vente(this.getItem(event))); 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; if (!this.options.editable) return;

View File

@ -10,7 +10,7 @@ export class RdDCreatureSheet extends RdDBaseActorSangSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return foundry.utils.mergeObject(RdDBaseActorSangSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorSangSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.hbs",
width: 640, height: 720 width: 640, height: 720
}, { inplace: false }) }, { inplace: false })
} }
@ -26,15 +26,15 @@ export class RdDCreatureSheet extends RdDBaseActorSangSheet {
// On competence change // On competence change
this.html.find('.creature-carac').change(async event => { this.html.find('.creature-carac').change(async event => {
let compName = event.currentTarget.attributes.compname.value; 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 => { this.html.find('.creature-niveau').change(async event => {
let compName = event.currentTarget.attributes.compname.value; 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 => { this.html.find('.creature-dommages').change(async event => {
let compName = event.currentTarget.attributes.compname.value; 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));
}); });
} }
} }

View File

@ -1,5 +1,5 @@
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { ITEM_TYPES } from "../item.js"; import { ITEM_TYPES } from "../constants.js";
import { LIST_CARAC_AUTRES } from "../rdd-carac.js"; import { LIST_CARAC_AUTRES } from "../rdd-carac.js";
import { RdDBaseActorSang } from "./base-actor-sang.js"; import { RdDBaseActorSang } from "./base-actor-sang.js";

View File

@ -8,7 +8,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.hbs",
width: 640, height: 720, width: 640, height: 720,
}, { inplace: false }) }, { inplace: false })
} }
@ -33,15 +33,15 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
// On competence change // On competence change
this.html.find('.creature-carac').change(async event => { this.html.find('.creature-carac').change(async event => {
let compName = event.currentTarget.attributes.compname.value; 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 => { this.html.find('.creature-dommages').change(async event => {
let compName = event.currentTarget.attributes.compname.value; 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 => this.html.find('.resonance-add').click(async event =>
DialogSelect.select({ await DialogSelect.select({
label: "Choisir un acteur à accorder", label: "Choisir un acteur à accorder",
list: game.actors.filter(it => it.isPersonnage() && it.prototypeToken.actorLink) list: game.actors.filter(it => it.isPersonnage() && it.prototypeToken.actorLink)
}, },

View File

@ -1,5 +1,5 @@
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js"; 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 { Misc } from "../misc.js";
import { RdDCarac } from "../rdd-carac.js"; import { RdDCarac } from "../rdd-carac.js";
import { RdDEncaisser } from "../rdd-roll-encaisser.js"; import { RdDEncaisser } from "../rdd-roll-encaisser.js";

View File

@ -6,8 +6,8 @@ import { ExportScriptarium } from "./export-scriptarium.js";
import { CATEGORIES_COMPETENCES, CATEGORIES_DRACONIC, Mapping } from "./mapping.js"; import { CATEGORIES_COMPETENCES, CATEGORIES_DRACONIC, Mapping } from "./mapping.js";
export class RdDActorExportSheet extends RdDActorSheet { export class RdDActorExportSheet extends RdDActorSheet {
static async init() { static init() {
await loadTemplates([ loadTemplates([
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs", "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/blessure.hbs",
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/blessures.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" }) Actors.registerSheet(SYSTEM_RDD, RdDActorExportSheet, { types: ["personnage"], makeDefault: false, label: "Feuille simplifiée" })
} }
static get defaultOptions() { static get defaultOptions() {
return foundry.utils.mergeObject(RdDActorSheet.defaultOptions, { return foundry.utils.mergeObject(RdDActorSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/actor-encart-sheet.hbs", 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 => this.html.find('.click-blessure-add').click(async event =>
await this.actor.ajouterBlessure({ await this.actor.ajouterBlessure({
gravite: this.html.find(event.currentTarget).data('gravite') 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], ExportScriptarium.INSTANCE.exportActors([this.actor],
`${this.actor.uuid}-${this.actor.name}` `${this.actor.uuid}-${this.actor.name}`
) )
}) )
} }
} }

View File

@ -1,4 +1,4 @@
import { ACTOR_TYPES } from "../../item.js" import { ACTOR_TYPES } from "../../constants.js"
import { Misc } from "../../misc.js" import { Misc } from "../../misc.js"
import { EXPORT_CSV_SCRIPTARIUM, OptionsAvancees } from "../../settings/options-avancees.js" import { EXPORT_CSV_SCRIPTARIUM, OptionsAvancees } from "../../settings/options-avancees.js"
import { Mapping } from "./mapping.js" import { Mapping } from "./mapping.js"

View File

@ -2,7 +2,7 @@ import { Grammar } from "../../grammar.js"
import { RdDItemArme } from "../../item-arme.js" import { RdDItemArme } from "../../item-arme.js"
import { RdDItemCompetence } from "../../item-competence.js" import { RdDItemCompetence } from "../../item-competence.js"
import { RdDItemSort } from "../../item-sort.js" import { RdDItemSort } from "../../item-sort.js"
import { ITEM_TYPES } from "../../item.js" import { ITEM_TYPES } from "../../constants.js"
import { Misc } from "../../misc.js" import { Misc } from "../../misc.js"
import { RdDTimestamp } from "../../time/rdd-timestamp.js" import { RdDTimestamp } from "../../time/rdd-timestamp.js"
import { RdDBonus } from "../../rdd-bonus.js" import { RdDBonus } from "../../rdd-bonus.js"

View File

@ -7,7 +7,7 @@ export class RdDActorVehiculeSheet extends RdDBaseActorSheet {
/** @override */ /** @override */
static get defaultOptions() { static get defaultOptions() {
return foundry.utils.mergeObject(RdDBaseActorSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.hbs",
width: 640, height: 720, width: 640, height: 720,
}, { inplace: false }) }, { inplace: false })
} }
@ -32,18 +32,10 @@ export class RdDActorVehiculeSheet extends RdDBaseActorSheet {
super.activateListeners(html); super.activateListeners(html);
if (!this.options.editable) return; if (!this.options.editable) return;
this.html.find('.resistance-moins').click(async event => { this.html.find('.resistance-moins').click(async event => await this.actor.vehicleIncDec("resistance", -1))
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('.resistance-plus').click(async event => { this.html.find('.structure-plus').click(async event => await this.actor.vehicleIncDec("structure", 1))
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);
});
} }
} }

View File

@ -6,7 +6,7 @@ import { Grammar } from "../grammar.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js"; import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
import { RdDItemTete } from "../item/tete.js"; import { RdDItemTete } from "../item/tete.js";
import { ITEM_TYPES } from "../item.js"; import { ITEM_TYPES } from "../constants.js";
const WHITESPACES = "\\s+" const WHITESPACES = "\\s+"
const NUMERIC = "[\\+\\-]?\\d+" const NUMERIC = "[\\+\\-]?\\d+"

View File

@ -1,6 +1,6 @@
import "./xregexp-all.js"; import "./xregexp-all.js";
import { SystemCompendiums } from "../settings/system-compendiums.js"; import { SystemCompendiums } from "../settings/system-compendiums.js";
import { ACTOR_TYPES } from "../item.js"; import { ACTOR_TYPES } from "../constants.js";
import { TextRollAlchimie } from "./textroll/text-roll-alchimie.js"; import { TextRollAlchimie } from "./textroll/text-roll-alchimie.js";
import { TextRollCaracCompetence } from "./textroll/text-roll-carac-competence.js"; import { TextRollCaracCompetence } from "./textroll/text-roll-carac-competence.js";
import { TextRollFormula } from "./textroll/text-roll-formula.js"; import { TextRollFormula } from "./textroll/text-roll-formula.js";

View File

@ -1,5 +1,5 @@
import "../xregexp-all.js"; import "../xregexp-all.js";
import { ACTOR_TYPES, ITEM_TYPES } from "../../item.js"; import { ACTOR_TYPES, ITEM_TYPES } from "../../constants.js";
import { RdDCarac } from "../../rdd-carac.js"; import { RdDCarac } from "../../rdd-carac.js";
import { RdDUtility } from "../../rdd-utility.js"; import { RdDUtility } from "../../rdd-utility.js";
import { RdDAlchimie } from "../../rdd-alchimie.js"; import { RdDAlchimie } from "../../rdd-alchimie.js";

View File

@ -5,7 +5,7 @@ import { RdDUtility } from "../../rdd-utility.js";
import { TextRollManager } from "./text-roll-formatter.js"; import { TextRollManager } from "./text-roll-formatter.js";
const REGECP_CARAC = "(?<carac>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)" const REGECP_CARAC = "(?<carac>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)"
const REGEXP_COMP = "(\\/(?<competence>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+))?" const REGEXP_COMP = "(\\/(?<competence>[A-Za-zÀ-ÖØ-öø-ÿ ]+([1-2]?[A-Za-zÀ-ÖØ-öø-ÿ ]+)?))?"
const REGEXP_DIFF = "(/(?<diff>[\\+\\-]?\\d+(d\\d+)?))?" const REGEXP_DIFF = "(/(?<diff>[\\+\\-]?\\d+(d\\d+)?))?"
const REGEXP_ROLL_CARAC_COMP = REGECP_CARAC + REGEXP_COMP + REGEXP_DIFF const REGEXP_ROLL_CARAC_COMP = REGECP_CARAC + REGEXP_COMP + REGEXP_DIFF
const XREGEXP_ROLL_CARAC_COMP = XRegExp("@roll\\[" + REGEXP_ROLL_CARAC_COMP + "\\]", 'giu') const XREGEXP_ROLL_CARAC_COMP = XRegExp("@roll\\[" + REGEXP_ROLL_CARAC_COMP + "\\]", 'giu')

View File

@ -18,7 +18,7 @@ export class TextRollFormula {
async onRollText(event, actor) { async onRollText(event, actor) {
const node = TextRollManager.getNode(event) const node = TextRollManager.getNode(event)
const rollFormula = node.data('roll-formula') const rollFormula = node.data('formula')
if (rollFormula) { if (rollFormula) {
const roll = new Roll(rollFormula) const roll = new Roll(rollFormula)
await roll.evaluate() await roll.evaluate()

View File

@ -62,7 +62,6 @@ export class ChatUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static removeMessages(socketData) { static removeMessages(socketData) {
if (Misc.isFirstConnectedGM()) { if (Misc.isFirstConnectedGM()) {
ChatUtility.onRemoveMessages(socketData); ChatUtility.onRemoveMessages(socketData);
@ -97,7 +96,7 @@ export class ChatUtility {
} }
break break
case "gmroll": case "gmroll":
messageData.whisper = ChatUtility.getOwners(actor) messageData.whisper = actor ? ChatUtility.getOwners(actor) : ChatUtility.getUserAndGMs()
break break
case "selfroll": case "selfroll":
messageData.whisper = [game.user] messageData.whisper = [game.user]
@ -108,7 +107,7 @@ export class ChatUtility {
} }
static getOwners(document) { static getOwners(document) {
return game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) return document ? game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) : [game.user]
} }
static getUserAndGMs() { static getUserAndGMs() {
@ -199,7 +198,7 @@ export class ChatUtility {
static async onCreateChatMessage(chatMessage, options, id) { static async onCreateChatMessage(chatMessage, options, id) {
if (chatMessage.isAuthor) { if (chatMessage.isAuthor) {
await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp()); await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp());
await chatMessage.update({ content: await RdDTextEditor.enrichHTML(chatMessage.content, undefined, {showLink:false}) }) await chatMessage.update({ content: await RdDTextEditor.enrichHTML(chatMessage.content, undefined, { showLink: false }) })
} }
} }
} }

View File

@ -50,4 +50,59 @@ export const RDD_CONFIG = {
{value: "Rare", label: "Rare"}, {value: "Rare", label: "Rare"},
{value: "Rarissime", label: "Rarissime"} {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',
}

View File

@ -27,7 +27,7 @@ export class DialogChoixXpCarac extends Dialog {
dialogData = foundry.utils.mergeObject(dialogData, { dialogData = foundry.utils.mergeObject(dialogData, {
default: 'appliquer', default: 'appliquer',
buttons: { 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) super(dialogData, dialogOptions)
@ -37,18 +37,13 @@ export class DialogChoixXpCarac extends Dialog {
} }
activateListeners(html) { activateListeners(html) {
//TODO
super.activateListeners(html) super.activateListeners(html)
this.html = html this.html = html
this.html.find("li.xpCarac-option .xpCarac-moins").click(event => this.html.find("li.xpCarac-option .xpCarac-moins").click(event => this.ajouterXp(event, -1))
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-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 liCarac = this.html.find(event.currentTarget)?.parents("li.xpCarac-option")
const label = liCarac?.data("carac-label") const label = liCarac?.data("carac-label")
const carac = this.caracs.find(c => c.label == label) const carac = this.caracs.find(c => c.label == label)

View File

@ -27,7 +27,7 @@ export class DialogChronologie extends Dialog {
timestamp: game.system.rdd.calendrier.timestamp, timestamp: game.system.rdd.calendrier.timestamp,
dateReel: game.system.rdd.calendrier.dateReel() 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); const dialog = new DialogChronologie(html, dialogData);
dialog.render(true); dialog.render(true);
} }
@ -100,7 +100,7 @@ export class DialogChronologie extends Dialog {
} }
async prepareChronologieEntry(journalParameters) { 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() { extractJournalParameters() {

View File

@ -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) new DialogCreateSigneDraconique(dialogData, html)
.render(true); .render(true);
} }
@ -49,7 +49,7 @@ export class DialogCreateSigneDraconique extends Dialog {
actor.createEmbeddedDocuments("Item", [signe]); actor.createEmbeddedDocuments("Item", [signe]);
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getOwners(actor), 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, signe: signe,
alias: actor.getAlias() alias: actor.getAlias()
}) })

View File

@ -1,88 +1,79 @@
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
export class DialogFabriquerPotion extends Dialog { export class DialogFabriquerPotion extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async create(actor, item, onActionItem) { static async create(actor, item) {
const min = DialogFabriquerPotion.nombreBrinsMinimum(item); const brinsMinimum = DialogFabriquerPotion.nombreBrinsMinimum(item)
if (item.system.quantite < min) { if (item.system.quantite < brinsMinimum) {
ui.notifications.warn(`Vous avez ${item.system.quantite} brins de ${item.name}, il en faut au moins ${min} pour faire une potion!`); ui.notifications.warn(`Vous avez ${item.system.quantite} brins de ${item.name}, il en faut au moins ${brinsMinimum} pour faire une potion!`)
return; 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); new DialogFabriquerPotion(actor, potionData, html, options).render(true)
let options = { classes: ["dialogfabriquerpotion"], width: 600, height: 160, 'z-index': 99999 };
new DialogFabriquerPotion(actor, potionData, onActionItem, html, options).render(true);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static prepareData(actor, item) { static prepareData(item, brinsMinimum) {
let potionData = foundry.utils.duplicate(item) const brinsOptimal = DialogFabriquerPotion.nombreBrinsOptimal(item)
potionData.nbBrinsSelect = RdDUtility.buildListOptions( return foundry.utils.mergeObject(foundry.utils.duplicate(item), {
DialogFabriquerPotion.nombreBrinsMinimum(item), nbBrinsSelect: RdDUtility.buildListOptions(brinsMinimum, brinsOptimal),
DialogFabriquerPotion.nombreBrinsOptimal(item)); nbBrins: Math.min(item.system.quantite, brinsOptimal),
potionData.nbBrins = Math.min(potionData.system.quantite, DialogFabriquerPotion.nombreBrinsOptimal(potionData)); herbebonus: item.system.niveau
potionData.herbebonus = item.system.niveau; })
potionData.buttonName = "Fabriquer";
return potionData;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
constructor(actor, potionData, onActionItem, html, options) { constructor(actor, potionData, html, options) {
const conf = { const conf = {
title: `Fabriquer une potion de ${potionData.system.categorie}`, title: `Fabriquer une potion de ${potionData.system.categorie}`,
content: html, content: html,
default: 'fabriquer', default: 'fabriquer',
buttons: { buttons: {
'fabriquer': { 'fabriquer': { label: "Fabriquer", callback: it => this.onFabriquer() }
label: potionData.buttonName, callback: it => this.onFabriquer()
}
} }
}; }
super(conf, options)
super(conf, options); this.actor = actor
this.potionData = potionData
this.actor = actor;
this.potionData = potionData;
this.onActionItem = onActionItem;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html)
this.html = html; this.html = html
this.html.find("[name='nbBrins']").change(event => { this.html.find("[name='nbBrins']").change(event => {
this.potionData.nbBrins = Misc.toInt(event.currentTarget.value); this.potionData.nbBrins = Misc.toInt(event.currentTarget.value)
const brinsManquants = Math.max(0, DialogFabriquerPotion.nombreBrinsOptimal(this.potionData) - this.potionData.nbBrins); const brinsManquants = Math.max(0, DialogFabriquerPotion.nombreBrinsOptimal(this.potionData) - this.potionData.nbBrins)
this.potionData.herbebonus = Math.max(0, this.potionData.system.niveau - brinsManquants) this.potionData.herbebonus = Math.max(0, this.potionData.system.niveau - brinsManquants)
}); })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async onFabriquer() { async onFabriquer() {
await this.html.find("[name='nbBrins']").change(); await this.html.find("[name='nbBrins']").change()
await this.actor.fabriquerPotion(this.potionData); await this.actor.fabriquerPotion(this.potionData)
this.close(); this.close()
await this.onActionItem()
} }
static nombreBrinsMinimum(herbeData) { static nombreBrinsMinimum(herbeData) {
switch (herbeData.system.categorie ?? '') { switch (herbeData.system.categorie ?? '') {
case "Soin": return 1 + Math.max(0, 12 - 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); case "Repos": return 1 + Math.max(0, 7 - 2 * herbeData.system.niveau)
} }
return 1; return 1
} }
static nombreBrinsOptimal(herbeData) { static nombreBrinsOptimal(herbeData) {
switch (herbeData.system.categorie ?? '') { switch (herbeData.system.categorie ?? '') {
case "Soin": return 12 - herbeData.system.niveau; case "Soin": return 12 - herbeData.system.niveau
case "Repos": return 7 - herbeData.system.niveau; case "Repos": return 7 - herbeData.system.niveau
} }
return 1; return 1
} }
} }

View File

@ -2,13 +2,13 @@ import { Misc } from "./misc.js";
export class DialogConsommer extends Dialog { export class DialogConsommer extends Dialog {
static async create(actor, item, onActionItem = async () => { }) { static async create(actor, item) {
const consommerData = DialogConsommer.prepareData(actor, item); const consommerData = DialogConsommer.prepareData(actor, item);
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-item-consommer.html', consommerData); const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-item-consommer.hbs', consommerData);
return new DialogConsommer(actor, item, consommerData, html, onActionItem) 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 }; const options = { classes: ["dialogconsommer"], width: 350, height: 'fit-content', 'z-index': 99999 };
let conf = { let conf = {
title: consommerData.title, title: consommerData.title,
@ -16,10 +16,7 @@ export class DialogConsommer extends Dialog {
default: consommerData.buttonName, default: consommerData.buttonName,
buttons: { buttons: {
[consommerData.buttonName]: { [consommerData.buttonName]: {
label: consommerData.buttonName, callback: async it => { label: consommerData.buttonName, callback: async it => await this.onConsommer()
await this.onConsommer();
await onActionItem();
}
} }
} }
}; };

View File

@ -3,7 +3,7 @@ export class DialogSelect extends Dialog {
static extractIdNameImg(it) { return { id: it.id, name: it.name, img: it.img } } static extractIdNameImg(it) { return { id: it.id, name: it.name, img: it.img } }
static async select(selectionData, onSelectChoice) { 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 = { const dialogData = {
title: selectionData.title ?? selectionData.label, title: selectionData.title ?? selectionData.label,

View File

@ -7,7 +7,7 @@ export class DialogSplitItem extends Dialog {
item: item, item: item,
choix: { quantite: 1, max: item.system.quantite - 1 } 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) return new DialogSplitItem(item, splitData, html, callback)
} }

View File

@ -9,7 +9,7 @@ export class DialogValidationEncaissement extends Dialog {
static async validerEncaissement(actor, rollData, armure, onEncaisser) { static async validerEncaissement(actor, rollData, armure, onEncaisser) {
const encaissement = await RdDUtility.jetEncaissement(actor, rollData, armure, { showDice: HIDE_DICE }); 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, actor: actor,
rollData: rollData, rollData: rollData,
encaissement: encaissement encaissement: encaissement

View 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))
}
}
}
}
}

View File

@ -1,6 +1,6 @@
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.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 { BASE_CORPS_A_CORPS } from "./item/base-items.js";
import { RdDCombatManager } from "./rdd-combat.js"; import { RdDCombatManager } from "./rdd-combat.js";
@ -123,10 +123,10 @@ export class RdDItemArme extends Item {
if (defCategory == 'bouclier') { if (defCategory == 'bouclier') {
return 'norm' return 'norm'
} }
if (armeAttaque.system.competence.toLowerCase().match(/(fléau)/)) { if (armeAttaque?.system?.competence?.toLowerCase().match(/(fléau)/)) {
return '' return ''
} }
if (armeParade.system.tir) { if (armeParade.system?.tir) {
return '' return ''
} }
const attCategory = RdDItemArme.getCategorieParade(armeAttaque) const attCategory = RdDItemArme.getCategorieParade(armeAttaque)

View File

@ -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"; import { RdDCombatManager } from "./rdd-combat.js";
export const CATEGORIES_COMPETENCES_CREATURES = { export const CATEGORIES_COMPETENCES_CREATURES = {
@ -17,9 +18,11 @@ export class RdDItemCompetenceCreature extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static setRollDataCreature(rollData) { static setRollDataCreature(rollData) {
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } } const code = Grammar.toLowerCaseNoAccentNoSpace(rollData.competence.name);
rollData.competence.system.defaut_carac = "carac_creature" const selectedCarac = { code: code, label: rollData.competence.name, value: rollData.competence.system.carac_value };
rollData.selectedCarac = rollData.carac.carac_creature rollData.carac = { [code]: selectedCarac }
rollData.competence.system.defaut_carac = code
rollData.selectedCarac = selectedCarac
rollData.arme = RdDItemCompetenceCreature.armeCreature(rollData.competence); rollData.arme = RdDItemCompetenceCreature.armeCreature(rollData.competence);
} }
@ -29,20 +32,20 @@ export class RdDItemCompetenceCreature extends Item {
if (categorieAttaque != undefined) { if (categorieAttaque != undefined) {
// cloner pour ne pas modifier la compétence // cloner pour ne pas modifier la compétence
return foundry.utils.mergeObject(item, { return foundry.utils.mergeObject(item, {
action: item.isCompetencePossession() ? 'possession' : 'attaque', action: item.isCompetencePossession() ? 'possession' : 'attaque',
system: { system: {
competence: item.name, competence: item.name,
cac: categorieAttaque == "naturelle" ? "naturelle" : "", cac: categorieAttaque == "naturelle" ? "naturelle" : "",
niveau: item.system.niveau, niveau: item.system.niveau,
initiative: RdDCombatManager.calculInitiative(item.system.niveau, item.system.carac_value), initiative: RdDCombatManager.calculInitiative(item.system.niveau, item.system.carac_value),
equipe: true, equipe: true,
resistance: 100, resistance: 100,
dommagesReels: item.system.dommages, dommagesReels: item.system.dommages,
penetration: 0, penetration: 0,
force: 0, force: 0,
rapide: true, rapide: true,
} }
}, { inplace: false, }); }, { inplace: false, });
} }
return undefined; return undefined;
} }

View File

@ -1,5 +1,5 @@
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { LOG_HEAD } from "./constants.js"; import { ITEM_TYPES, LOG_HEAD } from "./constants.js";
const MONNAIE_ETAIN = { const MONNAIE_ETAIN = {
name: "Denier (étain)", type: 'monnaie', name: "Denier (étain)", type: 'monnaie',
@ -70,18 +70,17 @@ export class Monnaie {
} }
static getFortune(monnaies) { static getFortune(monnaies) {
return (monnaies??[]) return (monnaies ?? [])
.map(m => Number(m.system.cout) * Number(m.system.quantite)) .map(m => Number(m.system.cout) * Number(m.system.quantite))
.reduce(Misc.sum(), 0); .reduce(Misc.sum(), 0);
} }
static async optimiserFortune(actor, fortune) { static async optimiserFortune(actor, fortune) {
Monnaie.validerMonnaies(actor)
let resteEnDeniers = Math.round(fortune * 100); let resteEnDeniers = Math.round(fortune * 100);
let monnaies = actor.itemTypes['monnaie']; const updates = []
let updates = [];
Monnaie.validerMonnaies(monnaies, actor);
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]) { for (let valeurDeniers of [1000, 100, 10, 1]) {
const itemPiece = parValeur[valeurDeniers]; const itemPiece = parValeur[valeurDeniers];
if (itemPiece) { if (itemPiece) {
@ -102,8 +101,11 @@ export class Monnaie {
} }
} }
static validerMonnaies(monnaies, actor = undefined) { static validerMonnaies(actor) {
monnaies.filter(it => VALEUR_DENIERS(it.system.cout) == 0) 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!`) .map(it => `La monnaie ${it.name} de l'acteur ${actor?.name ?? 'sélectionné'} a une valeur de 0!`)
.forEach(message => { .forEach(message => {
ui.notifications.warn(message); ui.notifications.warn(message);

View File

@ -1,8 +1,7 @@
import { ACTOR_TYPES, ITEM_TYPES } from "./constants.js";
import { RdDItemSort } from "./item-sort.js"; import { RdDItemSort } from "./item-sort.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
import { RdDItemCompetence } from "./item-competence.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 { HtmlUtility } from "./html-utility.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { SYSTEM_RDD } from "./constants.js"; import { SYSTEM_RDD } from "./constants.js";
@ -11,9 +10,11 @@ import { SystemCompendiums } from "./settings/system-compendiums.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { ACTOR_TYPES, ITEM_TYPES, RdDItem } from "./item.js"; import { RdDItem } from "./item.js";
import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js"; import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js";
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.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 * Extend the basic ItemSheet for RdD specific items
@ -26,8 +27,8 @@ export class RdDItemSheet extends ItemSheet {
static defaultTemplate(type) { static defaultTemplate(type) {
return type ? return type ?
`systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html` : `systems/foundryvtt-reve-de-dragon/templates/item/${type}-sheet.hbs` :
"systems/foundryvtt-reve-de-dragon/templates/item-sheet.html"; "systems/foundryvtt-reve-de-dragon/templates/item/item-sheet.hbs";
} }
static register(sheetClass) { static register(sheetClass) {
@ -132,13 +133,7 @@ export class RdDItemSheet extends ItemSheet {
formData.enchantement = await RdDTextEditor.enrichHTML(this.item.system.enchantement, this.item) formData.enchantement = await RdDTextEditor.enrichHTML(this.item.system.enchantement, this.item)
formData.sureffet = await RdDTextEditor.enrichHTML(this.item.system.sureffet, this.item) formData.sureffet = await RdDTextEditor.enrichHTML(this.item.system.sureffet, this.item)
} }
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)
}
if (this.item.type == ITEM_TYPES.herbe) { if (this.item.type == ITEM_TYPES.herbe) {
if (formData.options.isOwned && ['Soin', 'Repos'].includes(formData.system.categorie)) { if (formData.options.isOwned && ['Soin', 'Repos'].includes(formData.system.categorie)) {
formData.isIngredientPotionBase = true; formData.isIngredientPotionBase = true;
@ -164,23 +159,19 @@ export class RdDItemSheet extends ItemSheet {
HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionnelles.isUsing('afficher-prix-joueurs') HtmlUtility.showControlWhen(this.html.find(".item-cout"), ReglesOptionnelles.isUsing('afficher-prix-joueurs')
|| game.user.isGM || game.user.isGM
|| !this.item.isOwned); || !this.item.isOwned)
HtmlUtility.showControlWhen(this.html.find(".item-magique"), this.item.isMagique()); HtmlUtility.showControlWhen(this.html.find(".item-magique"), this.item.isMagique)
// Everything below here is only needed if the sheet is editable // 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.ondragstart = async event => await this._onDragStart(event)
this.form.ondrop = (event) => this._onDrop(event); this.form.ondrop = async event => await this._onDrop(event)
// Select competence categorie // 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) => { this.html.find('.sheet-competence-xp').change(event => RdDUtility.checkThanatosXP(this.item))
if (this.item.isCompetencePersonnage()) {
RdDUtility.checkThanatosXP(this.item.name);
}
});
this.html.find(".item-cout input[name='system.cout']").change(event => { this.html.find(".item-cout input[name='system.cout']").change(event => {
if (this.item.isMonnaie()) { if (this.item.isMonnaie()) {
const value = event.currentTarget.value; const value = event.currentTarget.value;
@ -189,66 +180,60 @@ export class RdDItemSheet extends ItemSheet {
} }
} }
}) })
this.html.find('.delete-bonus-case').click((event) => { this.html.find('.delete-bonus-case').click(async event => await this.supprimerBonusCase(event.currentTarget.attributes['data-deleteCoord'].value))
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 =>
this.html.find('.date-enchantement').change((event) => { await this.item.update({ 'system.cacher_points_de_tache': event.currentTarget.checked })
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('.roll-text').click(async event => await RdDTextEditor.rollText(event, this.actor)) 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)) this.html.find('.chat-roll-text').click(async event => await RdDTextEditor.chatRollText(event))
if (this.actor) { 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('.actionItem').click(async event => await ItemAction.onActionItem(event, this.actor, this.options))
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))); // TODO: utiliser un itemAction?
this.html.find('.item-vendre').click(async event => RdDSheetUtility.getItem(event, this.actor)?.proposerVente()); this.html.find('.item-potion-consommer').click(async event => await this.itemActionConsommer(event))
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('.item-quantite-plus').click(async event => { this.html.find('.item-quantite-plus').click(async event => {
await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), 1) await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), 1)
this.render(); //this.render()
}); })
this.html.find('.item-quantite-moins').click(async event => { this.html.find('.item-quantite-moins').click(async event => {
await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), -1) await this.actor.itemQuantiteIncDec(RdDSheetUtility.getItemId(event), -1)
this.render(); //this.render()
}); })
} }
const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: foundry.utils.duplicate(timestamp) }) const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: foundry.utils.duplicate(timestamp) })
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.debut', updateItemTimestamp); RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.debut', updateItemTimestamp)
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp); RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp)
} }
getActionRenderItem() { async itemActionDelete(event) {
return async () => { const item = RdDSheetUtility.getItem(event, this.actor)
let item = this.item; return await RdDUtility.confirmActorItemDelete(item, this.actor)
while (item) { }
await item.sheet?.render()
item = this.actor.getContenant(item) async itemActionConsommer(event) {
} const item = RdDSheetUtility.getItem(event, this.actor)
if (item) {
await actor.consommerPotion(item)
await RdDSheetUtility.renderItemBranch(this.actor, item)
} }
} }
_getEventActor(event) { async itemActionSplit(event) {
let actorId = event.currentTarget.attributes['data-actor-id'].value; const item = RdDSheetUtility.getItem(event, this.actor)
let actor = game.actors.get(actorId); if (item) {
return actor; 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) { async _onSelectCategorie(event) {
@ -290,7 +275,7 @@ export class RdDItemSheet extends ItemSheet {
break break
} }
return this.item.update(formData); return this.item.update(formData)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -323,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) { async _onDrop(event) {
// Try to extract the dragData // Try to extract the dragData
@ -350,13 +336,7 @@ export class RdDItemSheet extends ItemSheet {
return JSON.parse(eventData); return JSON.parse(eventData);
} }
} catch (err) { } } catch (err) { }
return undefined; return undefined
}
async _onDropItem(event, dragData) {
}
async _onDropActor(event, dragData) {
} }
} }

View File

@ -1,6 +1,6 @@
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { RdDItemCompetence } from "./item-competence.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 { Misc } from "./misc.js";
import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js"; import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js";
@ -22,7 +22,21 @@ export class RdDItemSort extends Item {
} }
static addSpaceToNonNumeric(value) { 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) { static toVar(value) {
@ -42,6 +56,10 @@ export class RdDItemSort extends Item {
return voies.map(voie => RdDItemCompetence.getVoieDraconic(competencesDraconic, voie)) return voies.map(voie => RdDItemCompetence.getVoieDraconic(competencesDraconic, voie))
} }
static getBestDraconicSort(competencesDraconic, sort) {
return RdDItemSort.getDraconicsSort(competencesDraconic, sort).sort(Misc.descending(it => it.system.niveau)).find(it=>true)
}
static getOrdreCode(code) { static getOrdreCode(code) {
return (VOIES_DRACONIC.find(it => it.code == code)?.ordre ?? '?') return (VOIES_DRACONIC.find(it => it.code == code)?.ordre ?? '?')
} }
@ -78,7 +96,7 @@ export class RdDItemSort extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isCoutVariable(sort) { static isCoutVariable(sort) {
return sort && (sort.system.ptreve.toLowerCase() == "variable" || sort.system.ptreve.indexOf("+") >= 0); return sort && !Number.isInteger(sort.system.ptreve) && (sort.system.ptreve.toLowerCase() == "variable" || sort.system.ptreve.indexOf("+") >= 0);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -151,5 +169,4 @@ export class RdDItemSort extends Item {
.map(it => it.split(':')) .map(it => it.split(':'))
.map(it => { return { case: it[0], bonus: it[1] } }); .map(it => { return { case: it[0], bonus: it[1] } });
} }
} }

View File

@ -1,7 +1,7 @@
import { ITEM_TYPES } from "./constants.js";
import { DialogItemVente } from "./achat-vente/dialog-item-vente.js"; import { DialogItemVente } from "./achat-vente/dialog-item-vente.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDHerbes } from "./rdd-herbes.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
import { SystemCompendiums } from "./settings/system-compendiums.js"; import { SystemCompendiums } from "./settings/system-compendiums.js";
@ -9,61 +9,7 @@ import { RdDRaretes } from "./item/raretes.js";
import { CATEGORIES_COMPETENCES } from "./item-competence.js"; import { CATEGORIES_COMPETENCES } from "./item-competence.js";
import { CATEGORIES_COMPETENCES_CREATURES } from "./item-competencecreature.js"; import { CATEGORIES_COMPETENCES_CREATURES } from "./item-competencecreature.js";
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE } from "./item/base-items.js"; import { BASE_CORPS_A_CORPS, BASE_ESQUIVE } from "./item/base-items.js";
import { ITEM_ACTIONS, DEFAULT_ACTIONS, COMMON_ACTIONS } from "./item/item-actions.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',
}
const typesInventaireMateriel = [ const typesInventaireMateriel = [
ITEM_TYPES.arme, 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 typesObjetsEquipable = [ITEM_TYPES.arme, ITEM_TYPES.armure, ITEM_TYPES.objet];
const typesEnvironnement = typesInventaireMateriel; const typesEnvironnement = typesInventaireMateriel;
const encBrin = 0.00005; // un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc 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 = { 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", arme: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.webp",
armure: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.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", 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", 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", jeu: "systems/foundryvtt-reve-de-dragon/icons/arts/jeux_petasse.webp",
recettecuisine: "systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_1.webp", livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp",
musique: "systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp",
maladie: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/maladie.webp", maladie: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/maladie.webp",
poison: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp", meditation: "systems/foundryvtt-reve-de-dragon/icons/meditations_ecrits/meditation_alchimie.webp",
oeuvre: "systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp", musique: "systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp",
nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.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", service: "systems/foundryvtt-reve-de-dragon/icons/services/lit.webp",
signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp", signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp",
gemme: "systems/foundryvtt-reve-de-dragon/icons/gemmes/almaze.webp", sort: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
possession: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
sortreserve: "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", 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 { export class RdDItem extends Item {
static get defaultIcon() { static get defaultIcon() {
return undefined; return undefined;
} }
@ -238,7 +180,6 @@ export class RdDItem extends Item {
isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature } isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature }
isConteneur() { return this.type == ITEM_TYPES.conteneur; } isConteneur() { return this.type == ITEM_TYPES.conteneur; }
isMonnaie() { return this.type == ITEM_TYPES.monnaie; } isMonnaie() { return this.type == ITEM_TYPES.monnaie; }
isPotion() { return this.type == ITEM_TYPES.potion; }
isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; } isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; }
isService() { return this.type == ITEM_TYPES.service; } isService() { return this.type == ITEM_TYPES.service; }
@ -277,6 +218,12 @@ export class RdDItem extends Item {
return this.getEnvironnements(milieux).length > 0 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) { getEnvironnements(milieux = undefined) {
const environnements = this.isInventaire() ? this.system.environnement : undefined; const environnements = this.isInventaire() ? this.system.environnement : undefined;
if (milieux == undefined || !environnements) { if (milieux == undefined || !environnements) {
@ -356,13 +303,6 @@ export class RdDItem extends Item {
getUtilisation() { getUtilisation() {
switch (this.type) { 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.nourritureboisson: return 'cuisine';
case ITEM_TYPES.herbe: case ITEM_TYPES.faune: case ITEM_TYPES.ingredient: case ITEM_TYPES.plante: case ITEM_TYPES.herbe: case ITEM_TYPES.faune: case ITEM_TYPES.ingredient: case ITEM_TYPES.plante:
switch (this.system.categorie) { 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; return this.type == ITEM_TYPES.objet && Grammar.includesLowerCaseNoAccent(this.name, 'cristal alchimique') && this.system.quantite > 0;
} }
isMagique() { get isMagique() {
return this.system.magique return this.system.magique
} }
@ -403,6 +343,7 @@ export class RdDItem extends Item {
isNomLike(texte) { isNomLike(texte) {
return Grammar.includesLowerCaseNoAccent(this.name, texte) return Grammar.includesLowerCaseNoAccent(this.name, texte)
} }
isNomTypeLike(texte) { isNomTypeLike(texte) {
return this.isNomLike(texte) || Grammar.includesLowerCaseNoAccent(Misc.typeName(this.type, 'Item'), texte) return this.isNomLike(texte) || Grammar.includesLowerCaseNoAccent(Misc.typeName(this.type, 'Item'), texte)
} }
@ -421,8 +362,6 @@ export class RdDItem extends Item {
return 0; return 0;
case ITEM_TYPES.herbe: case ITEM_TYPES.herbe:
return this.getEncHerbe(); return this.getEncHerbe();
case ITEM_TYPES.gemme:
return encPepin * this.system.taille;
} }
return Math.max(this.system.encombrement ?? 0, 0); return Math.max(this.system.encombrement ?? 0, 0);
} }
@ -471,68 +410,47 @@ export class RdDItem extends Item {
// appliquer le pourcentage // appliquer le pourcentage
return this.parent.calculerPrix(this); return this.parent.calculerPrix(this);
} }
return this.system.cout; return this.system.cout
} }
prepareDerivedData() { prepareDerivedData() {
super.prepareDerivedData(); super.prepareDerivedData();
if (this.isInventaire()) { if (this.isInventaire()) {
this.system.encTotal = this.getEncTotal(); this.system.encTotal = this.getEncTotal()
if (this.isPotion()) {
this.prepareDataPotion()
}
this.system.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
} }
this.equipable = this.isEquipable(); this.equipable = this.isEquipable()
} }
prepareDataPotion() { itemActions() {
const categorie = Grammar.toLowerCaseNoAccent(this.system.categorie); return COMMON_ACTIONS.concat(this.itemSpecificActions()).concat(DEFAULT_ACTIONS)
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);
}
}
} }
getActionPrincipale(options = { warnIfNot: true }) { itemSpecificActions() {
const actions = ITEM_ACTIONS[this.type] ?? []
return actions
}
isActionAllowed(code) {
switch (this.type) { switch (this.type) {
case ITEM_TYPES.conteneur: return 'Ouvrir'; case ITEM_TYPES.possession:
} case ITEM_TYPES.empoignade:
if (this.actor?.isPersonnage()) { case ITEM_TYPES.rencontre:
const warn = options.warnIfNot; case ITEM_TYPES.signedraconique:
if (this.getUtilisationCuisine() == 'brut') { switch (code) {
return 'Cuisiner'; case 'item-edit':
} case 'item-delete':
switch (this.type) { return game.user.isGM
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.maladie:
case ITEM_TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn); case ITEM_TYPES.poison:
case ITEM_TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined; return game.user.isGM
case ITEM_TYPES.queue: case ITEM_TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined; case ITEM_TYPES.casetmr:
} switch (code) {
} case 'item-delete':
return undefined; return game.user.isGM
} }
/* -------------------------------------------- */
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;
} }
return true
} }
async diminuerQuantite(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) { async diminuerQuantite(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
@ -673,7 +591,7 @@ export class RdDItem extends Item {
} }
getChatItemTemplate() { 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) { 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() { _queueChatData() {
function label(categorie) { function label(categorie) {
switch (categorie) { switch (categorie) {

View File

@ -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 { Misc } from "../misc.js";
import { ReglesOptionnelles } from "../settings/regles-optionnelles.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"; 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') { if (!ReglesOptionnelles.isUsing('deteriorationArmure') || this.system.protection == '0') {
return; return;
} }
@ -22,12 +23,10 @@ export class RdDItemArmure extends RdDItem {
protection = this.calculProtectionDeterioree(); protection = this.calculProtectionDeterioree();
ChatMessage.create({ content: `Votre armure ${this.name} s'est détériorée, elle protège maintenant de ${protection}` }); ChatMessage.create({ content: `Votre armure ${this.name} s'est détériorée, elle protège maintenant de ${protection}` });
} }
this.update({ await this.update({
system: { 'system.deterioration': deterioration,
deterioration: deterioration, 'system.protection': protection
protection: protection })
}
});
} }
calculProtectionDeterioree() { calculProtectionDeterioree() {

View File

@ -30,7 +30,7 @@ export class RdDItemBlessure extends RdDItem {
prepareDerivedData() { prepareDerivedData() {
super.prepareDerivedData(); super.prepareDerivedData();
this.system.label = this.getLabelGravite() this.system.label = RdDItemBlessure.getLabelGravite(this.system.gravite)
} }
static prepareTacheSoin(gravite) { static prepareTacheSoin(gravite) {
@ -43,29 +43,32 @@ export class RdDItemBlessure extends RdDItem {
} }
static async applyFullBlessure(actor, gravite) { static async applyFullBlessure(actor, gravite) {
const definition = RdDItemBlessure.getDefinition(gravite) const definition = foundry.utils.duplicate(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));
}
if (definition.vie) { if (definition.vie) {
lostVie = definition.vie await actor.santeIncDec("vie", definition.vie)
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) await this.createBlessure(actor, gravite)
ChatMessage.create({ ChatMessage.create({
content: `Blessure ${definition.label} appliquée à ${actor.name}`+ //TODO: hbs
`<br>Perte d'endurance : ${lostEndurance}`+ content: `Blessure ${definition.label} appliquée à ${actor.name}<br>Perte d'endurance : ${lostEndurance} (${definition.endurance})<br>Perte de Vie : ${definition.vie}`,
`<br>Perte de Vie : ${lostVie}`,
whisper: ChatUtility.getOwners(actor) 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) { static async createBlessure(actor, gravite, localisation = '', attackerToken) {
@ -125,10 +128,10 @@ export class RdDItemBlessure extends RdDItem {
} }
if (this.system.gravite > 0) { if (this.system.gravite > 0) {
const update = { system: { premierssoins: { bonus: 0 }, soinscomplets: { bonus: 0 } } } const update = { system: { premierssoins: { bonus: 0 }, soinscomplets: { bonus: 0 } } }
const gravite = this.system.gravite; const gravite = this.system.gravite
const graviteMoindre = gravite - 2; const graviteMoindre = gravite - 2
const moindres = blessures.filter(it => it.system.gravite == graviteMoindre, 'blessures').length 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); let rolled = await actor.jetRecuperationConstitution(this.system.soinscomplets.bonus, message);
@ -158,11 +161,11 @@ export class RdDItemBlessure extends RdDItem {
} }
peutRetrograder(graviteMoindre, moindres) { peutRetrograder(graviteMoindre, moindres) {
return moindres < RdDItemBlessure.getDefinition(graviteMoindre).max return moindres < RdDItemBlessure.maxBlessures(graviteMoindre)
} }
async calculerFinPeriodeTemporel(debut) { async calculerFinPeriodeTemporel(debut) {
return await debut.nouveauJour().addJours(this.system.gravite); return debut.nouveauJour().addJours(this.system.gravite);
} }
async onFinPeriode(oldTimestamp, newTimestamp) { 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` return `systems/foundryvtt-reve-de-dragon/icons/sante/${soins ? 'blessure-soins' : img}.webp`
} }
getLabelGravite() { static getLabelGravite(gravite) {
return RdDItemBlessure.getDefinition(this.system.gravite).label return definitionsBlessures.find(it => it.gravite >= gravite).label
} }
static getDefinition(gravite) { static getDefinition(gravite) {
return definitionsBlessures.sort(Misc.ascending(it => it.gravite)) return definitionsBlessures.find(it => it.gravite >= gravite)
.find(it => it.gravite >= gravite);
} }
static maxBlessures(gravite) { static maxBlessures(gravite) {
return RdDItemBlessure.getDefinition(gravite).max return definitionsBlessures.find(it => it.gravite >= gravite).max
} }
isContusion() { isContusion() {
@ -216,7 +219,7 @@ export class RdDItemBlessure extends RdDItem {
`<b>Heure et Date</b>: ${new RdDTimestamp(this.system.temporel.debut).formatDateHeure()}`, `<b>Heure et Date</b>: ${new RdDTimestamp(this.system.temporel.debut).formatDateHeure()}`,
RdDItem.propertyIfDefined('Blessé', this.parent?.name, this.parent), RdDItem.propertyIfDefined('Blessé', this.parent?.name, this.parent),
`<b>Localisation</b>: ${this.system.localisation}`, `<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}`, `<b>Difficulté des soins</b>: ${this.system.difficulte}`,
(this.system.soinscomplets.done ? (this.system.soinscomplets.done ?
`<b>Bonus soins complets</b>: ${this.system.soinscomplets.bonus}` : `<b>Bonus soins complets</b>: ${this.system.soinscomplets.bonus}` :

112
module/item/gemme.js Normal file
View 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
View 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)
}
}
}

View File

@ -10,7 +10,7 @@ export class RdDItemMaladie extends RdDItem {
} }
async calculerFinPeriodeTemporel(debut) { 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) { async onFinPeriode(oldTimestamp, newTimestamp) {

View File

@ -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() { static get defaultIcon() {
return "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp"; return "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp";
} }
async calculerFinPeriodeTemporel(debut) {
return await debut.appliquerDuree(this.system.duree, this.parent);
}
} }

View File

@ -8,7 +8,7 @@ export class RdDItemPoison extends RdDItem {
} }
async calculerFinPeriodeTemporel(debut) { 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) { async onFinPeriode(oldTimestamp, newTimestamp) {

105
module/item/potion.js Normal file
View 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;
}
}

View File

@ -6,8 +6,9 @@ export class RdDItemQueue extends RdDItem {
return "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp"; 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); return await debut.appliquerDuree(this.system.duree, this.parent);
} }
} }

View File

@ -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 { Misc } from "../misc.js";
import { LIST_CARAC_PERSONNAGE, RdDCarac } from "../rdd-carac.js"; import { LIST_CARAC_PERSONNAGE, RdDCarac } from "../rdd-carac.js";
@ -18,10 +19,12 @@ export class RdDItemRace extends RdDItem {
return false return false
} }
} }
const carac = RdDCarac.carac(code) if (code == LIST_CARAC_PERSONNAGE.taille.code) {
if (race.isMax(actor, code, value - 1)) { const carac = RdDCarac.carac(code)
ui.notifications.warn(`${value} est supérieure au maximum de ${carac.label}`) if (race.isMax(actor, code, value - 1)) {
return false ui.notifications.warn(`${value} est supérieure au maximum de ${carac.label}`)
return false
}
} }
return true return true
} }
@ -58,7 +61,8 @@ export class RdDItemRace extends RdDItem {
if (code == LIST_CARAC_PERSONNAGE.force.code) { if (code == LIST_CARAC_PERSONNAGE.force.code) {
return value >= this.getForceMax(actor) return value >= this.getForceMax(actor)
} }
const max = foundry.utils.getProperty(this, path) ?? -1 const pathMax = path.replace(".value", ".max");
const max = foundry.utils.getProperty(this, pathMax) ?? -1
return (max > 0 && value >= max) return (max > 0 && value >= max)
} }

View File

@ -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_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_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_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_COMMUNE,
RARETE_FREQUENTE, RARETE_FREQUENTE,
RARETE_RARE, RARETE_RARE,

View File

@ -74,7 +74,7 @@ export class RdDRencontre extends RdDItem {
} }
async calculerFinPeriodeTemporel(debut) { async calculerFinPeriodeTemporel(debut) {
return await debut.nouvelleHeure().addHeures(12); return debut.nouvelleHeure().addHeures(12);
} }
} }

View File

@ -34,8 +34,8 @@ export class RdDItemInventaireSheet extends RdDItemSheet {
HtmlUtility.showControlWhen(this.html.find("div.description-milieu"), TYPE_ITEMS_NATURELS.includes(this.item.type)); HtmlUtility.showControlWhen(this.html.find("div.description-milieu"), TYPE_ITEMS_NATURELS.includes(this.item.type));
if (!this.options.editable) return; if (!this.options.editable) return;
this.html.find("a.preparer-nourriture").click(event => this.preparerNourriture(event)); this.html.find("a.preparer-nourriture").click(async event => await this.preparerNourriture(event));
this.html.find("a.manger-nourriture").click(event => this.mangerNourriture(event)); this.html.find("a.manger-nourriture").click(async event => await this.mangerNourriture(event));
this.html.find("input.input-selection-milieu").keypress(event => { this.html.find("input.input-selection-milieu").keypress(event => {
if (event.keyCode == '13') { if (event.keyCode == '13') {
@ -43,11 +43,11 @@ export class RdDItemInventaireSheet extends RdDItemSheet {
} }
event.stopPropagation(); event.stopPropagation();
}) })
this.html.find("a.milieu-add").click(event => this.onAddMilieu(event)); this.html.find("a.milieu-add").click(async event => await this.onAddMilieu(event));
this.html.find("div.environnement-milieu a.milieu-delete").click(event => this.onDeleteMilieu(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(event => this.onChange(event, this.html.find("div.environnement-milieu select.environnement-rarete").change(async event => await this.onChange(event,
updated => this.$changeRarete(event, updated))); 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))); updated => this.$changeFrequence(event, updated)));

View File

@ -15,15 +15,15 @@ export class RdDBlessureItemSheet extends RdDItemSheet {
if (!this.options.editable) return; if (!this.options.editable) return;
this.html.find('[name="premierssoins-done"]').change(async event => { this.html.find('[name="premierssoins-done"]').change(async event =>
await this.item.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } }); await this.item.setSoinsBlessure({ premierssoins: { done: event.currentTarget.checked } })
}); )
this.html.find('[name="soinscomplets-done"]').change(async event => { this.html.find('[name="soinscomplets-done"]').change(async event =>
await this.item.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } }) await this.item.setSoinsBlessure({ soinscomplets: { done: event.currentTarget.checked } })
}); )
this.html.find('[name="system-gravite"]').change(async event => { this.html.find('[name="system-gravite"]').change(async event => {
const gravite = Number(event.currentTarget.value) const gravite = Number(event.currentTarget.value)
await this.item.setSoinsBlessure({ gravite: gravite, difficulte: - gravite }) await this.item.setSoinsBlessure({ gravite: gravite, difficulte: - gravite })
}); })
} }
} }

View File

@ -1,5 +1,5 @@
import { RdDBaseActorSheet } from "../actor/base-actor-sheet.js"; 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 { RdDSheetUtility } from "../rdd-sheet-utility.js";
import { RdDUtility } from "../rdd-utility.js"; import { RdDUtility } from "../rdd-utility.js";
import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js"; import { RdDItemInventaireSheet } from "./sheet-base-inventaire.js";
@ -29,9 +29,10 @@ export class RdDConteneurItemSheet extends RdDItemInventaireSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
prepareConteneurData(formData) { prepareConteneurData(formData) {
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes); RdDUtility.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires); 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) { async _onDragStart(event) {

View File

@ -9,7 +9,7 @@ export class RdDFauneItemSheet extends RdDItemInventaireSheet {
if (!this.options.editable) return; 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) { async _onDropActor(event, dragData) {

View 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}`)
});
}
}

View 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}`)
});
}
}

View File

@ -44,8 +44,8 @@ export class RdDRencontreItemSheet extends RdDItemSheet {
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
if (!this.options.editable) return; if (!this.options.editable) return;
this.html.find("a.effet-add").click(event => this.onAddEffet(event)); this.html.find("a.effet-add").click(async event => await this.onAddEffet(event));
this.html.find("a.effet-delete").click(event => this.onDeleteEffet(event)); this.html.find("a.effet-delete").click(async event => await this.onDeleteEffet(event));
} }
async onAddEffet(event) { async onAddEffet(event) {

View File

@ -36,9 +36,9 @@ export class RdDSigneDraconiqueItemSheet extends RdDItemSheet {
if (!this.options.editable) return; if (!this.options.editable) return;
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire()); html.find(".signe-aleatoire").click(async event => await this.setSigneAleatoire());
html.find("input.select-tmr").change(event => this.onSelectTmr(event)); html.find("input.select-tmr").change(async event => await 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-xp-sort").change(async event => await this.onValeurXpSort(event.currentTarget.attributes['data-typereussite']?.value, Number(event.currentTarget.value)));
} }
async setSigneAleatoire() { async setSigneAleatoire() {

View File

@ -1,5 +1,6 @@
import { ITEM_TYPES } from "../constants.js";
import { RdDItem } from "../item.js";
import { Grammar } from "../grammar.js" import { Grammar } from "../grammar.js"
import { ITEM_TYPES, RdDItem } from "../item.js"
import { SystemCompendiums } from "../settings/system-compendiums.js" import { SystemCompendiums } from "../settings/system-compendiums.js"
const DON_HAUT_REVE = "Don de Haut-Rêve" const DON_HAUT_REVE = "Don de Haut-Rêve"

View File

@ -2,7 +2,8 @@ import { RdDBaseActor } from "./actor/base-actor.js";
import { LOG_HEAD, SYSTEM_RDD } from "./constants.js"; import { LOG_HEAD, SYSTEM_RDD } from "./constants.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Monnaie } from "./item-monnaie.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 { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDRaretes } from "./item/raretes.js"; import { RdDRaretes } from "./item/raretes.js";
import { VOIES_DRACONIC } from "./item-sort.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 { export class Migrations {
static getMigrations() { static getMigrations() {
return [ return [
@ -609,6 +659,8 @@ export class Migrations {
new _11_2_20_MigrationAstrologie(), new _11_2_20_MigrationAstrologie(),
new _12_0_26_MigrationVoieSorts(), new _12_0_26_MigrationVoieSorts(),
new _12_0_32_MigrationRaces(), new _12_0_32_MigrationRaces(),
new _12_0_37_MigrationAlchimieEtat(),
new _12_0_38_TachesEcriture()
]; ];
} }

View File

@ -238,7 +238,7 @@ export class Misc {
/* -------------------------------------------- */ /* -------------------------------------------- */
static findFirstLike(value, elements, options = {}) { static findFirstLike(value, elements, options = {}) {
options = foundry.utils.mergeObject(DEFAULT_FIND_OPTIONS, options, { overwrite: true, inplace: false }); 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) { if (subset.length == 0) {
console.log(`Aucune ${options.description} pour ${value}`); console.log(`Aucune ${options.description} pour ${value}`);
return undefined return undefined
@ -263,8 +263,9 @@ export class Misc {
} }
value = Grammar.toLowerCaseNoAccent(value); value = Grammar.toLowerCaseNoAccent(value);
const subset = elements.filter(options.preFilter) const subset = elements.filter(options.preFilter)
.filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value)); .filter(it => Grammar.toLowerCaseNoAccent(options.mapper(it))?.includes(value))
if (subset.length == 0) { .sort(Misc.ascending(it => options.mapper(it)))
if (subset.length == 0 && options?.onMessage) {
options.onMessage(`Pas de ${options.description} correspondant à ${value}`); options.onMessage(`Pas de ${options.description} correspondant à ${value}`);
} }
return subset; return subset;

View File

@ -57,7 +57,7 @@ export const LIST_CARAC_PERSONNAGE = {
} }
export const LIST_CARAC_AUTRES = { export const LIST_CARAC_AUTRES = {
'perception': { code: 'perception', label: 'Perception', path: 'system.carac.perception.value' }, 'perception': { code: 'perception', label: 'Perception', path: 'system.carac.perception.value' },
} }
const LIST_CARAC_DERIVEE = { const LIST_CARAC_DERIVEE = {
@ -75,12 +75,12 @@ const LIST_CARAC_ROLL = Object.values(LIST_CARAC_PERSONNAGE).filter(it => it.isC
export class RdDCarac { export class RdDCarac {
static caracDetails(name) { static caracDetails(name, options = { onMessage: undefined }) {
let entry = Misc.findFirstLike(name, LIST_CARAC_ROLL, { mapper: it => it.code, description: 'caractéristique', onMessage: m => { } }) let entry = Misc.findFirstLike(name, LIST_CARAC_ROLL, { mapper: it => it.code, description: 'caractéristique', onMessage: m => { } })
if (entry) { if (entry) {
return entry return entry
} }
return Misc.findFirstLike(name, LIST_CARAC_ROLL, { mapper: it => it.label, description: 'caractéristique' }) return Misc.findFirstLike(name, LIST_CARAC_ROLL, { mapper: it => it.label, description: 'caractéristique', onMessage: options.onMessage })
} }
static carac(code) { static carac(code) {

View File

@ -13,6 +13,7 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { STATUSES } from "./settings/status-effects.js"; import { STATUSES } from "./settings/status-effects.js";
import { Targets } from "./targets.js"; import { Targets } from "./targets.js";
import { RdDEmpoignade } from "./rdd-empoignade.js"; import { RdDEmpoignade } from "./rdd-empoignade.js";
import { RdDRollResult } from "./rdd-roll-result.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
const premierRoundInit = [ const premierRoundInit = [
@ -361,7 +362,7 @@ export class RdDCombatManager extends Combat {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static listActionsActorCombatant( actor) { static listActionsActorCombatant(actor) {
const possessions = actor.listActionsPossessions() const possessions = actor.listActionsPossessions()
const actions = possessions.length > 0 const actions = possessions.length > 0
? possessions ? possessions
@ -542,7 +543,7 @@ export class RdDCombat {
case '.particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value); case '.particuliere-attaque': return await this.choixParticuliere(attackerRoll, event.currentTarget.attributes['data-mode'].value);
case '.parer-button': return this.parade(attackerRoll, armeParadeId); case '.parer-button': return this.parade(attackerRoll, armeParadeId);
case '.esquiver-button': return this.esquive(attackerRoll, compId, competence); case '.esquiver-button': return this.esquive(attackerRoll, compId, competence);
case '0encaisser-button': return this.encaisser(attackerRoll, defenderRoll); case '.encaisser-button': return this.encaisser(attackerRoll, defenderRoll);
case '.echec-total-attaque': return this._onEchecTotal(attackerRoll); case '.echec-total-attaque': return this._onEchecTotal(attackerRoll);
case '.appel-chance-attaque': return this.attacker.rollAppelChance( case '.appel-chance-attaque': return this.attacker.rollAppelChance(
@ -667,7 +668,7 @@ export class RdDCombat {
const activite = this._ajustementMouvement(this.defender) const activite = this._ajustementMouvement(this.defender)
const total = [portee, taille, activite].map(it => it.diff).filter(d => !Number.isNaN(d)).reduce(Misc.sum(), 0) const total = [portee, taille, activite].map(it => it.diff).filter(d => !Number.isNaN(d)).reduce(Misc.sum(), 0)
ChatMessage.create({ 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, rollData: rollData,
attacker: _token, attacker: _token,
isVisible: isVisible, isVisible: isVisible,
@ -734,7 +735,7 @@ export class RdDCombat {
await this.proposerAjustementTirLancer(rollData) await this.proposerAjustementTirLancer(rollData)
const dialog = await RdDRoll.create(this.attacker, 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', name: 'jet-attaque',
label: 'Attaque: ' + (arme?.name ?? competence.name), label: 'Attaque: ' + (arme?.name ?? competence.name),
@ -742,11 +743,8 @@ export class RdDCombat {
this.attacker.createCallbackExperience(), this.attacker.createCallbackExperience(),
this.attacker.createCallbackAppelAuMoral(), this.attacker.createCallbackAppelAuMoral(),
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) }, { action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
{ condition: r => arme && !RdDCombat.isParticuliere(r), action: r => this.attacker.incDecItemUse(arme._id) }, { action: async r => await this.attacker.incDecItemUse(arme._id, arme && !RdDCombat.isParticuliere(r)) },
{ condition: r => (RdDCombat.isReussite(r) && !RdDCombat.isParticuliere(r)), action: r => this._onAttaqueNormale(r) }, { action: r => this._onAttaque(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) },
] ]
}); });
dialog.render(true); dialog.render(true);
@ -782,9 +780,23 @@ export class RdDCombat {
return rollData; return rollData;
} }
async _onAttaque(attackerRoll) {
if (RdDCombat.isParticuliere(attackerRoll)) {
return await this._onAttaqueParticuliere(attackerRoll)
}
if (RdDCombat.isReussite(attackerRoll)) {
return await this._onAttaqueNormale(attackerRoll)
}
// if (RdDCombat.isParticuliere(attackerRoll) && attackerRoll.particuliere == undefined) {
// return
// }
if (RdDCombat.isEchecTotal(attackerRoll)) {
return await this._onAttaqueEchecTotal(attackerRoll)
}
return await this._onAttaqueEchec(attackerRoll)
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onAttaqueParticuliere(rollData) { async _onAttaqueParticuliere(rollData) {
const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0; const isMeleeDiffNegative = (rollData.competence.type == 'competencecreature' || rollData.selectedCarac.label == "Mêlée") && rollData.diffLibre < 0;
// force toujours, sauf empoignade // force toujours, sauf empoignade
// finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum // finesse seulement en mélée, pour l'empoignade, ou si la difficulté libre est de -1 minimum
@ -806,7 +818,7 @@ export class RdDCombat {
const choixParticuliere = await ChatMessage.create({ const choixParticuliere = await ChatMessage.create({
alias: this.attacker.getAlias(), alias: this.attacker.getAlias(),
whisper: ChatUtility.getOwners(this.attacker), 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(), alias: this.attacker.getAlias(),
attackerId: this.attackerId, attackerId: this.attackerId,
attackerToken: this.attackerToken, attackerToken: this.attackerToken,
@ -830,13 +842,13 @@ export class RdDCombat {
cible: this.defender?.getAlias() ?? 'la cible', cible: this.defender?.getAlias() ?? 'la cible',
isRecul: (attackerRoll.particuliere == 'force' || attackerRoll.tactique == 'charge') 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')) { if (!await this.attacker.accorder(this.defender, 'avant-defense')) {
return; return;
} }
if (this.target) { if (this.defender) {
await this._sendMessageDefense(attackerRoll, defenderRoll); await this._sendMessageDefense(attackerRoll, defenderRoll);
} }
} }
@ -895,7 +907,7 @@ export class RdDCombat {
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)), speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
alias: this.attacker?.getAlias(), alias: this.attacker?.getAlias(),
whisper: ChatUtility.getOwners(this.defender), whisper: ChatUtility.getOwners(this.defender),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.html', paramDemandeDefense), content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', paramDemandeDefense),
}); });
// flag pour garder les jets d'attaque/defense // flag pour garder les jets d'attaque/defense
ChatUtility.setMessageData(choixDefense, 'defender-roll', defenderRoll); ChatUtility.setMessageData(choixDefense, 'defender-roll', defenderRoll);
@ -940,7 +952,7 @@ export class RdDCombat {
async _onAttaqueEchecTotal(attackerRoll) { async _onAttaqueEchecTotal(attackerRoll) {
const choixEchecTotal = await ChatMessage.create({ const choixEchecTotal = await ChatMessage.create({
whisper: ChatUtility.getOwners(this.attacker), whisper: ChatUtility.getOwners(this.attacker),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', { content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.hbs', {
attackerId: this.attackerId, attackerId: this.attackerId,
attacker: this.attacker, attacker: this.attacker,
attackerToken: this.attackerToken, attackerToken: this.attackerToken,
@ -964,22 +976,20 @@ export class RdDCombat {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onAttaqueEchec(rollData) { async _onAttaqueEchec(attackerRoll) {
console.log("RdDCombat.onAttaqueEchec >>>", rollData); console.log("RdDCombat.onAttaqueEchec >>>", attackerRoll);
await RdDResolutionTable.displayRollData(rollData, this.attacker, 'chat-resultat-attaque.html'); await RdDRollResult.displayRollData(attackerRoll, this.attacker, 'chat-resultat-attaque.hbs');
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async choixParticuliere(rollData, choix) { async choixParticuliere(rollData, choix) {
console.log("RdDCombat.choixParticuliere >>>", rollData, choix); console.log("RdDCombat.choixParticuliere >>>", rollData, choix);
if (choix != "rapidite") { await this.attacker.incDecItemUse(rollData.arme.id, choix != "rapidite")
this.attacker.incDecItemUse(rollData.arme.id);
}
this.removeChatMessageActionsPasseArme(rollData.passeArme); this.removeChatMessageActionsPasseArme(rollData.passeArme);
rollData.particuliere = choix; rollData.particuliere = choix;
await this._onAttaqueNormale(rollData); await this._onAttaqueNormale(rollData)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -995,7 +1005,7 @@ export class RdDCombat {
let rollData = this._prepareParade(attackerRoll, arme, competence); let rollData = this._prepareParade(attackerRoll, arme, competence);
const dialog = await RdDRoll.create(this.defender, rollData, 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', name: 'jet-parade',
label: 'Parade: ' + (arme ? arme.name : rollData.competence.name), label: 'Parade: ' + (arme ? arme.name : rollData.competence.name),
@ -1003,10 +1013,8 @@ export class RdDCombat {
this.defender.createCallbackExperience(), this.defender.createCallbackExperience(),
this.defender.createCallbackAppelAuMoral(), this.defender.createCallbackAppelAuMoral(),
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) }, { action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
{ condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(armeParadeId) }, { action: async r => await this.defender.incDecItemUse(armeParadeId, !RdDCombat.isParticuliere(r)) },
{ condition: RdDCombat.isReussite, action: r => this._onParadeNormale(r) }, { action: r => this._onParade(r) },
{ condition: RdDCombat.isParticuliere, action: r => this._onParadeParticuliere(r) },
{ condition: RdDCombat.isEchec, action: r => this._onParadeEchec(r) },
] ]
}); });
dialog.render(true); dialog.render(true);
@ -1037,8 +1045,19 @@ export class RdDCombat {
return defenderRoll; return defenderRoll;
} }
async _onParade(defenderRoll) {
if (RdDCombat.isParticuliere(defenderRoll)) {
return await this._onParadeParticuliere(defenderRoll)
}
if (RdDCombat.isReussite(defenderRoll)) {
return await this._onParadeNormale(defenderRoll)
}
await this._onParadeEchec(defenderRoll)
}
/* -------------------------------------------- */ /* -------------------------------------------- */
_onParadeParticuliere(defenderRoll) { async _onParadeParticuliere(defenderRoll) {
console.log("RdDCombat._onParadeParticuliere >>>", defenderRoll); console.log("RdDCombat._onParadeParticuliere >>>", defenderRoll);
if (!defenderRoll.attackerRoll.isPart) { if (!defenderRoll.attackerRoll.isPart) {
// TODO: attaquant doit jouer résistance et peut être désarmé p132 // TODO: attaquant doit jouer résistance et peut être désarmé p132
@ -1047,14 +1066,13 @@ export class RdDCombat {
this.defender) this.defender)
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onParadeNormale(defenderRoll) { async _onParadeNormale(defenderRoll) {
console.log("RdDCombat._onParadeNormale >>>", defenderRoll); console.log("RdDCombat._onParadeNormale >>>", defenderRoll);
await this.computeRecul(defenderRoll); await this.computeRecul(defenderRoll);
await this.computeDeteriorationArme(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); this.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
} }
@ -1062,7 +1080,7 @@ export class RdDCombat {
async _onParadeEchec(defenderRoll) { async _onParadeEchec(defenderRoll) {
console.log("RdDCombat._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.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true }); this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true });
@ -1079,18 +1097,16 @@ export class RdDCombat {
let rollData = this._prepareEsquive(attackerRoll, esquive); let rollData = this._prepareEsquive(attackerRoll, esquive);
const dialog = await RdDRoll.create(this.defender, rollData, 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', name: 'jet-esquive',
label: 'Esquiver', label: 'Esquiver',
callbacks: [ callbacks: [
this.defender.createCallbackExperience(), this.defender.createCallbackExperience(),
this.defender.createCallbackAppelAuMoral(), this.defender.createCallbackAppelAuMoral(),
{ condition: r => !RdDCombat.isParticuliere(r), action: r => this.defender.incDecItemUse(esquive._id) }, { action: async r => await this.defender.incDecItemUse(esquive._id, !RdDCombat.isParticuliere(r)) },
{ action: r => this.removeChatMessageActionsPasseArme(r.passeArme) }, { action: r => this.removeChatMessageActionsPasseArme(r.passeArme) },
{ condition: RdDCombat.isReussite, action: r => this._onEsquiveNormale(r) }, { action: r => this._onEsquive(r) },
{ condition: RdDCombat.isParticuliere, action: r => this._onEsquiveParticuliere(r) },
{ condition: RdDCombat.isEchec, action: r => this._onEsquiveEchec(r) },
] ]
}); });
dialog.render(true); dialog.render(true);
@ -1118,9 +1134,18 @@ export class RdDCombat {
return rollData; return rollData;
} }
async _onEsquive(defenderRoll) {
if (RdDCombat.isParticuliere(defenderRoll)) {
return await this._onEsquiveParticuliere(defenderRoll)
}
if (RdDCombat.isReussite(defenderRoll)) {
return await this._onEsquiveNormale(defenderRoll)
}
return await this._onEsquiveEchec(defenderRoll)
}
/* -------------------------------------------- */ /* -------------------------------------------- */
_onEsquiveParticuliere(rollData) { async _onEsquiveParticuliere(defenderRoll) {
console.log("RdDCombat._onEsquiveParticuliere >>>", rollData); console.log("RdDCombat._onEsquiveParticuliere >>>", defenderRoll);
ChatUtility.createChatWithRollMode( ChatUtility.createChatWithRollMode(
{ content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" }, { content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" },
this.defender); this.defender);
@ -1129,7 +1154,7 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onEsquiveNormale(defenderRoll) { async _onEsquiveNormale(defenderRoll) {
console.log("RdDCombat._onEsquiveNormal >>>", 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); this.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
} }
@ -1137,7 +1162,7 @@ export class RdDCombat {
async _onEsquiveEchec(defenderRoll) { async _onEsquiveEchec(defenderRoll) {
console.log("RdDCombat._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.removeChatMessageActionsPasseArme(defenderRoll.passeArme);
this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true }) this._sendMessageDefense(defenderRoll.attackerRoll, defenderRoll, { defense: true })

View File

@ -18,6 +18,7 @@ import { FenetreRechercheTirage } from "./tirage/fenetre-recherche-tirage.js";
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
import { DialogFatigueVoyage } from "./voyage/dialog-fatigue-voyage.js"; import { DialogFatigueVoyage } from "./voyage/dialog-fatigue-voyage.js";
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js";
import { RdDRollResult } from "./rdd-roll-result.js";
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/; 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 <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({ path: ["/ddr"], func: (content, msg, params) => this.rollDeDraconique(msg), descr: "Lance un Dé Draconique" });
this.registerCommand({ this.registerCommand({
@ -256,7 +267,7 @@ export class RdDCommands {
let commands = [] let commands = []
this._buildSubTableHelp(commands, table ?? this.commandsTable); 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( let d = new Dialog(
{ {
title: "Commandes disponibles dans le tchat", 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) { async rollRdDNumeric(msg, carac, diff, significative = false) {
@ -349,7 +379,7 @@ export class RdDCommands {
show: { title: "Table de résolution" } show: { title: "Table de résolution" }
}; };
await RdDResolutionTable.rollData(rollData); 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) { async getTMRAleatoire(msg, params) {
if (params.length < 2) { if (params.length < 2) {
let type = params[0] let type = params[0]
const solvedTerrain = TMRUtility.findTMRLike(type)?.type const solvedTerrain = type ? TMRUtility.findTMRLike(type)?.type : undefined
if (solvedTerrain){ const filter = solvedTerrain ? (it => it.type == solvedTerrain) : (it => true)
const tmr = await TMRUtility.getTMRAleatoire(type ? (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 RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`)
} }
} }
return false; return false
} }
async findTMR(msg, params) { async findTMR(msg, params) {

View File

@ -1,13 +1,10 @@
/* -------------------------------------------- */ /* -------------------------------------------- */
import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDRoll } from "./rdd-roll.js"; import { RdDRoll } from "./rdd-roll.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js";
import { STATUSES } from "./settings/status-effects.js"; import { STATUSES } from "./settings/status-effects.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ITEM_TYPES } from "./constants.js";
import { ITEM_TYPES } from "./item.js"; import { RdDRollResult } from "./rdd-roll-result.js";
/* -------------------------------------------- */
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDEmpoignade { export class RdDEmpoignade {
@ -160,7 +157,7 @@ export class RdDEmpoignade {
if ((isNouvelle || empoignade.system.pointsemp == 0) && defender.hasArmeeMeleeEquipee()) { if ((isNouvelle || empoignade.system.pointsemp == 0) && defender.hasArmeeMeleeEquipee()) {
ChatUtility.createChatWithRollMode( 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 attacker
) )
@ -193,7 +190,7 @@ export class RdDEmpoignade {
} }
if (empoignade.system.pointsemp >= 2) { if (empoignade.system.pointsemp >= 2) {
if (!empoignade.system.ausol) { 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); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
} else { } else {
@ -217,7 +214,7 @@ export class RdDEmpoignade {
} }
const msg = await ChatMessage.create({ const msg = await ChatMessage.create({
whisper: ChatUtility.getOwners(attacker), 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); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
@ -225,7 +222,7 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) { static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) {
const dialog = await RdDRoll.create(attacker, rollData, 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', name: 'jet-empoignade',
label: 'Empoigner', label: 'Empoigner',
@ -251,7 +248,7 @@ export class RdDEmpoignade {
if (rollData.rolled.isPart) { if (rollData.rolled.isPart) {
rollData.particuliere = "finesse"; 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); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
@ -288,7 +285,7 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $rollDefenseEmpoignade(defender, defenderRoll) { static async $rollDefenseEmpoignade(defender, defenderRoll) {
const dialog = await RdDRoll.create(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', name: 'empoignade',
label: 'Contrer', label: 'Contrer',
@ -313,9 +310,9 @@ export class RdDEmpoignade {
RdDEmpoignade.$updateEtatEmpoignade(empoignade) 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) { 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); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
} }
@ -359,7 +356,7 @@ export class RdDEmpoignade {
await attacker.setEffect(STATUSES.StatusProne, true); await attacker.setEffect(STATUSES.StatusProne, true);
await defender.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); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
@ -375,7 +372,7 @@ export class RdDEmpoignade {
await defender.setEffect(STATUSES.StatusProne, true); await defender.setEffect(STATUSES.StatusProne, true);
await this.$deleteEmpoignade(empoignade) 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); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
@ -402,7 +399,7 @@ export class RdDEmpoignade {
if (perteMode == "endquart") { if (perteMode == "endquart") {
await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4))); 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); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
@ -429,7 +426,6 @@ export class RdDEmpoignade {
return await Item.create({ return await Item.create({
name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name, name: "Empoignade en cours de " + attacker.name + ' sur ' + defender.name,
type: 'empoignade', 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 } system: { description: "", empoignadeid: foundry.utils.randomID(16), compteempoigne: 0, empoigneurid: attacker.id, empoigneid: defender.id, ptsemp: 0, empoigneurname: attacker.name, empoignename: defender.name }
}, },
{ {

View File

@ -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;
}
}

View File

@ -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);
}
}
}
}

View File

@ -1,6 +1,6 @@
import { RdDItemArme } from "./item-arme.js"; import { RdDItemArme } from "./item-arme.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { ITEM_TYPES } from "./item.js"; import { ITEM_TYPES } from "./constants.js";
export class RdDHotbar { export class RdDHotbar {

View File

@ -18,7 +18,6 @@ import { RdDCompendiumOrganiser } from "./rdd-compendium-organiser.js"
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js" import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"
import { RdDHotbar } from "./rdd-hotbar-drop.js" import { RdDHotbar } from "./rdd-hotbar-drop.js"
import { EffetsDraconiques } from "./tmr/effets-draconiques.js" import { EffetsDraconiques } from "./tmr/effets-draconiques.js"
import { RdDHerbes } from "./rdd-herbes.js"
import { RdDDice } from "./rdd-dice.js" import { RdDDice } from "./rdd-dice.js"
import { RdDPossession } from "./rdd-possession.js" import { RdDPossession } from "./rdd-possession.js"
import { Misc } from "./misc.js" import { Misc } from "./misc.js"
@ -76,7 +75,10 @@ import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.
import { RdDActorExportSheet } from "./actor/export-scriptarium/actor-encart-sheet.js" import { RdDActorExportSheet } from "./actor/export-scriptarium/actor-encart-sheet.js"
import { RdDStatBlockParser } from "./apps/rdd-import-stats.js" import { RdDStatBlockParser } from "./apps/rdd-import-stats.js"
import { RdDJournalSheet } from "./journal/journal-sheet.js" import { RdDJournalSheet } from "./journal/journal-sheet.js"
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.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 * RdD system
@ -87,9 +89,9 @@ export class SystemReveDeDragon {
static start() { static start() {
const system = new SystemReveDeDragon() 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('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d))
Hooks.once('ready', async () => await system.onReady()) Hooks.once('ready', () => system.onReady())
} }
constructor() { constructor() {
@ -100,16 +102,18 @@ export class SystemReveDeDragon {
this.itemClasses = { this.itemClasses = {
armure: RdDItemArmure, armure: RdDItemArmure,
blessure: RdDItemBlessure, blessure: RdDItemBlessure,
gemme: RdDItemGemme,
maladie: RdDItemMaladie, maladie: RdDItemMaladie,
ombre: RdDItemOmbre, ombre: RdDItemOmbre,
poison: RdDItemPoison, poison: RdDItemPoison,
potion: RdDItemPotion,
queue: RdDItemQueue, queue: RdDItemQueue,
tete: RdDItemTete,
race: RdDItemRace, race: RdDItemRace,
rencontre: RdDRencontre, rencontre: RdDRencontre,
service: RdDItemService, service: RdDItemService,
signedraconique: RdDItemSigneDraconique, signedraconique: RdDItemSigneDraconique,
souffle: RdDItemSouffle, souffle: RdDItemSouffle,
tete: RdDItemTete,
} }
this.actorClasses = { this.actorClasses = {
commerce: RdDCommerce, commerce: RdDCommerce,
@ -123,14 +127,14 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
/* -------------------------------------------- */ /* -------------------------------------------- */
async onInit() { onInit() {
game.system.rdd = this game.system.rdd = this
this.AppAstrologie = AppAstrologie this.AppAstrologie = AppAstrologie
console.log(`Initializing Reve de Dragon System Settings`) console.log(`Initializing Reve de Dragon System Settings`)
// preload handlebars templates // preload handlebars templates
await RdDUtility.preloadHandlebarsTemplates() RdDUtility.preloadHandlebarsTemplates()
AppPersonnageAleatoire.preloadHandlebars() AppPersonnageAleatoire.preloadHandlebars()
RdDItemSort.preloadHandlebars() RdDItemSort.preloadHandlebars()
@ -187,24 +191,14 @@ export class SystemReveDeDragon {
Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true }) Actors.registerSheet(SYSTEM_RDD, RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true })
Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true }) Actors.registerSheet(SYSTEM_RDD, RdDActorEntiteSheet, { types: ["entite"], makeDefault: true })
Items.unregisterSheet("core", ItemSheet) Items.unregisterSheet("core", ItemSheet)
await RdDActorExportSheet.init() 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)
RdDJournalSheet.register()
Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, { Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, {
types: [ types: [
"objet", "arme", "armure", "livre", "potion", "munition", "objet", "arme", "armure", "livre", "munition",
"monnaie", "nourritureboisson", "gemme", "monnaie", "nourritureboisson",
], makeDefault: true ],
makeDefault: true
}) })
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, { Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
types: [ types: [
@ -214,8 +208,22 @@ export class SystemReveDeDragon {
"queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve", "queue", "ombre", "souffle", "tete", "casetmr", "sort", "sortreserve",
"nombreastral", "tache", "maladie", "poison", "possession", "nombreastral", "tache", "maladie", "poison", "possession",
"tarot", "extraitpoetique", "empoignade" "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 // préparation des différents modules
console.log(`Initializing Reve de Dragon Hooks and handlers`) console.log(`Initializing Reve de Dragon Hooks and handlers`)
@ -316,7 +324,6 @@ export class SystemReveDeDragon {
} }
StatusEffects.onReady() StatusEffects.onReady()
RdDHerbes.onReady()
RdDDice.onReady() RdDDice.onReady()
RdDStatBlockParser.parseStatBlock() RdDStatBlockParser.parseStatBlock()

View File

@ -117,7 +117,7 @@ export class RdDMeteo {
meteo.pluie.description = RdDMeteo.pluie(meteo.pluie.force); meteo.pluie.description = RdDMeteo.pluie(meteo.pluie.force);
ChatMessage.create({ 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() whisper: ChatUtility.getGMs()
}); });
} }

View File

@ -13,7 +13,7 @@ const words = ['pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i',
export class RdDNameGen { export class RdDNameGen {
static async proposeName(msg, params) { 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() nom: await RdDNameGen.generate()
}); });
ChatMessage.create({ content: html, whisper: ChatUtility.getGMs() }); ChatMessage.create({ content: html, whisper: ChatUtility.getGMs() });

View File

@ -1,9 +1,9 @@
/* -------------------------------------------- */
import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDRoll } from "./rdd-roll.js"; import { RdDRoll } from "./rdd-roll.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { RdDItemCompetenceCreature } from "./item-competencecreature.js";
import { Targets } from "./targets.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 /* On part du principe qu'une entité démarre tjs
@ -91,18 +91,21 @@ export class RdDPossession {
} }
RdDPossession.selectCompetenceDraconicOuPossession(rollData, defender) RdDPossession.selectCompetenceDraconicOuPossession(rollData, defender)
rollData.diffLibre = RdDPossession.getInfoAttaque(rollData).diffLibre rollData.diffLibre = RdDPossession.getInfoAttaque(rollData).diffLibre
await RdDPossession.$rollDefensePossession(defender, rollData); await RdDPossession.$rollDefensePossession(defender, rollData);
} }
static selectCompetenceDraconicOuPossession(rollData, rollingActor) { static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
rollData.competence = rollingActor.getDraconicOuPossession(); rollData.competence = rollingActor.getDraconicOuPossession();
if (rollingActor.isCreatureEntite()) { 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 { else {
rollData.selectedCarac = rollingActor.system.carac.reve
rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } } rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } }
rollData.selectedCarac = rollData.forceCarac['reve-actuel']
rollData.competence.system.defaut_carac = 'reve-actuel' rollData.competence.system.defaut_carac = 'reve-actuel'
} }
} }
@ -110,7 +113,7 @@ export class RdDPossession {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) { static async $rollAttaquePossession(attacker, rollData, isNouvelle = false) {
const dialog = await RdDRoll.create(attacker, rollData, 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', name: 'jet-possession',
label: rollData.isECNIDefender ? 'Conjurer la possession' : '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) const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid)
RdDPossession.storePossessionAttaque(possession, rollData) 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) { static async $rollDefensePossession(defender, rollData) {
const dialog = await RdDRoll.create(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', name: 'possession',
label: 'Conjurer une Possession', label: 'Conjurer une Possession',
@ -171,10 +174,10 @@ export class RdDPossession {
rollData.possession = possession rollData.possession = possession
RdDPossession.$updateEtatPossession(rollData.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) { if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
// conjuration // conjuration
victime.deleteEmbeddedDocuments("Item", [rollData.possession._id]) await victime.deleteEmbeddedDocuments("Item", [rollData.possession._id])
} }
} }

View File

@ -1,4 +1,3 @@
import { ChatUtility } from "./chat-utility.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js"; import { RdDDice } from "./rdd-dice.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
@ -54,7 +53,6 @@ export class RdDResolutionTable {
return this._computeCell(level, percentage); return this._computeCell(level, percentage);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _computeRow(caracValue) { static _computeRow(caracValue) {
let dataRow = [ let dataRow = [
@ -89,24 +87,10 @@ export class RdDResolutionTable {
return resultat; 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) { static actorChatName(actor) {
return actor ?? game.user.name; 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) { static async rollData(rollData) {
rollData.rolled = await this.roll(rollData.caracValue, rollData.finalLevel, rollData); rollData.rolled = await this.roll(rollData.caracValue, rollData.finalLevel, rollData);
@ -284,7 +268,7 @@ export class RdDResolutionTable {
maxCarac = Math.min(maxCarac, minCarac + 20); maxCarac = Math.min(maxCarac, minCarac + 20);
minLevel = Math.max(minLevel, -10); minLevel = Math.max(minLevel, -10);
maxLevel = Math.max(Math.min(maxLevel, 30), minLevel + colonnes); 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, carac: carac,
difficulte: level, difficulte: level,
min: minLevel, min: minLevel,

View File

@ -8,7 +8,7 @@ import { RdDUtility } from "./rdd-utility.js";
export class RdDEncaisser extends Dialog { export class RdDEncaisser extends Dialog {
static async encaisser(actor) { 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() } { ajustementsEncaissement: RdDUtility.getAjustementsEncaissement() }
); );
new RdDEncaisser(html, actor).render(true); new RdDEncaisser(html, actor).render(true);

View File

@ -15,7 +15,7 @@ export class RdDRollResolutionTable extends Dialog {
if (RdDRollResolutionTable.resolutionTable == undefined) { if (RdDRollResolutionTable.resolutionTable == undefined) {
const rollData = {} const rollData = {}
RdDRollResolutionTable._setDefaultOptions(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 = new RdDRollResolutionTable(rollData, html);
RdDRollResolutionTable.resolutionTable.render(true); RdDRollResolutionTable.resolutionTable.render(true);
} }

17
module/rdd-roll-result.js Normal file
View 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);
}
}

View File

@ -8,7 +8,7 @@ import { RdDCarac } from "./rdd-carac.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { ACTOR_TYPES } from "./item.js"; import { ACTOR_TYPES } from "./constants.js";
/** /**
* Extend the base Dialog entity to select roll parameters * Extend the base Dialog entity to select roll parameters
@ -137,7 +137,11 @@ export class RdDRoll extends Dialog {
this.rollData.selectedCarac = this.rollData.carac[this.actor.mapCarac(this.rollData.competence.system.defaut_carac)] this.rollData.selectedCarac = this.rollData.carac[this.actor.mapCarac(this.rollData.competence.system.defaut_carac)]
} }
if (this.rollData.selectedCarac) { if (this.rollData.selectedCarac) {
this.html.find("[name='carac']").val(RdDCarac.caracDetails(this.rollData.selectedCarac.label).code) 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) { if (this.rollData.selectedSort) {
this.setSelectedSort(this.rollData.selectedSort); this.setSelectedSort(this.rollData.selectedSort);
@ -265,24 +269,21 @@ export class RdDRoll extends Dialog {
} }
async onAction(action) { async onAction(action) {
this.rollData.forceDiceResult = Number.parseInt(this.html.find("[name='force-dice-result']").val()) ?? -1; this.rollData.forceDiceResult = Number.parseInt(this.html.find("[name='force-dice-result']").val()) ?? -1
await RdDResolutionTable.rollData(this.rollData); await RdDResolutionTable.rollData(this.rollData)
console.log("RdDRoll -=>", this.rollData, this.rollData.rolled);
if (action.callbacks) for (let callback of action.callbacks) {
for (let callback of action.callbacks) { await callback.action(this.rollData)
if (callback.condition == undefined || callback.condition(this.rollData)) { }
await callback.action(this.rollData);
}
}
} }
async setSelectedSort(sort) { async setSelectedSort(sort) {
this.rollData.selectedSort = sort; // Update the selectedCarac this.rollData.selectedSort = sort; // Update the selectedCarac
this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.system.draconic); this.rollData.competence = RdDItemSort.getBestDraconicSort(this.rollData.draconicList, sort)
this.rollData.bonus = RdDItemSort.getCaseBonus(sort, this.rollData.tmr.coord); this.rollData.bonus = RdDItemSort.getCaseBonus(sort, this.rollData.tmr.coord);
this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7); this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7);
RdDItemSort.setCoutReveReel(sort); RdDItemSort.setCoutReveReel(sort);
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(".sort-ou-rituel").text(sort.system.isrituel ? "rituel" : "sort");
this.html.find(".bonus-case").text(`${this.rollData.bonus}%`); this.html.find(".bonus-case").text(`${this.rollData.bonus}%`);
this.html.find(".placeholder-description-sort").children().remove(); this.html.find(".placeholder-description-sort").children().remove();
@ -343,7 +344,7 @@ export class RdDRoll extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async buildAjustements(rollData) { 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);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -1,4 +1,3 @@
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
import { CompendiumTable, CompendiumTableHelpers, SystemCompendiums } from "./settings/system-compendiums.js"; import { CompendiumTable, CompendiumTableHelpers, SystemCompendiums } from "./settings/system-compendiums.js";
export class RdDRollTables { export class RdDRollTables {

View File

@ -66,11 +66,13 @@ export class RdDSheetUtility {
} }
static async splitItem(item, actor, onSplit = () => { }) { 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); await RdDSheetUtility._onSplitItem(item, split, actor);
onSplit(); onSplit();
}); await RdDSheetUtility.renderItemBranch(actor, item)
dialog.render(true); }
const dialog = await DialogSplitItem.create(item, _onSplit)
dialog.render(true)
} }
static async _onSplitItem(item, split, actor) { static async _onSplitItem(item, split, actor) {
@ -82,4 +84,11 @@ export class RdDSheetUtility {
await actor.createEmbeddedDocuments('Item', [splitItem]) await actor.createEmbeddedDocuments('Item', [splitItem])
} }
} }
static async renderItemBranch(actor, item) {
while (item) {
await item.sheet?.render()
item = actor.getContenant(item)
}
}
} }

View File

@ -15,8 +15,7 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { RdDDice } from "./rdd-dice.js"; import { RdDDice } from "./rdd-dice.js";
import { STATUSES } from "./settings/status-effects.js"; import { STATUSES } from "./settings/status-effects.js";
import { RdDRencontre } from "./item/rencontre.js"; import { RdDRencontre } from "./item/rencontre.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { ITEM_TYPES } from "./constants.js";
import { ITEM_TYPES } from "./item.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
const TMR_DISPLAY_SIZE = { const TMR_DISPLAY_SIZE = {
@ -48,7 +47,7 @@ export class RdDTMRDialog extends Dialog {
static async create(actor, tmrData) { static async create(actor, tmrData) {
await PixiTMR.init() 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) { if (tmrData.mode != 'visu' && !game.user.isGM) {
ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatUtility.getGMs() }); 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.subdialog = undefined
this.displaySize = undefined this.displaySize = undefined
if (!this.viewOnly && !game.user.isGM) { if (!this.viewOnly && !game.user.isGM) {
this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); this.$tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")");
} }
this.callbacksOnAnimate = []; this.callbacksOnAnimate = [];
const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def); const displaySize = TMR_DISPLAY_SIZE.clamp(game.settings.get(SYSTEM_RDD, TMR_DISPLAY_SIZE.code) ?? TMR_DISPLAY_SIZE.def);
@ -139,7 +138,7 @@ export class RdDTMRDialog extends Dialog {
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
// Le reste... // Le reste...
this.updateValuesDisplay(); this.$updateValuesDisplay();
} }
lancerUnSort() { lancerUnSort() {
@ -190,7 +189,7 @@ export class RdDTMRDialog extends Dialog {
forceTMRContinueAction() { forceTMRContinueAction() {
ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR'); ui.notifications.warn('Vous devez finir votre action avant de continuer dans les TMR');
this.bringSubDialogToTop(); this.bringSubDialogToTop();
return; return false
} }
setTMRPendingAction(dialog) { setTMRPendingAction(dialog) {
@ -212,7 +211,7 @@ export class RdDTMRDialog extends Dialog {
} }
getSortsReserve(coord) { 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' TMRUtility.getTMR(coord).type == 'fleuve'
? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve' ? it => TMRUtility.getTMR(it.system.coord).type == 'fleuve'
: it => it.system.coord == coord : it => it.system.coord == coord
@ -241,7 +240,7 @@ export class RdDTMRDialog extends Dialog {
this._getTokensRencontres().forEach(t => this._trackToken(t)) this._getTokensRencontres().forEach(t => this._trackToken(t))
this._getTokensSortsReserve().forEach(t => this._trackToken(t)) this._getTokensSortsReserve().forEach(t => this._trackToken(t))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
updateTokens() { updateTokens() {
this._removeTokens(t => true); this._removeTokens(t => true);
@ -271,8 +270,7 @@ export class RdDTMRDialog extends Dialog {
} }
_getTokensSortsReserve() { _getTokensSortsReserve() {
const sortsReserve = this.actor.itemTypes[ITEM_TYPES.sortreserve]; return Misc.concat(this.sortsReserve.map(sortReserve =>
return Misc.concat(sortsReserve.map(sortReserve =>
EffetsDraconiques.sortReserve.tokens(this.pixiTMR, sortReserve, () => sortReserve.system.coord))) EffetsDraconiques.sortReserve.tokens(this.pixiTMR, sortReserve, () => sortReserve.system.coord)))
} }
@ -298,7 +296,7 @@ export class RdDTMRDialog extends Dialog {
const coordOrig = this._getCoordActor(); const coordOrig = this._getCoordActor();
const coordTarget = TMRUtility.deplacement(coordOrig, move); const coordTarget = TMRUtility.deplacement(coordOrig, move);
await this._deplacerDemiReve(coordTarget, 'normal'); await this._deplacerDemiReve(coordTarget, 'normal');
this.checkQuitterTMR(); await this.$checkQuitterTMR();
} }
calculCoutMonteeTMR() { calculCoutMonteeTMR() {
@ -306,7 +304,7 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async updateValuesDisplay() { async $updateValuesDisplay() {
if (this.viewOnly || !this.rendered) { if (this.viewOnly || !this.rendered) {
return; return;
} }
@ -337,22 +335,30 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async close() { async close() {
await this.$forceClose(this.actor.name + " a quitté les terres médianes")
}
async $forceClose(message) {
if (this.subdialog) { if (this.subdialog) {
return this.forceTMRContinueAction() this.forceTMRContinueAction()
return false
} }
this.descenteTMR = true; this.descenteTMR = true;
if (this.actor.tmrApp) { if (this.actor.tmrApp) {
this.actor.tmrApp = undefined; // Cleanup reference this.actor.tmrApp = undefined; // Cleanup reference
if (!this.viewOnly) { if (!this.viewOnly) {
await this.actor.setEffect(STATUSES.StatusDemiReve, false) await this.actor.setEffect(STATUSES.StatusDemiReve, false);
this._tellToGM(this.actor.name + " a quitté les terres médianes"); this.$tellToUserAndGM(message)
} }
await this.actor.santeIncDec((ReglesOptionnelles.isUsing("appliquer-fatigue") ? "fatigue" : "endurance"), const appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue");
this.cumulFatigue) await this.actor.santeIncDec(
appliquerFatigue ? "fatigue" : "endurance",
(appliquerFatigue ? 1 : -1) * this.cumulFatigue);
} }
await super.close(); this.pixiTMR.close();
this.pixiTMR.close()
this.pixiTMR = undefined this.pixiTMR = undefined
await super.close();
return true
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -364,48 +370,53 @@ export class RdDTMRDialog extends Dialog {
} }
switch (action) { switch (action) {
case 'derober': case 'derober':
await this.derober(); await this.$derober()
this.restoreTMRAfterAction(); this.restoreTMRAfterAction()
return; return
case 'refouler': case 'refouler':
await this.refouler(); await this.$refouler()
break; break
case 'maitriser': case 'maitriser':
await this.maitriserRencontre(); await this.$maitriserRencontre()
break; break
case 'ignorer': case 'ignorer':
await this.ignorerRencontre(); await this.$ignorerRencontre()
break; break
} }
await this.postRencontre(tmr); await this.postRencontre(tmr);
this.restoreTMRAfterAction(); this.restoreTMRAfterAction();
} }
async derober() { async $derober() {
console.log("-> derober", this.currentRencontre); if (this.currentRencontre) {
await this.actor.addTMRRencontre(this.currentRencontre); console.log("-> derober", this.currentRencontre);
this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR."); await this.actor.addTMRRencontre(this.currentRencontre);
this.close(); this.$forceClose(`${this.actor.name} s'est dérobé face à la rencontre ${this.currentRencontre.name}, et quitte les TMR.`)
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async refouler() { async $refouler() {
console.log("-> refouler", this.currentRencontre); if (this.currentRencontre) {
await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`); console.log("-> refouler", this.currentRencontre);
await this.actor.deleteRencontreTMRAtPosition() await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`);
this.updateTokens(); await this.$deleteRencontreTMRAtPosition()
this.updateValuesDisplay(); this.updateTokens();
this.nettoyerRencontre(); this.$updateValuesDisplay();
this.$nettoyerRencontre();
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async ignorerRencontre() { async $ignorerRencontre() {
console.log("-> ignorer", this.currentRencontre); if (this.currentRencontre) {
this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name); console.log("-> ignorer", this.currentRencontre);
await this.actor.deleteRencontreTMRAtPosition() this.$tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
this.updateTokens(); await this.$deleteRencontreTMRAtPosition()
this.updateValuesDisplay(); this.updateTokens();
this.nettoyerRencontre(); this.$updateValuesDisplay();
this.$nettoyerRencontre();
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -422,41 +433,29 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
checkQuitterTMR() { async $checkQuitterTMR() {
if (this.actor.isDead()) { const reason = this.actor.isDead()
this._tellToGM("Vous êtes mort : vous quittez les Terres médianes !"); ? "est mort"
this.close(); : this.actor.isCumulFatigueCauseSommeil(this.cumulFatigue)
return true; ? "s'écroule de fatigue"
: (this.actor.getReveActuel() == 0)
? "tombe à 0 Points de Rêve"
: undefined
if (reason) {
if (!this.actor.isDead()) {
await this.$refouler()
}
this.$forceClose(`${this.actor.name} ${reason} et quitte les Terres médianes !`)
return true
} }
return false
if (ReglesOptionnelles.isUsing("appliquer-fatigue")
? (this.actor.getFatigueRestante() <= this.cumulFatigue)
: (this.actor.getEnduranceActuelle() <= this.cumulFatigue)
) {
this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !");
this.quitterLesTMRInconscient();
return true;
}
if (this.actor.getReveActuel() == 0) {
this._tellToGM("Vos Points de Rêve sont à 0 : vous quittez les Terres médianes !");
this.quitterLesTMRInconscient();
return true;
}
return false;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async quitterLesTMRInconscient() { async $maitriserRencontre() {
await this.refouler();
this.close();
}
/* -------------------------------------------- */
async maitriserRencontre() {
console.log("-> maitriser", this.currentRencontre); console.log("-> maitriser", this.currentRencontre);
await this.actor.deleteRencontreTMRAtPosition() await this.$deleteRencontreTMRAtPosition();
this.updateTokens(); this.updateTokens();
let rencontreData = { let rencontreData = {
@ -471,11 +470,21 @@ export class RdDTMRDialog extends Dialog {
tmr: TMRUtility.getTMR(this._getCoordActor()) tmr: TMRUtility.getTMR(this._getCoordActor())
} }
await this._tentativeMaitrise(rencontreData); await this.$tentativeMaitrise(rencontreData);
}
async $deleteRencontreTMRAtPosition() {
const position = this.actor.getDemiReve()
const rencontreIds = this.actor.itemTypes[ITEM_TYPES.rencontre]
.filter(it => it.system.coord == position)
.map(it => it.id)
if (rencontreIds.length > 0) {
await this.actor.deleteEmbeddedDocuments('Item', rencontreIds)
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _tentativeMaitrise(rencData) { async $tentativeMaitrise(rencData) {
this.rencontreState = 'normal'; this.rencontreState = 'normal';
rencData.reve = this.actor.getReveActuel(); rencData.reve = this.actor.getReveActuel();
@ -484,7 +493,7 @@ export class RdDTMRDialog extends Dialog {
RollDataAjustements.calcul(rencData, this.actor); RollDataAjustements.calcul(rencData, this.actor);
rencData.rolled = rencData.presentCite rencData.rolled = rencData.presentCite
? this._rollPresentCite(rencData) ? this.$rollPresentCite(rencData)
: await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements)); : await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements));
const result = rencData.rolled.isSuccess const result = rencData.rolled.isSuccess
@ -494,38 +503,41 @@ export class RdDTMRDialog extends Dialog {
await RdDRencontre.appliquer(result.effets, this, rencData); await RdDRencontre.appliquer(result.effets, this, rencData);
rencData.poesie = { extrait: result.poesie, reference: result.reference }; rencData.poesie = { extrait: result.poesie, reference: result.reference };
rencData.message = this.formatMessageRencontre(rencData, result.message); rencData.message = this.$formatMessageRencontre(rencData, result.message);
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor), whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencData) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.hbs`, rencData)
}); });
this.updateValuesDisplay(); this.$updateValuesDisplay();
if (this.checkQuitterTMR()) { if (await this.$checkQuitterTMR()) {
return; return;
} }
if (this.rencontreState == 'persistant') { if (this.rencontreState == 'persistant') {
this._nouvelleTentativeMaitrise(rencData); this.$nouvelleTentativeMaitrise(rencData);
} }
else if (!this.isRencontreDeplacement()) { else if (!this.isRencontreDeplacement()) {
this.nettoyerRencontre(); this.$nettoyerRencontre();
} }
} }
_nouvelleTentativeMaitrise(rencData) { $nouvelleTentativeMaitrise(rencData) {
setTimeout(() => { setTimeout(() => {
// TODO: remplacer par une boucle while(this.currentRencontre) ? /**
* TODO: remplacer par une boucle while(this.currentRencontre) ?
* ajouter un moyen d'attendre la saisie de l'utilisateur (jet obligatoire)?
*/
rencData.nbRounds++; rencData.nbRounds++;
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
} }
this._tentativeMaitrise(rencData); this.$tentativeMaitrise(rencData);
this._deleteTmrMessages(rencData.actor, rencData.nbRounds); this.$deleteTmrMessages(rencData.actor, rencData.nbRounds);
}, 2000); }, 2000);
} }
formatMessageRencontre(rencData, template) { $formatMessageRencontre(rencData, template) {
let messageDuree = '' let messageDuree = ''
if (rencData.nbRounds > 1) { if (rencData.nbRounds > 1) {
if (rencData.rolled.isSuccess) { if (rencData.rolled.isSuccess) {
@ -544,7 +556,7 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_rollPresentCite(rencData) { $rollPresentCite(rencData) {
let rolled = RdDResolutionTable.computeChances(rencData.reve, 0); let rolled = RdDResolutionTable.computeChances(rencData.reve, 0);
foundry.utils.mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score }); foundry.utils.mergeObject(rolled, { caracValue: rencData.reve, finalLevel: 0, roll: rolled.score });
RdDResolutionTable.succesRequis(rolled); RdDResolutionTable.succesRequis(rolled);
@ -552,7 +564,7 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_deleteTmrMessages(actor, nbRounds = -1) { $deleteTmrMessages(actor, nbRounds = -1) {
setTimeout(() => { setTimeout(() => {
if (nbRounds < 0) { if (nbRounds < 0) {
ChatUtility.removeChatMessageContaining(`<h4 data-categorie="tmr" data-actor-id="${actor._id}"`); ChatUtility.removeChatMessageContaining(`<h4 data-categorie="tmr" data-actor-id="${actor._id}"`);
@ -571,7 +583,7 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_tellToGM(message) { $tellToGM(message) {
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user.id,
content: message, content: message,
@ -580,7 +592,7 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_tellToUserAndGM(message) { $tellToUserAndGM(message) {
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user.id,
content: message, content: message,
@ -602,7 +614,7 @@ export class RdDTMRDialog extends Dialog {
if (this.currentRencontre) { if (this.currentRencontre) {
if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)) { if (this.rencontresExistantes.find(it => it.id == this.currentRencontre.id)) {
// rencontre en attente suite à dérobade // rencontre en attente suite à dérobade
await this.maitriserRencontre(); await this.$maitriserRencontre();
} }
else { else {
const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr); const dialog = new RdDTMRRencontreDialog(this.actor, this.currentRencontre, tmr);
@ -649,7 +661,7 @@ export class RdDTMRDialog extends Dialog {
tmr: tmr, tmr: tmr,
presentCite: presentCite presentCite: presentCite
}; };
await this._tentativeMaitrise(rencontreData); await this.$tentativeMaitrise(rencontreData);
this.postRencontre(tmr); this.postRencontre(tmr);
} }
@ -725,10 +737,10 @@ export class RdDTMRDialog extends Dialog {
rollData.poesie = await Poetique.getExtrait(); rollData.poesie = await Poetique.getExtrait();
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor), 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) { if (rollData.rolled.isEchec) {
await this.close(); await this.$forceClose(`n'a pas maîtrisé la case ${rollData.tmr.label} et quitte les terres médianes`)
} }
await this.souffleSiEchecTotal(rollData); await this.souffleSiEchecTotal(rollData);
} }
@ -783,7 +795,7 @@ export class RdDTMRDialog extends Dialog {
onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), onConqueteReussie: r => EffetsDraconiques.fermetureCites.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
onConqueteEchec: r => { onConqueteEchec: r => {
this.souffleSiEchecTotal(rollData); this.souffleSiEchecTotal(rollData);
this.close() this.$forceClose(`${this.actor.name} n'a pas maîtrisé la ${tmr.label}, et quitte les TMR.`)
}, },
canClose: false canClose: false
}); });
@ -798,7 +810,7 @@ export class RdDTMRDialog extends Dialog {
onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), onConqueteReussie: r => EffetsDraconiques.periple.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
onConqueteEchec: r => { onConqueteEchec: r => {
this.souffleSiEchecTotal(rollData); this.souffleSiEchecTotal(rollData);
this.close() this.$forceClose(`${this.actor.name} n'a pas purifié la ${tmr.label}, et quitte les TMR.`)
}, },
canClose: false canClose: false
}); });
@ -812,7 +824,7 @@ export class RdDTMRDialog extends Dialog {
difficulte: -7, difficulte: -7,
action: 'Conquérir', action: 'Conquérir',
onConqueteReussie: r => EffetsDraconiques.conquete.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)), onConqueteReussie: r => EffetsDraconiques.conquete.onVisiteSupprimer(r.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)),
onConqueteEchec: r => this.close(), onConqueteEchec: r => this.$forceClose(`${this.actor.name} n'a pas conquis la case ${tmr.label}, et quitte les TMR.`),
canClose: false canClose: false
}); });
} }
@ -842,7 +854,7 @@ export class RdDTMRDialog extends Dialog {
rollData.poesie = await Poetique.getExtrait(); rollData.poesie = await Poetique.getExtrait();
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor), 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) { if (rollData.rolled.isEchec) {
options.onConqueteEchec(rollData, options.effetDraconique); options.onConqueteEchec(rollData, options.effetDraconique);
@ -858,7 +870,7 @@ export class RdDTMRDialog extends Dialog {
rollData.isTMRCache = rollData.actor.isTMRCache(); rollData.isTMRCache = rollData.actor.isTMRCache();
const dialog = await RdDRoll.create(this.actor, rollData, 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, name: rollData.maitrise.verbe, label: rollData.maitrise.action,
@ -908,8 +920,8 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
lancerSortEnReserve(coord, sortId) { lancerSortEnReserve(coord, sortId) {
let sorts = this.getSortsReserve(coord); const sort = this.getSortsReserve(coord)
let sort = sorts.find(it => it.id == sortId); .find(it => it.id == sortId);
if (sort) { if (sort) {
this.processSortReserve(sort); this.processSortReserve(sort);
} else { } else {
@ -923,19 +935,15 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async processSortReserve(sortReserve) { async processSortReserve(sortReserve) {
await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]); await this.actor.deleteEmbeddedDocuments('Item', [sortReserve.id]);
console.log("declencheSortEnReserve", sortReserve); console.log("declencheSortEnReserve", sortReserve)
const heureCible = RdDTimestamp.definition(sortReserve.system.heurecible).label; const sort = sortReserve.system.sortid ? this.actor.items.get(sortReserve.system.sortid) : undefined
this._tellToUserAndGM(`Vous avez déclenché const message = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-lancement-sortreserve.hbs`,
${sortReserve.system.echectotal ? "<strong>l'échec total!</strong>" : "le sort"} { sortReserve, sort })
en réserve <strong>${sortReserve.name}</strong> await this.$forceClose(message)
avec ${sortReserve.system.ptreve} points de Rêve
en ${sortReserve.system.coord} (${TMRUtility.getTMRLabel(sortReserve.system.coord)}).
L'heure ciblée est ${heureCible}`);
this.close();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
nettoyerRencontre() { $nettoyerRencontre() {
// Suppression des dessins des zones possibles // Suppression des dessins des zones possibles
this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic)) this.currentRencontre?.graphics?.forEach(graphic => this.pixiTMR.removeGraphic(graphic))
// Nettoyage de la structureet de l'état // Nettoyage de la structureet de l'état
@ -1022,7 +1030,7 @@ export class RdDTMRDialog extends Dialog {
console.log("STATUS :", this.rencontreState, this.currentRencontre); console.log("STATUS :", this.rencontreState, this.currentRencontre);
} }
this.checkQuitterTMR(); await this.$checkQuitterTMR();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -1055,13 +1063,13 @@ export class RdDTMRDialog extends Dialog {
*/ */
this.notifierResonanceSigneDraconique(targetCoord); this.notifierResonanceSigneDraconique(targetCoord);
await this.actor.rollUnSort(targetCoord); await this.actor.rollUnSort(targetCoord);
this.nettoyerRencontre(); this.$nettoyerRencontre();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
externalRefresh() { externalRefresh() {
this.createPixiSprites(); this.createPixiSprites();
this.updateValuesDisplay(); this.$updateValuesDisplay();
this.updateTokens(); this.updateTokens();
console.log("TMR REFRESHED !!!"); console.log("TMR REFRESHED !!!");
} }
@ -1072,7 +1080,7 @@ export class RdDTMRDialog extends Dialog {
return this.forceTMRContinueAction() return this.forceTMRContinueAction()
} }
if (this.currentRencontre != 'normal') { if (this.currentRencontre != 'normal') {
this.nettoyerRencontre(); this.$nettoyerRencontre();
} }
let tmr = TMRUtility.getTMR(targetCoord); let tmr = TMRUtility.getTMR(targetCoord);
// Gestion cases spéciales type Trou noir, etc // Gestion cases spéciales type Trou noir, etc
@ -1084,7 +1092,7 @@ export class RdDTMRDialog extends Dialog {
if (ReglesOptionnelles.isUsing("appliquer-fatigue")) { if (ReglesOptionnelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
} }
this.updateValuesDisplay(); this.$updateValuesDisplay();
this.actor.notifyRefreshTMR(); this.actor.notifyRefreshTMR();
if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/... if (deplacementType == 'normal') { // Pas de rencontres après un saut de type passeur/changeur/...
@ -1099,7 +1107,7 @@ export class RdDTMRDialog extends Dialog {
if (!this.viewOnly && this.actor.isResonanceSigneDraconique(coord)) { if (!this.viewOnly && this.actor.isResonanceSigneDraconique(coord)) {
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor), 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(), alias: this.actor.getAlias(),
typeTMR: TMRUtility.getTMRType(coord) typeTMR: TMRUtility.getTMRType(coord)
}) })

View File

@ -52,7 +52,7 @@ export class RdDTokenHud {
}; };
const controlIconCombat = html.find('.control-icon[data-action=combat]'); const controlIconCombat = html.find('.control-icon[data-action=combat]');
await RdDTokenHud._configureSubMenu(controlIconCombat, 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, hudData,
(event) => { (event) => {
let initCommand = event.currentTarget.attributes['data-command']?.value; let initCommand = event.currentTarget.attributes['data-command']?.value;
@ -70,7 +70,7 @@ export class RdDTokenHud {
static async addExtensionHudCombat(html, combatant, token, actions) { static async addExtensionHudCombat(html, combatant, token, actions) {
const hudData = { combatant, token, actions, commandes: [] }; const hudData = { combatant, token, actions, commandes: [] };
const controlIconTarget = html.find('.control-icon[data-action=target]'); 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) => { (event) => {
const actionIndex = event.currentTarget.attributes['data-action-index']?.value; const actionIndex = event.currentTarget.attributes['data-action-index']?.value;
const action = hudData.actions[actionIndex]; const action = hudData.actions[actionIndex];

View File

@ -19,10 +19,12 @@ import { RdDEmpoignade } from "./rdd-empoignade.js";
import { ExperienceLog } from "./actor/experience-log.js"; import { ExperienceLog } from "./actor/experience-log.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { APP_ASTROLOGIE_REFRESH } from "./sommeil/app-astrologie.js"; 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 { RdDBaseActor } from "./actor/base-actor.js";
import { RdDCarac } from "./rdd-carac.js"; import { RdDCarac } from "./rdd-carac.js";
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.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 // This table starts at 0 -> niveau -10
@ -107,102 +109,105 @@ export class RdDUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async preloadHandlebarsTemplates() { static preloadHandlebarsTemplates() {
const templatePaths = [ const templatePaths = [
//Character Sheets //Character Sheets
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-sheet.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.hbs',
// sous-parties de feuilles de personnages // sous-parties de feuilles de personnages
'systems/foundryvtt-reve-de-dragon/templates/actor/header-buttons.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/item-action-controls.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/header-etat.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/header-buttons.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/header-etat.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-creature.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/header-effects.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/header-compteurs-entitee.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/header-hautreve.html', '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/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/armures.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/carac-main.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-entitee.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/carac-entitee.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/competence.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/competence.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/combat.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/combat.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/blessures.html', '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/blessure.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/maladies-poisons.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/possessions.html', '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/resonances.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/taches.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/jeus.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/jeux.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.html',
'systems/foundryvtt-reve-de-dragon/templates/actor/non-haut-revant.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/haut-revant.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queues.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queue.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-queue.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-souffles.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/dragon-tetes.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-signes-draconiques.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/hr-signes-draconiques.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-rencontres.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/hr-rencontres.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts-reserve.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/hr-sorts-reserve.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-meditations.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/hr-meditations.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/hr-casestmr.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/hr-casetmrs.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/xp-journal.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/xp-journal.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/editor-notes-mj.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/editor-notes-mj.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.hbs',
"systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-monnaie.html", "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-animaux.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-suivants.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/liens-vehicules.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.html', 'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.hbs',
//Items //Items
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs', '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/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/icon-arme-broken.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/temporel.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-inventaire.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.html', 'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.html', 'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item-queue-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/header-item.hbs',
'systems/foundryvtt-reve-de-dragon/templates/header-item.html',
'systems/foundryvtt-reve-de-dragon/templates/item/queue-sheet.hbs',
// partial enums // partial enums
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-caracteristiques.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-categories.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-categories.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-ingredient.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html', 'systems/foundryvtt-reve-de-dragon/templates/item/enum-categorie-alchimie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.html', 'systems/foundryvtt-reve-de-dragon/templates/item/enum-etat-alchimie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-queue.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-competence.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-heures.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-draconic.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-heures.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-mortalite.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-mortalite.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-periode.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-periode.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-effet.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-tmr-type.hbs',
// Partials // 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/chat-effet-tendre-moment.hbs',
'systems/foundryvtt-reve-de-dragon/templates/coeur/afficher-coeur.hbs', 'systems/foundryvtt-reve-de-dragon/templates/coeur/afficher-coeur.hbs',
'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs', 'systems/foundryvtt-reve-de-dragon/templates/tirage/liste-resultats-recherche.hbs',
@ -214,56 +219,55 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs', 'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs', 'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.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-overflow.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html', '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-astrologique.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-coeur.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-competences.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffFixe.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffFixe.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffCondition.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffCondition.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-forcer.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-item-hautrevant.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-item-hautrevant.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-item-frequence.html', 'systems/foundryvtt-reve-de-dragon/templates/partial-item-frequence.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-item-description.html', '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/roll/explain.hbs',
'systems/foundryvtt-reve-de-dragon/templates/resolution-table.html', 'systems/foundryvtt-reve-de-dragon/templates/resolution-table.hbs',
// Dialogs // Dialogs
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.hbs',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-competence.hbs',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.hbs',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-sort.hbs',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.hbs',
'systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-validation-encaissement.hbs',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.hbs',
'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.hbs',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html', '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/sommeil-actor-moral.hbs',
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-gardien.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-joueur.hbs',
'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-theme.hbs', 'systems/foundryvtt-reve-de-dragon/templates/sommeil/astrologie-theme.hbs',
// HUD // HUD
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.hbs',
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.hbs',
// messages tchat // messages tchat
'systems/foundryvtt-reve-de-dragon/templates/chat-infojet.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-infojet.hbs',
'systems/foundryvtt-reve-de-dragon/templates/chat-description.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-description.hbs',
'systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-info-appel-au-moral.hbs',
'systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.html', '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-acteur.hbs',
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-sante.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-competence-xp.hbs',
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.hbs',
'systems/foundryvtt-reve-de-dragon/templates/chat-potionenchantee-chateaudormant.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-fabriquer-potion-base.hbs',
'systems/foundryvtt-reve-de-dragon/templates/chat-fabriquer-potion-base.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.hbs'
'systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html'
]; ];
// foundry et options // foundry et options
Handlebars.registerHelper('RDD_CONFIG', path => RDD_CONFIG[path]) Handlebars.registerHelper('RDD_CONFIG', path => RDD_CONFIG[path])
Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name)); Handlebars.registerHelper('linkCompendium', (pack, id, name) => RdDUtility.linkCompendium(pack, id, name));
@ -278,7 +282,7 @@ export class RdDUtility {
const html = options.fn(this); const html = options.fn(this);
return html.replace(rgx, "$& selected"); return html.replace(rgx, "$& selected");
}) })
// logic // logic
Handlebars.registerHelper('either', (a, b) => a ?? b); Handlebars.registerHelper('either', (a, b) => a ?? b);
// string manipulation // string manipulation
@ -294,9 +298,9 @@ export class RdDUtility {
// math // math
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1))); Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
Handlebars.registerHelper('repeat', function(n, block) { Handlebars.registerHelper('repeat', function (n, block) {
let accum = ''; let accum = '';
for(let i = 0; i < n; ++i){ for (let i = 0; i < n; ++i) {
accum += block.fn(i) accum += block.fn(i)
} }
return accum return accum
@ -314,6 +318,7 @@ export class RdDUtility {
// gestion des dates et heures // gestion des dates et heures
Handlebars.registerHelper('timestamp-imgSigneHeure', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigneHeure(heure)) }); Handlebars.registerHelper('timestamp-imgSigneHeure', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigneHeure(heure)) });
Handlebars.registerHelper('timestamp-imgSigne', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigne(heure)) }); Handlebars.registerHelper('timestamp-imgSigne', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigne(heure)) });
Handlebars.registerHelper('timestamp-definition', (heure) => RdDTimestamp.definition(heure))
Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier()); Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier());
Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree()); Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree());
Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode()); Handlebars.registerHelper('timestamp-formulesPeriode', () => RdDTimestamp.formulesPeriode());
@ -334,6 +339,9 @@ export class RdDUtility {
Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field)); Handlebars.registerHelper('isFieldInventaireModifiable', (type, field) => RdDItem.isFieldInventaireModifiable(type, field));
// Items // Items
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field)); 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 // TMRs
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord)); Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
@ -341,7 +349,7 @@ export class RdDUtility {
Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type)); Handlebars.registerHelper('typeTmr-name', type => TMRUtility.typeTmrName(type));
Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord)); Handlebars.registerHelper('effetRencontre-name', coord => TMRUtility.typeTmrName(coord));
await loadTemplates(templatePaths); loadTemplates(templatePaths);
} }
static getItem(itemId, actorId = undefined) { static getItem(itemId, actorId = undefined) {
@ -435,8 +443,8 @@ export class RdDUtility {
}; };
if (!optionsArbre.templateItem) { if (!optionsArbre.templateItem) {
optionsArbre.templateItem = item.parent?.type == 'commerce' optionsArbre.templateItem = item.parent?.type == 'commerce'
? "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.html" ? "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.hbs"
: "systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.html"; : "systems/foundryvtt-reve-de-dragon/templates/actor/inventaire-item.hbs";
} }
item.niveau = optionsArbre.profondeur; item.niveau = optionsArbre.profondeur;
} }
@ -464,13 +472,38 @@ export class RdDUtility {
return ligneObjet; 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) { static buildInventaireConteneur(actorId, itemId, options) {
const actor = game.actors.get(actorId) const actor = game.actors.get(actorId)
const item = actor?.items.get(itemId) const item = actor?.items.get(itemId)
if (item) { if (item?.type == ITEM_TYPES.conteneur) {
return RdDUtility.buildContenuConteneur(item, options, { ouvert: true, profondeur: 1 }); 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))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -872,7 +905,7 @@ export class RdDUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async confirmActorItemDelete(sheet, item, htmlToDelete) { static async confirmActorItemDelete(item, actor) {
const itemId = item.id; const itemId = item.id;
const confirmationSuppression = { const confirmationSuppression = {
settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(), settingConfirmer: "confirmation-supprimer-" + item.getItemGroup(),
@ -881,8 +914,7 @@ export class RdDUtility {
buttonLabel: "Supprimer", buttonLabel: "Supprimer",
onAction: () => { onAction: () => {
console.log('Delete : ', itemId); console.log('Delete : ', itemId);
sheet.actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false }); actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false });
RdDUtility.slideOnDelete(sheet, htmlToDelete);
} }
}; };
if (item.isConteneurNonVide()) { if (item.isConteneurNonVide()) {
@ -895,8 +927,7 @@ export class RdDUtility {
label: "Supprimer conteneur et contenu", label: "Supprimer conteneur et contenu",
callback: () => { callback: () => {
console.log("Delete : ", itemId); console.log("Delete : ", itemId);
sheet.actor.deleteAllConteneur(itemId, { renderSheet: false }); actor.deleteAllConteneur(itemId, { renderSheet: false });
RdDUtility.slideOnDelete(sheet, htmlToDelete);
} }
} }
}); });
@ -934,8 +965,8 @@ export class RdDUtility {
} }
/*-------------------------------------------- */ /*-------------------------------------------- */
static checkThanatosXP(compName) { static checkThanatosXP(item) {
if (compName.includes('Thanatos')) { 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."; 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({ ChatMessage.create({
whisper: ChatUtility.getUserAndGMs(), whisper: ChatUtility.getUserAndGMs(),

View File

@ -112,7 +112,7 @@ export class StatusEffects extends FormApplication {
const options = super.defaultOptions; const options = super.defaultOptions;
foundry.utils.mergeObject(options, { foundry.utils.mergeObject(options, {
id: "status-effects", 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, height: 800,
width: 350, width: 350,
minimizable: false, minimizable: false,

View File

@ -157,7 +157,7 @@ export class SystemCompendiums extends FormApplication {
const options = super.defaultOptions; const options = super.defaultOptions;
foundry.utils.mergeObject(options, { foundry.utils.mergeObject(options, {
id: "system-compendiums", id: "system-compendiums",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/system-compendiums.html", template: "systems/foundryvtt-reve-de-dragon/templates/settings/system-compendiums.hbs",
height: 'fit-content', height: 'fit-content',
width: 600, width: 600,
minimizable: false, minimizable: false,

View File

@ -15,7 +15,7 @@ export class DialogRepos extends Dialog {
"heures": 4 "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); const dialog = new DialogRepos(html, actor);
dialog.render(true); dialog.render(true);
} }

View File

@ -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) new DialogStress(dialogData, html)
.render(true); .render(true);
} }

View File

@ -334,6 +334,10 @@ export class RdDTimestamp {
return this.nouvelleHeure().addHeures((12 + heure - this.heure) % 12); return this.nouvelleHeure().addHeures((12 + heure - this.heure) % 12);
} }
debutJournee() {
return RdDTimestamp.timestamp(this.annee, this.mois, this.jour)
}
async appliquerDuree(duree, actor) { async appliquerDuree(duree, actor) {
const formule = FORMULES_DUREE.find(it => it.code == duree) ?? FORMULES_DUREE.find(it => it.code == ""); const formule = FORMULES_DUREE.find(it => it.code == duree) ?? FORMULES_DUREE.find(it => it.code == "");
return await formule.calcul(this, actor); return await formule.calcul(this, actor);

View File

@ -26,7 +26,7 @@ export class TMRRencontres {
* @param {*} forcedRoll * @param {*} forcedRoll
*/ */
async rollRencontre(terrain, forcedRoll) { async rollRencontre(terrain, forcedRoll) {
const tmrType = TMRUtility.findTMRLike(terrain)?.type const tmrType = TMRUtility.findTMRLike(terrain, { inclusMauvaise: true })?.type
if (tmrType == undefined) { if (tmrType == undefined) {
return undefined; return undefined;
} }
@ -38,7 +38,7 @@ export class TMRRencontres {
const frequence = it => it.system.frequence[tmrType]; const frequence = it => it.system.frequence[tmrType];
const row = await this.table.getRandom(frequence, filtreMauvaise, forcedRoll); const row = await this.table.getRandom(frequence, filtreMauvaise, forcedRoll);
if (row) { if (row) {
await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item', {showSource: false}); await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item', { showSource: false });
} }
return row?.document; return row?.document;

View File

@ -22,7 +22,7 @@ export const TMRType = {
export const FLEUVE_COORD = 'Fleuve' export const FLEUVE_COORD = 'Fleuve'
const TMRMapping = { 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" }, A1: { type: TMRType.cite.type, label: "Cité Vide" },
B1: { type: TMRType.plaines.type, label: "Plaines dAssorh" }, B1: { type: TMRType.plaines.type, label: "Plaines dAssorh" },
C1: { type: TMRType.necropole.type, label: "Nécropole de Kroak" }, C1: { type: TMRType.necropole.type, label: "Nécropole de Kroak" },
@ -281,18 +281,18 @@ export class TMRUtility {
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label; return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label;
} }
static findTMRLike(type, options = { inclusMauvaise: true }) { static findTMRLike(type, options = { inclusMauvaise: false }) {
const choix = [...Object.values(TMRType)] const choix = [...Object.values(TMRType)]
if (options.inclusMauvaise) { if (options.inclusMauvaise) {
choix.push({ name: 'Mauvaise', type: 'mauvaise'}); choix.push({ name: 'Mauvaise', type: 'mauvaise'});
} }
const selection = Misc.findAllLike(type, choix) const selection = Misc.findAllLike(type, choix)
if (selection.length == 0) { 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 return undefined
} }
if (selection.length > 1) { 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 undefined;
} }
return selection[0] return selection[0]
@ -357,7 +357,7 @@ export class TMRUtility {
} }
static filterTMR(filter) { static filterTMR(filter) {
return Object.values(TMRMapping).filter(filter); return Object.values(TMRMapping).filter(it => !it.generique && filter(it))
} }
static getCasesType(type) { static getCasesType(type) {

View File

@ -1,4 +1,4 @@
import { ITEM_TYPES } from "../item.js"; import { ITEM_TYPES } from "../constants.js";
import { TMRUtility } from "../tmr-utility.js"; import { TMRUtility } from "../tmr-utility.js";
import { PixiTMR } from "./pixi-tmr.js"; import { PixiTMR } from "./pixi-tmr.js";

View File

@ -18,7 +18,7 @@ import { Periple } from "./periple.js";
import { UrgenceDraconique } from "./urgence-draconique.js"; import { UrgenceDraconique } from "./urgence-draconique.js";
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { AugmentationSeuil } from "./augmentation-seuil.js"; import { AugmentationSeuil } from "./augmentation-seuil.js";
import { ITEM_TYPES } from "../item.js"; import { ITEM_TYPES } from "../constants.js";
export class EffetsDraconiques { export class EffetsDraconiques {
static carteTmr = new CarteTmr(); static carteTmr = new CarteTmr();

View File

@ -113,7 +113,7 @@ export class EffetsRencontre {
}) })
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getOwners(context.actor), whisper: ChatUtility.getOwners(context.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.html`, context) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.hbs`, context)
}); });
} }
@ -128,7 +128,7 @@ export class EffetsRencontre {
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getOwners(context.actor), whisper: ChatUtility.getOwners(context.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.html`, context) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.hbs`, context)
}); });
} }

View File

@ -5,7 +5,7 @@ import { RdDRollTables } from "../rdd-rolltables.js";
import { TMRUtility } from "../tmr-utility.js"; import { TMRUtility } from "../tmr-utility.js";
import { tmrTokenZIndex } from "../tmr-constants.js"; import { tmrTokenZIndex } from "../tmr-constants.js";
import { Draconique } from "./draconique.js"; import { Draconique } from "./draconique.js";
import { ITEM_TYPES } from "../item.js"; import { ITEM_TYPES } from "../constants.js";
import { TMRAnimations } from "./animation.js"; import { TMRAnimations } from "./animation.js";
export class UrgenceDraconique extends Draconique { export class UrgenceDraconique extends Draconique {

View File

@ -1,4 +1,4 @@
import { ITEM_TYPES } from "../item.js" import { ITEM_TYPES } from "../constants.js"
import { RdDItemCompetence } from "../item-competence.js" import { RdDItemCompetence } from "../item-competence.js"
import { ChatUtility } from "../chat-utility.js" import { ChatUtility } from "../chat-utility.js"
import { Misc } from "../misc.js" import { Misc } from "../misc.js"

View File

@ -1,6 +1,7 @@
{ {
"scripts": { "scripts": {
"build": "npx vite build", "build": "npx vite build",
"run": "npx vite serve",
"packCompendiumsToDist": "node ./tools/packCompendiumsToDist.mjs", "packCompendiumsToDist": "node ./tools/packCompendiumsToDist.mjs",
"packCompendiumsToPublic": "node ./tools/packCompendiumsToPublic.mjs", "packCompendiumsToPublic": "node ./tools/packCompendiumsToPublic.mjs",
"unpackCompendiumsFromPublic": "node ./tools/unpackCompendiumsFromPublic.mjs" "unpackCompendiumsFromPublic": "node ./tools/unpackCompendiumsFromPublic.mjs"

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