Compare commits

...

82 Commits

Author SHA1 Message Date
080d05d2cd Merge pull request 'Version 12.0.2' (#713) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #713
2024-10-06 17:03:41 +02:00
f8f889e9f9 Jets de vie/endurance/rêve actuel 2024-10-05 15:13:29 +02:00
ad80802af6 Remove log 2024-10-05 14:40:14 +02:00
0f7b9baf51 Amélioration liste de compétences 2024-10-05 14:39:56 +02:00
b866c95ebd Correction de la protection 2024-10-05 12:57:02 +02:00
689e287ac7 Bouton d'export si mode avancé 2024-10-05 12:50:29 +02:00
40b0d7e6dc Jets de carac/compétences sur feuille encart 2024-10-05 12:41:28 +02:00
d439d73636 Version 12.0.12 2024-10-05 00:42:32 +02:00
e91eea532d Ajout feuille encart
Feuille de PNJ au format des encarts Scriptarium.
Aucune possibilité de jets de dés pour l'instant.
2024-10-05 00:42:27 +02:00
f116003d6f Fix: vente depuis les compendiums/Objets
On peut de nouveau vendre des items sans propriétaire,
depuis les compendiums ou depuis l'onglet des Objets
2024-10-05 00:39:50 +02:00
c3a44665c5 Load handlebars dans app-personnage-aleatoire 2024-10-05 00:39:50 +02:00
40b57517d8 Merge pull request '12.0.11' (#712) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #712
2024-10-02 07:37:42 +02:00
e04586ba44 Ajout de génération aléatoire de description
Ajout d'un bouton pour générer aléatoirement les éléments de description:

- nom (pour le MJ seul)
- sexe
- age
- main directrice
- cheveux, yeux
- heure de naissance
- taille et poids (selon la caractéristique Taille)
2024-10-02 00:46:11 +02:00
611acd4d44 Version 12.0.11 2024-10-01 02:07:42 +02:00
9b37533bdf Correction nom classe (inutile) 2024-10-01 02:00:42 +02:00
50d923061b Ajout d'un champ pour les métiers 2024-10-01 01:59:51 +02:00
e89a8ba232 Ajout background system pour Foundry 2024-10-01 01:58:06 +02:00
b8f236fa97 Fix esquive avec armure
- ajout de champ sans armure/avec armure
- calcul correct avec armure
2024-09-28 17:45:31 +02:00
74b184aa32 Use windows-1252 encoding 2024-09-28 17:44:28 +02:00
9c17f85fa8 Fix: détermination niveau de base
simplification: déterminer les catégories en fonction du type d'Item
2024-09-27 22:40:08 +02:00
599fdc752d Fix naming + charset 2024-09-27 13:44:56 +02:00
fa890491e5 Fix wrong object import 2024-09-27 13:41:30 +02:00
80435b6bca Fix wrong object import 2024-09-27 13:21:42 +02:00
1a476bd5bc Fix wrong object import 2024-09-27 13:20:29 +02:00
8d6c4565a9 Merge pull request 'v12.0.9 - Le scriptorium d'Astrobazzarh' (#711) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #711
2024-09-27 10:16:54 +02:00
6819f1c2f5 Correction du mapping
- gestion des armes une/deux mains/lancées
- dommages des armes une/deux mains
- correction de la voie de draconic
- correction des bonus de cases
- correction des retours à la ligne
2024-09-27 02:36:54 +02:00
43607afc12 Correction du parser des bonus de case 2024-09-27 02:33:01 +02:00
538cf5bdbf Extraction des calculs de dommages
Préparation pour le Mapping des armes
2024-09-27 02:32:13 +02:00
75507f3eca Fix deprecation 2024-09-27 02:30:48 +02:00
a622814295 Amélioration message tchat de tirage 2024-09-26 00:55:37 +02:00
2aa8fcb980 Amélioration export voies draconiques 2024-09-26 00:55:08 +02:00
a65326d658 Version 12.0.9
Export format csv
2024-09-25 23:43:04 +02:00
b6a203b82a Export vers un fichier csv 2024-09-25 23:43:04 +02:00
7e8f642d87 Export csv pour Scriptarium
Activable dans les options avancées du système
Un menu contextuel permet d'écrire dans les logs
2024-09-25 23:43:04 +02:00
91be2761f5 Passage html -> hbs 2024-09-25 23:43:03 +02:00
2ac39e3428 Ajout de la taille (manquante) 2024-09-25 23:43:03 +02:00
a162001ba4 Cleanup 2024-09-25 23:43:03 +02:00
52e1f9dfbf Rename TYPES en ITEM_TYPES
Pour ajouter les ACTOR_TYPES
2024-09-25 23:43:03 +02:00
c586a90690 Merge pull request 'Version 12.0.8 - La quincaillerie d'Astrobazzarh' (#710) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #710
2024-09-06 15:14:23 +02:00
16e40b0ed8 12.0.8 - La quincaillerie d'Astrobazzarh
- le propriétaire est indiqué dans les feuilles d'équipements/
   compétences/...
- Ecaille d'efficacité
  - l'écaille d'efficacité est prise en compte même si on n'utilise
     pas le ciblage en combat
  - l'écaille d'efficacité est prise en compte pour l'initiative
- Corrections
  - l'état général est pris en compte pour les initiatives
  - le tooltip de l'initiative affiche correctement l'initiative
2024-09-06 00:49:39 +02:00
427a950954 L'initiative utilise l'écaille d'efficacité 2024-09-06 00:47:32 +02:00
a7b20bdd35 Ecaille d'efficacité sans cible
L'écaille d'efficacité est prise en compte si on n'utilise pas
l'automatisation de combat avec une cible
2024-09-06 00:45:49 +02:00
3b18e0b919 Ajout du propriétaire sur les Items 2024-09-05 23:54:02 +02:00
ff8a5d7ba3 Fix tooltip initiative 2024-09-05 23:54:02 +02:00
3aa8c0f0af Fix weapon in the HUD 2024-09-01 20:39:25 +02:00
8d9f09c18c Fix warnings 2024-09-01 20:22:52 +02:00
9d654246c2 Merge pull request '12.0.7 - La propriété d'Astrobazzarh' (#709) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #709
2024-09-01 20:21:04 +02:00
111fac2b2d Amélioration dialogue voyage
- le changement de terrain change l'affichage de compétences
- le total de fatigue est affiché (ajustement + base)
2024-09-01 20:13:09 +02:00
3e99265125 Version 12.0.7 - La propriété d'Astrobazzarh
- correction des opérations faites à la création d'un Item:
  - la durée des queues/rencontres/souffles
  - les effets draconiques d'un souffle/queue
  - mise à jour des points de tâche des blessures lors des soins
- pas d'expérience sur les particulières quand aucun MJ n'est connecté
- Le drag&drop d'un acteur depuis la liste des acteurs sur la fiche
  d'une entité incarnée permet d'accorder le personnage
- Les messages pour résister aux possessions/conjuration sont envoyées
  au défenseur
- Les messages pour résister aux empoignades sont envoyées au défenseur
2024-08-31 00:59:26 +02:00
28878b74fc Fix: demandes au défenseur
Les demandes de résistance pour les possessions sont envoyées au
défenseur

Les demlandes de défense contre une empoignade dont envoyées au
 défenseur
2024-08-31 00:58:58 +02:00
ba8276ef37 Possibilité d'accorder un personnage
Le drag&drop d'un acteur depuis la liste des acteurs sur la fiche
d'une entité incarnée permet d'accorder le personnage
2024-08-31 00:21:24 +02:00
b9e8c24461 Pas d'expérience si le MJ n'est pas connecté
Pour éviter les jets de dés abusifs quand le MJ n'est pas là,
les réussites particulières ne rapportent plus d'expérience
lorsque le MJ n'est pas connecté
2024-08-30 23:56:20 +02:00
8754ea9f5f Fix hook sur creation
Correction des Hooks qui font des calculs à la création d'un item.

- document instanceof Document est false pour un Actor
- le tri des users ne marche pas sur foundry 12
- mise à jour des blessures lors des soins

Correction de la détermination du MJ connecté permettant de nouveau:
- jets de dés quand aucun MJ n'est connecté
- affichage de l'horloge
2024-08-30 23:54:06 +02:00
f56ddb4a1b Merge pull request 'Version 12.0.6 - Le bazar d'Astrobazzarh' (#708) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #708
2024-08-01 07:19:12 +02:00
e80dbc7332 Version 12.0.6 2024-08-01 01:19:54 +02:00
4c82d85e6a Fix: visibilité des tirages dans les compendium
Les macros /tirer affichaient le résultat pour tous les joueurs
2024-08-01 01:19:07 +02:00
538058ecc6 Fix: cas d'un objet est un conteneur fantôme
Lors d'une partie, la feuille d'un personnage a été bloquée.
Après debug, il semble que l'objet a eu le flag estContenu=true
sans être contenu.

En regardant le json, il semble que des Item "objet" se sont retrouvés
avec un champ "contenu", et que l'arbre des contenant a été cassé.

Du coup: l'ajout dans un conteneur est maintenant "sécurisé" pour
éviter l'accident. si on essaie d'ajouter dans un Item non conteneur,
on positionne estContenu à false, et on corrige si possible le "contenu"
de la cible, qui ne devrait pas être là.
2024-08-01 01:17:36 +02:00
70e42ea631 Merge pull request 'Restaurer la compatibilité v11' (#707) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #707
2024-07-15 17:17:29 +02:00
15525ef8cc Restaurer la compatibilité v11 2024-07-10 23:17:27 +02:00
5a4ef6da7e Merge pull request '12.0.5 - Les mauvais jours d'Astrobazzarh' (#706) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #706
2024-07-08 22:14:15 +02:00
ab698b2124 Version 12.0.5 - Les mauvais jours d'Astrobazzarh
- Fix: on peut de nouveau ouvrir l'édition de calendrier
- Fix: on ne peut plus ouvrir plusieurs fenêtres de lancer de sort
- Fix: Failed to execute 'getComputedStyle' on 'Window'
2024-07-04 21:30:19 +02:00
4cc6e86d79 Fix: Failed to execute 'getComputedStyle'
Dans certains cas (ouverture de fenêtre de lancer de sort),
le bringToTop était appelé alors que la fenêtre n'était pas prête
2024-07-04 21:23:29 +02:00
8f3d56a830 Une seule fenêtres de lancer de sort à la fois
On ne peut plus ouvrir de fenêtre de lancer de sort quand une
fenêtre est déjà ouverte
2024-07-04 21:23:29 +02:00
8561e3f8bc Securité: limiter les cleanupConteneurs
Dans certains cas mal identifiés, on pouvait avoir un problème de droits
sur l'acteur, quand plusieurs joueurs accédaient en même temps à
l'équipement porté par une mule, par exemple
2024-07-04 21:23:29 +02:00
f207cb7325 Fix: Fenêtre d'édition du calendrier
Ajout d'un helper Handlebars pour accéder à l'objet RDD_CONFIG
sans avoir besoin de l'ajouter dans les données pour rendu du template
2024-07-04 21:23:28 +02:00
b9e911a588 Merge pull request '## 12.0.4 - La plaie d'Astrobazzarh' (#705) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #705
2024-07-03 21:47:11 +02:00
92e9be8b02 Version 12.0.4 2024-07-03 02:35:23 +02:00
50a86e751d Fix: warnings deprecated v12 2024-07-02 23:37:50 +02:00
1725d4c17b Fix: impossible de faire l'encaissement
Echec lors des test de permission d'utilisateur
2024-07-02 23:36:52 +02:00
3e33053ed4 Merge pull request '12.0.3 - L'hémorragie d'Astrobazzarh' (#704) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #704
2024-07-01 22:21:26 +02:00
baa3729568 Version 12.0.3 2024-06-29 00:26:12 +02:00
99f29cb95b Fix confirmation de suppression
Lors de la suppression, la demande de confirmation était toujours
faite, même si on indiquait de ne plus demander
2024-06-29 00:12:31 +02:00
7d19860f5f Fix ouverture des Items avec rareté
La sélection des raretés ne fonctionnait plus, la liste des
raretés n'étant pas disponible configuration n'étant
pas disponible dans les données des Items.
2024-06-29 00:12:31 +02:00
40987149cc Fix Ouvertures impossibles
Le contexte des constructeurs est partagé entre Actor et Items,
il faut donc enlever l'indicateur qui sert au choix de la bonne
classe dérivée, sans quoi certains objets/acteurs peuvent être
créés en utilisant le type de base, ce qui empêche d'ouvrir
certains items d'acteurs après avoir redémarré le monde

Par exemple, après ajout d'une blessure et redémarrage, il était
impossible de réouvrir la feuille du personnage blessé.
2024-06-29 00:12:30 +02:00
49d7c4f71d Merge pull request '12.0.2 - Les pluies d'Astrobazzarh' (#703) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #703
2024-06-14 08:04:23 +02:00
23582984cf Version 12.0.2 - Les pluies d'Astrobazzarh 2024-06-14 00:25:10 +02:00
638459049d Fix: dé draconique et rencontre
Le dé draconique donnait toujours un total de 0
2024-06-14 00:03:06 +02:00
366ca981ca Fix message de log de journaux 2024-06-13 22:46:35 +02:00
c0e54c2369 Fix warning sur test de version 2024-06-13 22:06:23 +02:00
f95f5b2b81 Fix calendrier in v12 2024-06-13 22:00:09 +02:00
d30226cb33 Fix game.users for v12 2024-06-13 21:52:48 +02:00
5cf7dda76c Fix game.users for v12 2024-06-13 21:51:31 +02:00
84 changed files with 2039 additions and 620 deletions

View File

@@ -1,16 +1,92 @@
# 12.0
## 12.0.12 - L'étalage d'Astrobazzarh
- Fix: On peut de nouveau vendre des items sans propriétaire, depuis les compendiums ou depuis l'onglet des Objets
- Début de Feuille PNJ au format des encarts Scriptarium
- support des jets de caractéristiques
- support des jets de compétences
## 12.0.11 - Le scriptorium d'Astrobazzarh
- ajout d'un bouton pour générer les éléments de description d'un personnage
- ajout du logo en background dans la liste des systèmes Foundry
- ajout d'un champ pour le métier
- export scriptarium
- encodage de l'export en windows-1252
- export de l'esquive avec armure et sans armure
## 12.0.10 - Le scriptorium d'Astrobazzarh
- corrections de l'export scriptarium
## 12.0.9 - Le scriptorium d'Astrobazzarh
- ajout d'une fonction avancée pour exporter les personnages dans un format csv
## 12.0.8 - La quincaillerie d'Astrobazzarh
- le propriétaire est indiqué dans les feuilles d'équipements/compétences/...
- Ecaille d'efficacité
- l'écaille d'efficacité est prise en compte même si on n'utilise pas le ciblage en combat
- l'écaille d'efficacité est prise en compte pour l'initiative
- Corrections
- l'état général est pris en compte pour les initiatives
- le tooltip de l'initiative affiche correctement l'initiative
## 12.0.7 - La propriété d'Astrobazzarh
- correction des opérations faites à la création d'un Item:
- la durée des queues/rencontres/souffles
- les effets draconiques d'un souffle/queue
- mise à jour des points de tâche des blessures lors des soins
- pas d'expérience sur les particulières quand aucun MJ n'est connecté
- Le drag&drop d'un acteur depuis la liste des acteurs sur la fiche
d'une entité incarnée permet d'accorder le personnage
- Les messages pour résister aux possessions/conjuration sont envoyées
au défenseur
- Les messages pour résister aux empoignades sont envoyées au défenseur
- la commande /voyage affiche maintenant le total de fatigue pour chaque voyageur
- la commande /voyage affiche maintenant les compétences liées au terrain
## 12.0.6 - Le bazar d'Astrobazzarh
- Corrections de l'inventaire en bazar:
- un problème pouvait survenir en déplaçant les objets
l'inventaire, qui fait qu'un conteneur se retrouve récursivement dans son
propre contenu, ce qui empêche d'ouvrir la feuille d'acteur.
- un objet non-conteneur pouvait dans certains cas avoir un pseudo contenu
- un objet pouvait être considéré comme contenu, sans être présent dans un
conteneur (et donc non affiché)
- vider les conteneurs supprime correctement toutes les informations liées
aux conteneurs/contenus
- Les messages pour les tirages dans le compendium utilisent le "roll mode"
courant pour leur visibilité
- Fix: restaurer la compatibilité Foundry 11
## 12.0.5 - Les mauvais jours d'Astrobazzarh
- Fix: on peut de nouveau ouvrir l'édition de calendrier
- Fix: on ne peut plus ouvrir plusieurs fenêtres de lancer de sort
- Fix: Failed to execute 'getComputedStyle' on 'Window'
## 12.0.4 - La plaie d'Astrobazzarh
- **Support V12**
- Fix: les boutons d'encaissement dans le tchat fonctionnent de nouveau
- Fix warnings sur "Die" et AudioHelper
## 12.0.3 - L'hémorragie d'Astrobazzarh
- **Support V12**
- On peut de nouveau ouvrir un acteur blessé après redémarrage du monde
- On peut de nouveau ouvrir les Items avec une rareté par environnement
- Le choix de ne plus afficher les demandes de suppression est bien pris en compte
## 12.0.2 - Les pluies d'Astrobazzarh
- **Support V12**
- correction des actions techniques déleguées au MJ qui bloquaient les fenêtre de lancer de dés des joueurs (et plein d'autres)
- la fenêtre de calendrier s'ouvre correctement
- les dés draconiques peuvent de nouveau faire plus que 0
- adaptation de la fenêtre de recherche
- correction des comparaisons de version pour les migrations automatiques
- correction des roll.eveluate: l'option async est maintenant standard
- correction des templates liés aux selections
- correction de l'ajustement de luminosité de la scène selon l'heure
- correction des images d'effets sur les tokens
- correction de la vente par le tchat: seul le premier acheteur pouvait acheter
- correction d'erreurs intempestives 'User ... lacks permission to update ...'
# 11.2 # 11.2
## 11.2.22 - Le futur d'Akarlikarlikar
- correction de la vente par le tchat: seul le premier acheteur pouvait acheter
- correction d'erreurs intempestives 'User ... lacks permission to update ...'
### Support V12
- adaptation fenêtre de recherche
- correction des comparaisons de version pour les migrations automatiques
- correction des roll.eveluate: l'option async est maintenant standard
- correction des templates liés aux selections
- correction de l'ajustement de luminosité de la scène selon l'heure
- correction des images d'effets sur les tokens
## 11.2.21 - Le questionnement d'Akarlikarlikar ## 11.2.21 - Le questionnement d'Akarlikarlikar
- Une confirmation spécifique est demandée pour monter dans les terres médianes en cas de rencontre en attente - Une confirmation spécifique est demandée pour monter dans les terres médianes en cas de rencontre en attente
- L'expérience en caractéristique sur les jets de chance et rêve actuels est mise dans la caractéristique correspondante - L'expérience en caractéristique sur les jets de chance et rêve actuels est mise dans la caractéristique correspondante

View File

@@ -9,7 +9,7 @@ export class DialogItemVente extends Dialog {
const venteData = { const venteData = {
item: item, item: item,
alias: item.actor?.name ?? game.user.name, alias: item.actor?.name ?? game.user.name,
vendeurId: item.actor.id, vendeurId: item.actor?.id,
prixOrigine: item.calculerPrixCommercant(), prixOrigine: item.calculerPrixCommercant(),
prixUnitaire: item.calculerPrixCommercant(), prixUnitaire: item.calculerPrixCommercant(),
prixLot: item.calculerPrixCommercant(), prixLot: item.calculerPrixCommercant(),

View File

@@ -17,6 +17,7 @@ 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";
/* -------------------------------------------- */ /* -------------------------------------------- */
/** /**
@@ -198,6 +199,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
this.html.find('.jeu-label a').click(async event => this.actor.rollJeu(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('.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))
if (game.user.isGM) { if (game.user.isGM) {
// experience log // experience log
this.html.find('.experiencelog-delete').click(async event => { this.html.find('.experiencelog-delete').click(async event => {
@@ -216,7 +218,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
} }
// Points de reve actuel // Points de reve actuel
this.html.find('.ptreve-actuel a').click(async event => this.actor.rollCarac('reve-actuel', true)) this.html.find('.roll-reve-actuel').click(async event => this.actor.rollCarac('reve-actuel', true))
this.html.find('.empoignade-label a').click(async event => RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor))) this.html.find('.empoignade-label a').click(async event => RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor)))
this.html.find('.arme-label a').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event)))) this.html.find('.arme-label a').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event))))

View File

@@ -32,7 +32,7 @@ import { RdDItemBlessure } from "./item/blessure.js";
import { AppAstrologie } from "./sommeil/app-astrologie.js"; import { AppAstrologie } from "./sommeil/app-astrologie.js";
import { RdDEmpoignade } from "./rdd-empoignade.js"; import { RdDEmpoignade } from "./rdd-empoignade.js";
import { ExperienceLog, XP_TOPIC } from "./actor/experience-log.js"; import { ExperienceLog, XP_TOPIC } from "./actor/experience-log.js";
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
import { RdDBaseActorSang } from "./actor/base-actor-sang.js"; import { RdDBaseActorSang } from "./actor/base-actor-sang.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js"; import { DialogChoixXpCarac } from "./dialog-choix-xp-carac.js";
@@ -92,7 +92,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
canReceive(item) { canReceive(item) {
return ![TYPES.competencecreature, TYPES.tarot, TYPES.service].includes(item.type) return ![ITEM_TYPES.competencecreature, ITEM_TYPES.tarot, ITEM_TYPES.service].includes(item.type)
} }
isPersonnageJoueur() { isPersonnageJoueur() {
@@ -125,7 +125,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
getMalusArmure() { getMalusArmure() {
return this.itemTypes[TYPES.armure].filter(it => it.system.equipe) return this.itemTypes[ITEM_TYPES.armure].filter(it => it.system.equipe)
.map(it => it.system.malus) .map(it => it.system.malus)
.reduce(Misc.sum(), 0); .reduce(Misc.sum(), 0);
} }
@@ -142,7 +142,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
getDemiReve() { return this.system.reve.tmrpos.coord } getDemiReve() { return this.system.reve.tmrpos.coord }
getDraconicList() { return this.itemTypes[TYPES.competence].filter(it => it.system.categorie == 'draconic') } getDraconicList() { return this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == 'draconic') }
getBestDraconic() { return foundry.utils.duplicate(this.getDraconicList().sort(Misc.descending(it => it.system.niveau)).find(it => true)) } getBestDraconic() { return foundry.utils.duplicate(this.getDraconicList().sort(Misc.descending(it => it.system.niveau)).find(it => true)) }
getDraconicOuPossession() { getDraconicOuPossession() {
return [...this.getDraconicList().filter(it => it.system.niveau >= 0), return [...this.getDraconicList().filter(it => it.system.niveau >= 0),
@@ -153,7 +153,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async $perteRevePotionsEnchantees() { async $perteRevePotionsEnchantees() {
let potions = this.itemTypes[TYPES.potion] let potions = this.itemTypes[ITEM_TYPES.potion]
.filter(it => Grammar.includesLowerCaseNoAccent(it.system.categorie, 'enchanté') && !it.system.prpermanent) .filter(it => Grammar.includesLowerCaseNoAccent(it.system.categorie, 'enchanté') && !it.system.prpermanent)
const potionUpdates = await Promise.all(potions.map(async it => { const potionUpdates = await Promise.all(potions.map(async it => {
@@ -345,7 +345,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _recupererBlessures(message, isMaladeEmpoisonne) { async _recupererBlessures(message, isMaladeEmpoisonne) {
const timestamp = game.system.rdd.calendrier.getTimestamp() const timestamp = game.system.rdd.calendrier.getTimestamp()
const blessures = this.filterItems(it => it.system.gravite > 0, TYPES.blessure).sort(Misc.ascending(it => it.system.gravite)) const blessures = this.filterItems(it => it.system.gravite > 0, ITEM_TYPES.blessure).sort(Misc.ascending(it => it.system.gravite))
await Promise.all(blessures.map(async b => b.recuperationBlessure({ await Promise.all(blessures.map(async b => b.recuperationBlessure({
actor: this, actor: this,
@@ -361,7 +361,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _recupererVie(message, isMaladeEmpoisonne) { async _recupererVie(message, isMaladeEmpoisonne) {
const tData = this.system const tData = this.system
let blessures = this.filterItems(it => it.system.gravite > 0, TYPES.blessure); let blessures = this.filterItems(it => it.system.gravite > 0, ITEM_TYPES.blessure);
if (blessures.length > 0) { if (blessures.length > 0) {
return return
} }
@@ -636,7 +636,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async sortMisEnReserve(sort, draconic, coord, ptreve) { async sortMisEnReserve(sort, draconic, coord, ptreve) {
await this.createEmbeddedDocuments("Item", [{ await this.createEmbeddedDocuments("Item", [{
type: TYPES.sortreserve, type: ITEM_TYPES.sortreserve,
name: sort.name, name: sort.name,
img: sort.img, img: sort.img,
system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' } system: { sortid: sort._id, draconic: (draconic?.name ?? sort.system.draconic), ptreve: ptreve, coord: coord, heurecible: 'Vaisseau' }
@@ -991,24 +991,24 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
buildTMRInnaccessible() { buildTMRInnaccessible() {
return this.items.filter(it => it.type == TYPES.casetmr).filter(it => EffetsDraconiques.isInnaccessible(it)).map(it => it.system.coord) return this.items.filter(it => it.type == ITEM_TYPES.casetmr).filter(it => EffetsDraconiques.isInnaccessible(it)).map(it => it.system.coord)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getRencontresTMR() { getRencontresTMR() {
return this.itemTypes[TYPES.rencontre]; return this.itemTypes[ITEM_TYPES.rencontre];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async deleteRencontreTMRAtPosition() { async deleteRencontreTMRAtPosition() {
const rencontreIds = this.itemTypes[TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id) const rencontreIds = this.itemTypes[ITEM_TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id)
if (rencontreIds.length > 0) { if (rencontreIds.length > 0) {
await this.deleteEmbeddedDocuments('Item', rencontreIds) await this.deleteEmbeddedDocuments('Item', rencontreIds)
} }
} }
getRencontreTMREnAttente() { getRencontreTMREnAttente() {
return this.itemTypes[TYPES.rencontre].find(this.filterRencontreTMRDemiReve()) return this.itemTypes[ITEM_TYPES.rencontre].find(this.filterRencontreTMRDemiReve())
} }
filterRencontreTMRDemiReve() { filterRencontreTMRDemiReve() {
@@ -1146,8 +1146,7 @@ export class RdDActor extends RdDBaseActorSang {
diffNbDoses: -Number(this.system.compteurs.ethylisme.nb_doses || 0), diffNbDoses: -Number(this.system.compteurs.ethylisme.nb_doses || 0),
finalLevel: 0, finalLevel: 0,
diffConditions: 0, diffConditions: 0,
ajustementsForce: CONFIG.RDD.difficultesLibres, ajustementsForce: CONFIG.RDD.difficultesLibres
config: game.system.rdd.config
} }
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-ethylisme.html', rollData); let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-roll-ethylisme.html', rollData);
new RdDRollDialogEthylisme(html, rollData, this, r => this.saouler(r.forceAlcool)).render(true); new RdDRollDialogEthylisme(html, rollData, this, r => this.saouler(r.forceAlcool)).render(true);
@@ -1161,11 +1160,11 @@ export class RdDActor extends RdDBaseActorSang {
if (result) { return result } if (result) { return result }
switch (item.type) { switch (item.type) {
case TYPES.potion: return await this.consommerPotion(item, onActionItem); case ITEM_TYPES.potion: return await this.consommerPotion(item, onActionItem);
case TYPES.livre: return await this.actionLire(item); case ITEM_TYPES.livre: return await this.actionLire(item);
case TYPES.conteneur: return await item.sheet.render(true); case ITEM_TYPES.conteneur: return await item.sheet.render(true);
case TYPES.herbe: return await this.actionHerbe(item, onActionItem); case ITEM_TYPES.herbe: return await this.actionHerbe(item, onActionItem);
case TYPES.queue: case TYPES.ombre: return await this.actionRefoulement(item); case ITEM_TYPES.queue: case ITEM_TYPES.ombre: return await this.actionRefoulement(item);
} }
return undefined return undefined
} }
@@ -1549,6 +1548,9 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { async appliquerAjoutExperience(rollData, hideChatMessage = 'show') {
if (!Misc.firstConnectedGM()){
return
}
hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM) hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM)
let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence, rollData.jetResistance); let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence, rollData.jetResistance);
if (xpData.length) { if (xpData.length) {
@@ -1557,7 +1559,7 @@ export class RdDActor extends RdDBaseActorSang {
xpData xpData
}) })
if (hideChatMessage) { if (hideChatMessage) {
ChatUtility.blindMessageToGM({ content: content }); ChatUtility.blindMessageToGM({ content: content })
} }
else { else {
ChatMessage.create({ ChatMessage.create({
@@ -1600,7 +1602,7 @@ export class RdDActor extends RdDBaseActorSang {
computeDraconicAndSortIndex(sortList) { computeDraconicAndSortIndex(sortList) {
let draconicList = this.getDraconicList(); let draconicList = this.getDraconicList();
for (let sort of sortList) { for (let sort of sortList) {
let draconicsSort = this.getDraconicsSort(draconicList, sort).map(it => it.name); let draconicsSort = RdDItemSort.getDraconicsSort(draconicList, sort).map(it => it.name);
for (let index = 0; index < draconicList.length && sort.system.listIndex == undefined; index++) { for (let index = 0; index < draconicList.length && sort.system.listIndex == undefined; index++) {
if (draconicsSort.includes(draconicList[index].name)) { if (draconicsSort.includes(draconicList[index].name)) {
sort.system.listIndex = index; sort.system.listIndex = index;
@@ -1610,19 +1612,6 @@ export class RdDActor extends RdDBaseActorSang {
return draconicList; return draconicList;
} }
/* -------------------------------------------- */
getDraconicsSort(draconicList, sort) {
//console.log(draconicList, bestDraconic, draconic, voie);
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
case "lecture d'aura":
case "detection d'aura":
return draconicList;
case "annulation de magie":
return draconicList.filter(it => !RdDItemCompetence.isThanatos(it));
}
return [RdDItemCompetence.getVoieDraconic(draconicList, sort.system.draconic)];
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollUnSort(coord) { async rollUnSort(coord) {
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
@@ -1824,7 +1813,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
blessuresASoigner() { blessuresASoigner() {
return (this.itemTypes[TYPES.blessure]) return (this.itemTypes[ITEM_TYPES.blessure])
.filter(it => it.system.gravite > 0 && it.system.gravite <= 6) .filter(it => it.system.gravite > 0 && it.system.gravite <= 6)
.filter(it => !(it.system.premierssoins.done && it.system.soinscomplets.done)) .filter(it => !(it.system.premierssoins.done && it.system.soinscomplets.done))
.sort(Misc.descending(b => (b.system.premierssoins.done ? "A" : "B") + b.system.gravite)) .sort(Misc.descending(b => (b.system.premierssoins.done ? "A" : "B") + b.system.gravite))
@@ -3063,7 +3052,7 @@ export class RdDActor extends RdDBaseActorSang {
async nouvelleIncarnation() { async nouvelleIncarnation() {
let incarnation = this.toObject(); let incarnation = this.toObject();
incarnation.items = Array.from(this.items.filter(it => it.type == TYPES.competence), incarnation.items = Array.from(this.items.filter(it => it.type == ITEM_TYPES.competence),
it => { it => {
it = it.toObject(); it = it.toObject();
it.id = undefined; it.id = undefined;
@@ -3078,7 +3067,7 @@ export class RdDActor extends RdDBaseActorSang {
incarnation.name = 'Réincarnation de ' + incarnation.name incarnation.name = 'Réincarnation de ' + incarnation.name
incarnation.system = { incarnation.system = {
carac: foundry.utils.duplicate(this.system.carac), carac: foundry.utils.duplicate(this.system.carac),
heure: RdDTimestamp.defHeure(await RdDDice.rollTotal("1dh", { rollMode: "selfroll", showDice: SHOW_DICE })).key, heure: RdDTimestamp.defHeure(await RdDDice.rollHeure( { rollMode: "selfroll", showDice: SHOW_DICE })).key,
age: 18, age: 18,
biographie: '', biographie: '',
notes: '', notes: '',

View File

@@ -25,8 +25,8 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet {
if (!this.options.editable) return; if (!this.options.editable) return;
this.html.find('.encaisser-direct').click(async event => this.actor.encaisser()) this.html.find('.encaisser-direct').click(async event => this.actor.encaisser())
this.html.find('.carac-label a').click(async event => this.actor.rollCarac(Grammar.toLowerCaseNoAccent(event.currentTarget.attributes.name.value))); this.html.find('.roll-carac').click(async event => this.actor.rollCarac(Grammar.toLowerCaseNoAccent(event.currentTarget.attributes.name.value)));
this.html.find('a.competence-label').click(async event => this.actor.rollCompetence(RdDSheetUtility.getItemId(event))); this.html.find('.roll-competence').click(async event => this.actor.rollCompetence(RdDSheetUtility.getItemId(event)));
this.html.find('.endurance-plus').click(async event => this.actor.santeIncDec("endurance", 1)); this.html.find('.endurance-plus').click(async event => this.actor.santeIncDec("endurance", 1));
this.html.find('.endurance-moins').click(async event => this.actor.santeIncDec("endurance", -1)); this.html.find('.endurance-moins').click(async event => this.actor.santeIncDec("endurance", -1));

View File

@@ -12,7 +12,7 @@ import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
import { RdDBaseActor } from "./base-actor.js"; import { RdDBaseActor } from "./base-actor.js";
import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
import { StatusEffects } from "../settings/status-effects.js"; import { StatusEffects } from "../settings/status-effects.js";
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { Targets } from "../targets.js"; import { Targets } from "../targets.js";
import { RdDPossession } from "../rdd-possession.js"; import { RdDPossession } from "../rdd-possession.js";
import { RdDCombat } from "../rdd-combat.js"; import { RdDCombat } from "../rdd-combat.js";
@@ -108,14 +108,14 @@ export class RdDBaseActorReve extends RdDBaseActor {
async $finDeRoundSupprimerObsoletes() { async $finDeRoundSupprimerObsoletes() {
const obsoletes = [] const obsoletes = []
.concat(this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp <= 0)) .concat(this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp <= 0))
.concat(this.itemTypes[TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2)) .concat(this.itemTypes[ITEM_TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2))
.map(it => it.id); .map(it => it.id);
await this.deleteEmbeddedDocuments('Item', obsoletes); await this.deleteEmbeddedDocuments('Item', obsoletes);
} }
async $finDeRoundEmpoignade() { async $finDeRoundEmpoignade() {
const immobilisations = this.itemTypes[TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id); const immobilisations = this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id);
immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this, immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this,
game.actors.get(emp.system.empoigneid), game.actors.get(emp.system.empoigneid),
emp emp
@@ -151,13 +151,13 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
getPossession(possessionId) { getPossession(possessionId) {
return this.itemTypes[TYPES.possession].find(it => it.system.possessionid == possessionId); return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId);
} }
getPossessions() { getPossessions() {
return this.itemTypes[TYPES.possession]; return this.itemTypes[ITEM_TYPES.possession];
} }
getEmpoignades() { getEmpoignades() {
return this.itemTypes[TYPES.empoignade]; return this.itemTypes[ITEM_TYPES.empoignade];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -296,6 +296,9 @@ export class RdDBaseActorReve extends RdDBaseActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollCarac(caracName, jetResistance = undefined) { async rollCarac(caracName, jetResistance = undefined) {
if (Grammar.equalsInsensitive(caracName, 'taille')){
return
}
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
let selectedCarac = this.getCaracByName(caracName) let selectedCarac = this.getCaracByName(caracName)
await this.openRollDialog({ await this.openRollDialog({
@@ -318,11 +321,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollCompetence(idOrName, options = { tryTarget: true }) { 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 } let rollData = { carac: this.system.carac, competence: competence, arme: options.arme }
if (competence.type == TYPES.competencecreature) { if (competence.type == ITEM_TYPES.competencecreature) {
const arme = RdDItemCompetenceCreature.armeCreature(competence) const arme = RdDItemCompetenceCreature.armeCreature(competence)
if (arme && options.tryTarget && Targets.hasTargets()) { if (arme && options.tryTarget && Targets.hasTargets()) {
Targets.selectOneToken(target => { Targets.selectOneToken(target => {
@@ -361,7 +364,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
* @returns * @returns
*/ */
rollArme(arme, categorieArme = "competence") { rollArme(arme, categorieArme = "competence") {
let compToUse = this.$getCompetenceArme(arme, categorieArme) const compToUse = this.$getCompetenceArme(arme, categorieArme)
if (!RdDItemArme.isArmeUtilisable(arme)) { if (!RdDItemArme.isArmeUtilisable(arme)) {
ui.notifications.warn(`Arme inutilisable: ${arme.name} a une résistance de 0 ou moins`) ui.notifications.warn(`Arme inutilisable: ${arme.name} a une résistance de 0 ou moins`)
return return
@@ -375,7 +378,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
title: 'Ne pas utiliser les automatisation de combat', title: 'Ne pas utiliser les automatisation de combat',
buttonLabel: "Pas d'automatisation", buttonLabel: "Pas d'automatisation",
onAction: async () => { onAction: async () => {
this.rollCompetence(compToUse, { tryTarget: false }) this.rollCompetence(compToUse, { tryTarget: false, arme: arme })
} }
}); });
return return
@@ -396,19 +399,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
$getCompetenceArme(arme, competenceName) { $getCompetenceArme(arme, competenceName) {
switch (arme.type) { return RdDItemArme.getCompetenceArme(arme, competenceName)
case TYPES.competencecreature:
return arme.name
case TYPES.arme:
switch (competenceName) {
case 'competence': return arme.system.competence;
case 'unemain': return RdDItemArme.competence1Mains(arme);
case 'deuxmains': return RdDItemArme.competence2Mains(arme);
case 'tir': return arme.system.tir;
case 'lancer': return arme.system.lancer;
}
}
return undefined
} }
verifierForceMin(item) { verifierForceMin(item) {
@@ -508,8 +499,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
isEntiteAccordee(attacker) { return true } isEntiteAccordee(attacker) { return true }
async setEntiteReveAccordee(attacker) { async setEntiteReveAccordee(actor) {
ui.notifications.error("Impossible de s'accorder à " + this.name + ": ce n'est pas une entite de cauchemer/rêve"); ui.notifications.error("Impossible de s'accorder à " + this.name + ": ce n'est pas une entité incarnée");
} }
} }

View File

@@ -1,7 +1,7 @@
import { MAX_ENDURANCE_FATIGUE, RdDUtility } from "../rdd-utility.js"; import { MAX_ENDURANCE_FATIGUE, 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 { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.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";
@@ -50,9 +50,9 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
isDead() { return this.system.sante.vie.value < -this.getSConst() } isDead() { return this.system.sante.vie.value < -this.getSConst() }
nbBlessuresLegeres() { return this.itemTypes[TYPES.blessure].filter(it => it.isLegere()).length } nbBlessuresLegeres() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isLegere()).length }
nbBlessuresGraves() { return this.itemTypes[TYPES.blessure].filter(it => it.isGrave()).length } nbBlessuresGraves() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isGrave()).length }
nbBlessuresCritiques() { return this.itemTypes[TYPES.blessure].filter(it => it.isCritique()).length } nbBlessuresCritiques() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isCritique()).length }
/* -------------------------------------------- */ /* -------------------------------------------- */
computeResumeBlessure() { computeResumeBlessure() {
@@ -197,7 +197,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
} }
async supprimerBlessures(filterToDelete) { async supprimerBlessures(filterToDelete) {
const toDelete = this.filterItems(filterToDelete, TYPES.blessure) const toDelete = this.filterItems(filterToDelete, ITEM_TYPES.blessure)
.map(it => it.id); .map(it => it.id);
await this.deleteEmbeddedDocuments('Item', toDelete); await this.deleteEmbeddedDocuments('Item', toDelete);
} }

View File

@@ -3,7 +3,7 @@ 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, TYPES } from "../item.js"; import { RdDItem, ITEM_TYPES } from "../item.js";
import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -38,8 +38,7 @@ export class RdDBaseActorSheet extends ActorSheet {
description: await TextEditor.enrichHTML(this.actor.system.description, { async: true }), description: await TextEditor.enrichHTML(this.actor.system.description, { async: true }),
notesmj: await TextEditor.enrichHTML(this.actor.system.notesmj, { async: true }), notesmj: await TextEditor.enrichHTML(this.actor.system.notesmj, { async: true }),
options: RdDSheetUtility.mergeDocumentRights(this.options, this.actor, this.isEditable), options: RdDSheetUtility.mergeDocumentRights(this.options, this.actor, this.isEditable),
effects: this.actor.effects, effects: this.actor.effects
config: game.system.rdd.config
} }
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes); RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
@@ -52,7 +51,7 @@ export class RdDBaseActorSheet extends ActorSheet {
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires); this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires); this._appliquerRechercheObjets(formData.conteneurs, formData.inventaires);
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs); formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
formData.competences.filter(it => it.type == 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;
} }

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 { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.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";
@@ -121,6 +121,7 @@ export class RdDBaseActor extends Actor {
return new ActorConstructor(docData, context); return new ActorConstructor(docData, context);
} }
} }
context.rdd = undefined
super(docData, context); super(docData, context);
} }
@@ -231,11 +232,13 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async cleanupConteneurs() { async cleanupConteneurs() {
let updates = this.itemTypes['conteneur'] if (Misc.isOwnerPlayerOrUniqueConnectedGM(this)) {
.filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0) let updates = this.itemTypes['conteneur']
.map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } }); .filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0)
if (updates.length > 0) { .map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } });
await this.updateEmbeddedDocuments("Item", updates) if (updates.length > 0) {
await this.updateEmbeddedDocuments("Item", updates)
}
} }
} }
@@ -539,7 +542,7 @@ export class RdDBaseActor extends Actor {
// Calculer le total actuel des contenus // Calculer le total actuel des contenus
const encContenu = dest.getEncContenu(); const encContenu = dest.getEncContenu();
const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet const newEnc = moved.getEncTotal(); // Calculer le total actuel du nouvel objet
const placeDisponible = Math.roundDecimals(dest.system.capacite - encContenu - newEnc, 4) const placeDisponible = Misc.keepDecimals(dest.system.capacite - encContenu - newEnc, 4)
// Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet // Teste si le conteneur de destination a suffisament de capacité pour recevoir le nouvel objet
if (placeDisponible < 0) { if (placeDisponible < 0) {
@@ -554,15 +557,15 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** Ajoute un item dans un conteneur, sur la base de leurs ID */ /** Ajoute un item dans un conteneur, sur la base de leurs ID */
async ajouterDansConteneur(item, conteneur, onAjouterDansConteneur) { async ajouterDansConteneur(item, conteneur, onAjouterDansConteneur) {
if (!conteneur) { if (conteneur?.isConteneur()) {
// TODO: afficher
item.estContenu = false;
}
else if (conteneur.isConteneur()) {
item.estContenu = true; item.estContenu = true;
const nouveauContenu = [...conteneur.system.contenu, item.id]; const nouveauContenu = [...conteneur.system.contenu, item.id];
await conteneur.update({ 'system.contenu': nouveauContenu }); await conteneur.update({ 'system.contenu': nouveauContenu });
onAjouterDansConteneur(item.id, conteneur.id); onAjouterDansConteneur(item.id, conteneur.id)
}
else {
item.estContenu = false;
await conteneur?.update({ 'system.-=contenu': undefined })
} }
} }
@@ -580,8 +583,13 @@ export class RdDBaseActor extends Actor {
if (item.estContenu) { if (item.estContenu) {
item.estContenu = undefined; item.estContenu = undefined;
} }
if (item.type == 'conteneur' && item.system.contenu.length > 0) { if (item.system.contenu != undefined) {
corrections.push({ _id: item.id, 'system.contenu': [] }); if (item.type == 'conteneur') {
corrections.push({ _id: item.id, 'system.contenu': [] });
}
else {
corrections.push({ _id: item.id, 'system.-=contenu': undefined });
}
} }
} }
if (corrections.length > 0) { if (corrections.length > 0) {
@@ -616,15 +624,21 @@ export class RdDBaseActor extends Actor {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/** Supprime un item d'un conteneur, sur la base /**
* de leurs ID */ * Supprime un item d'un conteneur, sur la base de leurs ID
*/
async enleverDeConteneur(item, conteneur, onEnleverDeConteneur) { async enleverDeConteneur(item, conteneur, onEnleverDeConteneur) {
if (conteneur?.isConteneur()) { if (conteneur) {
item.estContenu = false; if (conteneur.isConteneur()) {
const contenu = conteneur.system.contenu.filter(id => id != item.id); const contenu = conteneur.system.contenu.filter(id => id != item.id);
await conteneur.update({ 'system.contenu': contenu }); await conteneur.update({ 'system.contenu': contenu });
onEnleverDeConteneur(); onEnleverDeConteneur();
}
else {
await conteneur.update({ 'system.-=contenu': undefined })
}
} }
item.estContenu = false;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -690,7 +704,7 @@ export class RdDBaseActor extends Actor {
async actionPrincipale(item, onActionItem = async () => { }) { async actionPrincipale(item, onActionItem = async () => { }) {
switch (item.type) { switch (item.type) {
case TYPES.conteneur: return await item.sheet.render(true); case ITEM_TYPES.conteneur: return await item.sheet.render(true);
} }
return undefined return undefined
} }

View File

@@ -1,5 +1,5 @@
import { ENTITE_INCARNE } from "../constants.js"; import { ENTITE_INCARNE } from "../constants.js";
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { STATUSES } from "../settings/status-effects.js"; import { STATUSES } from "../settings/status-effects.js";
import { RdDBaseActorSang } from "./base-actor-sang.js"; import { RdDBaseActorSang } from "./base-actor-sang.js";
@@ -12,7 +12,7 @@ export class RdDCreature extends RdDBaseActorSang {
isCreature() { return true } isCreature() { return true }
canReceive(item) { canReceive(item) {
return item.type == TYPES.competencecreature || item.isInventaire(); return item.type == ITEM_TYPES.competencecreature || item.isInventaire();
} }
async remiseANeuf() { async remiseANeuf() {
@@ -33,27 +33,4 @@ export class RdDCreature extends RdDBaseActorSang {
} }
} }
isEntiteAccordee(attacker) {
if (this.isEntite([ENTITE_INCARNE])) {
let resonnance = this.system.sante.resonnance
return (resonnance.actors.find(it => it == attacker.id))
}
return true
}
/* -------------------------------------------- */
async setEntiteReveAccordee(attacker) {
if (this.isEntite([ENTITE_INCARNE])) {
let resonnance = foundry.utils.duplicate(this.system.sante.resonnance);
if (resonnance.actors.find(it => it == attacker.id)) {
// déjà accordé
return;
}
await this.update({ "system.sante.resonnance": [...resonnance, attacker.id] });
}
else {
super.setEntiteReveAccordee(attacker)
}
}
} }

View File

@@ -54,6 +54,12 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
}); });
} }
async _onDropActor(event, dragData) {
const dropActor = fromUuidSync(dragData.uuid)
await this.actor.setEntiteReveAccordee(dropActor)
super._onDropActor(event, dragData)
}
async deleteSubActeur(actorId) { async deleteSubActeur(actorId) {
let newResonances = this.actor.system.sante.resonnance.actors.filter(id => id != actorId); let newResonances = this.actor.system.sante.resonnance.actors.filter(id => id != actorId);
await this.actor.update({ 'system.sante.resonnance.actors': newResonances }, { renderSheet: false }); await this.actor.update({ 'system.sante.resonnance.actors': newResonances }, { renderSheet: false });

View File

@@ -1,5 +1,5 @@
import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js"; import { ENTITE_INCARNE, ENTITE_NONINCARNE } from "../constants.js";
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDEncaisser } from "../rdd-roll-encaisser.js"; import { RdDEncaisser } from "../rdd-roll-encaisser.js";
import { STATUSES } from "../settings/status-effects.js"; import { STATUSES } from "../settings/status-effects.js";
@@ -12,7 +12,7 @@ export class RdDEntite extends RdDBaseActorReve {
} }
canReceive(item) { canReceive(item) {
return item.type == TYPES.competencecreature return item.type == ITEM_TYPES.competencecreature
} }
isEntite(typeentite = []) { isEntite(typeentite = []) {
@@ -29,7 +29,7 @@ export class RdDEntite extends RdDBaseActorReve {
getChance() { return this.getReve() } getChance() { return this.getReve() }
getDraconicOuPossession() { getDraconicOuPossession() {
return this.itemTypes[TYPES.competencecreature] return this.itemTypes[ITEM_TYPES.competencecreature]
.filter(it => it.system.categorie == 'possession') .filter(it => it.system.categorie == 'possession')
.sort(Misc.descending(it => it.system.niveau)) .sort(Misc.descending(it => it.system.niveau))
.find(it => true); .find(it => true);
@@ -91,20 +91,16 @@ export class RdDEntite extends RdDBaseActorReve {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async setEntiteReveAccordee(attacker) { async setEntiteReveAccordee(actor) {
if (this.isEntite([ENTITE_INCARNE])) { if (this.isEntite([ENTITE_INCARNE])) {
let resonnance = foundry.utils.duplicate(this.system.sante.resonnance); if (this.system.sante.resonnance.actors.find(it => it == actor.id)) {
if (resonnance.actors.find(it => it == attacker.id)) {
// déjà accordé // déjà accordé
return; return
} }
resonnance.actors.push(attacker.id); await this.update({ "system.sante.resonnance.actors": [...this.system.sante.resonnance.actors, actor.id] })
await this.update({ "system.sante.resonnance": resonnance });
} }
else { else {
super.setEntiteReveAccordee(attacker) super.setEntiteReveAccordee(actor)
} }
} }
} }

View File

@@ -0,0 +1,88 @@
import { RdDActorSheet } from "../../actor-sheet.js"
import { SYSTEM_RDD } from "../../constants.js";
import { Misc } from "../../misc.js";
import { EXPORT_CSV_SCRIPTARIUM, OptionsAvancees } from "../../settings/options-avancees.js";
import { ExportScriptarium } from "./export-scriptarium.js";
import { CATEGORIES_COMPETENCES, CATEGORIES_DRACONIC, Mapping } from "./mapping.js";
export class RdDActorExportSheet extends RdDActorSheet {
static async init() {
await loadTemplates([
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs",
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs",
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-compteur.hbs",
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee.hbs",
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee-compteur.hbs",
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/competences.hbs",
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/esquive.hbs",
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/protection.hbs",
"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs",
])
Actors.registerSheet(SYSTEM_RDD, RdDActorExportSheet, { types: ["personnage"], makeDefault: false, label: "Feuille d'encart" })
}
static get defaultOptions() {
return foundry.utils.mergeObject(RdDActorSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/actor-encart-sheet.hbs",
width: 550,
showCompNiveauBase: false,
vueArchetype: false,
}, { inplace: false })
}
constructor(actor, options) {
super(actor, options)
}
async getData() {
const formData = await super.getData()
// Add any structured, precomputed list of data
formData.export = this.getMappingValues();
formData.competences = this.getCompetences(CATEGORIES_COMPETENCES)
formData.draconic = this.getCompetences(CATEGORIES_DRACONIC)
formData.options.exportScriptarium = OptionsAvancees.isUsing(EXPORT_CSV_SCRIPTARIUM)
return formData
}
getMappingValues() {
const context = Mapping.prepareContext(this.actor)
return Object.fromEntries(Mapping.getMapping().map(it => [it.column, {
colName: it.colName ?? it.column,
column: it.column,
rollClass: it.rollClass,
value: it.getter(this.actor, context)
}]))
}
getCompetences(categories) {
const competences = Mapping.getCompetencesCategorie(this.actor, categories)
if (competences.length == 0) {
return ''
}
const byCategories = Mapping.competencesByCategoriesByNiveau(competences, categories)
const listByCategories = Object.values(byCategories)
.map(it => it.competencesParNiveau)
.map(byNiveau => {
const niveaux = Object.keys(byNiveau).map(it => Number(it)).sort(Misc.ascending())
if (niveaux.length == 0) {
return undefined
}
const listCategorieByNiveau = niveaux.map(niveau => {
const list = byNiveau[niveau].sort(Misc.ascending(it => it.name))
return {niveau, list}
})
return Misc.concat(listCategorieByNiveau)
}).filter(it => it != undefined)
return Misc.concat(listByCategories)
}
activateListeners(html) {
super.activateListeners(html);
this.html.find('.button-export').click(async event => {
ExportScriptarium.INSTANCE.exportActors([this.actor],
`${this.actor.uuid}-${this.actor.name}`
)
})
}
}

View File

@@ -0,0 +1,78 @@
import { ACTOR_TYPES } from "../../item.js"
import { Misc } from "../../misc.js"
import { EXPORT_CSV_SCRIPTARIUM, OptionsAvancees } from "../../settings/options-avancees.js"
import { Mapping } from "./mapping.js"
const IMG_SCRIPTARIUM = '<img class="context-menu-img" src="systems/foundryvtt-reve-de-dragon/styles/img/ui/scriptarium.svg">'
export class ExportScriptarium {
static init() {
ExportScriptarium.INSTANCE = new ExportScriptarium()
}
constructor() {
Hooks.on("getActorDirectoryFolderContext", (actorDirectory, menus) => { ExportScriptarium.INSTANCE.onActorDirectoryMenu(actorDirectory, menus) })
Hooks.on("getActorDirectoryEntryContext", (actorDirectory, menus) => { ExportScriptarium.INSTANCE.onActorDirectoryMenu(actorDirectory, menus) })
}
onActorDirectoryMenu(actorDirectory, menus) {
menus.push({
name: 'Export Personnages <i class="fa-regular fa-file-csv"></i>',
icon: IMG_SCRIPTARIUM,
condition: (target) => game.user.isGM &&
OptionsAvancees.isUsing(EXPORT_CSV_SCRIPTARIUM) &&
this.$getActors(actorDirectory, target).length > 0,
callback: target => this.exportActors(this.$getActors(actorDirectory, target), this.$getTargetName(actorDirectory, target))
})
}
$getTargetName(actorDirectory, target) {
const li = target.closest(".directory-item")
const folderId = li.data("folderId")
const actorId = li.data("documentId")
return actorId
? game.actors.get(actorId).name
: actorDirectory.folders.find(it => it.id == folderId).name
}
$getActors(actorDirectory, target) {
const li = target.closest(".directory-item")
const folderId = li.data("folderId")
const actorId = li.data("documentId")
const actors = actorId
? [game.actors.get(actorId)]
: folderId
? actorDirectory.folders.find(it => it.id == folderId).contents
: []
return actors.filter(it => it.type == ACTOR_TYPES.personnage)
}
exportActors(actors, targetName) {
const eol = '\n\r'
const header = Misc.join(this.getHeaderLine(), ';')
const actorLines = actors.map(actor => Misc.join(this.getActorLine(actor), ';'))
const data = Misc.join([header, ...actorLines], eol)
const filename = `scriptarium-${targetName?.slugify()}.csv`;
saveDataToFile(data, "text/csv;charset=windows-1252", `${filename}`);
}
getHeaderLine() {
return Mapping.getColumns()
}
getActorLine(actor) {
const values = Mapping.getValues(actor)
return values
.map(it => this.$escapeQuotes(it))
.map(it => it.replaceAll("\n", " ").replaceAll("\r", ""))
}
$escapeQuotes(it) {
it = '' + it
if (it.includes('"') || it.includes(';')) {
return `"${it.replaceAll('"', '\\"')}"`
}
return it
}
}

View File

@@ -0,0 +1,362 @@
import { Grammar } from "../../grammar.js"
import { RdDItemArme } from "../../item-arme.js"
import { RdDItemCompetence } from "../../item-competence.js"
import { RdDItemSort } from "../../item-sort.js"
import { ITEM_TYPES } from "../../item.js"
import { Misc } from "../../misc.js"
import { RdDTimestamp } from "../../time/rdd-timestamp.js"
import { RdDBonus } from "../../rdd-bonus.js"
import { TMRType } from "../../tmr-utility.js"
export const CATEGORIES_COMPETENCES = [
"generale",
"particuliere",
"specialisee",
"connaissance",
]
export const CATEGORIES_DRACONIC = [
"draconic",
]
const CATEGORIES_COMBAT = [
"melee",
"tir",
"lancer"
]
const NIVEAU_BASE = {
"generale": -4,
"particuliere": -8,
"specialisee": -11,
"connaissance": -11,
"draconic": -11,
"melee": -6,
"tir": -8,
"lancer": -8,
}
class ColumnMappingFactory {
static createMappingArme(part, i) {
return { column: `arme_${part}_${i}`, getter: (actor, context) => Mapping.getArme(actor, context, part, i) }
}
static createMappingSort(part, i) {
return { column: `sort_${part}_${i}`, getter: (actor, context) => Mapping.getSort(actor, context, part, i) }
}
}
const NB_ARMES = 10
const NB_SORTS = 20
const TABLEAU_ARMES = [...Array(NB_ARMES).keys()]
const TABLEAU_SORTS = [...Array(NB_SORTS).keys()]
const MAPPING_BASE = [
{ column: "ID", colName: 'ID', getter: (actor, context) => actor.id },
{ column: "name", getter: (actor, context) => actor.name },
{ column: "metier", colName: 'Métier', getter: (actor, context) => actor.system.metier },
{ column: "biographie", colName: 'Biographie', getter: (actor, context) => actor.system.biographie },
{ column: "taille", getter: (actor, context) => actor.system.carac.taille.value },
{ column: "apparence", rollClass: 'roll-carac', getter: (actor, context) => actor.system.carac.apparence.value },
{ column: "constitution", rollClass: 'roll-carac', getter: (actor, context) => actor.system.carac.constitution.value },
{ column: "force", rollClass: 'roll-carac', getter: (actor, context) => actor.system.carac.force.value },
{ column: "agilite", rollClass: 'roll-carac', colName: 'Agilité', getter: (actor, context) => actor.system.carac.agilite.value },
{ column: "dexterite", rollClass: 'roll-carac', colName: 'Dextérité', getter: (actor, context) => actor.system.carac.dexterite.value },
{ column: "vue", rollClass: 'roll-carac', getter: (actor, context) => actor.system.carac.vue.value },
{ column: "ouie", rollClass: 'roll-carac', colName: 'Ouïe', getter: (actor, context) => actor.system.carac.ouie.value },
{ column: "odoratgout", rollClass: 'roll-carac', colName: 'Odo-goût', getter: (actor, context) => actor.system.carac.odoratgout.value },
{ column: "volonte", rollClass: 'roll-carac', colName: 'Volonté', getter: (actor, context) => actor.system.carac.volonte.value },
{ column: "intellect", rollClass: 'roll-carac', getter: (actor, context) => actor.system.carac.intellect.value },
{ column: "empathie", rollClass: 'roll-carac', getter: (actor, context) => actor.system.carac.empathie.value },
{ column: "reve", rollClass: 'roll-carac', colName: 'Rêve', getter: (actor, context) => actor.system.carac.reve.value },
{ column: "chance", rollClass: 'roll-carac', getter: (actor, context) => actor.system.carac.chance.value },
{ column: "melee", rollClass: 'roll-carac', colName: 'Mêlée', getter: (actor, context) => actor.system.carac.melee.value },
{ column: "tir", rollClass: 'roll-carac', getter: (actor, context) => actor.system.carac.tir.value },
{ column: "lancer", rollClass: 'roll-carac', getter: (actor, context) => actor.system.carac.lancer.value },
{ column: "derobee", rollClass: 'roll-carac', colName: 'Dérobée', getter: (actor, context) => actor.system.carac.derobee.value },
{ column: "vie", getter: (actor, context) => actor.system.sante.vie.max },
{ column: "endurance", getter: (actor, context) => actor.system.sante.endurance.max },
{ column: "plusdom", colName: '+dom', getter: (actor, context) => actor.system.attributs.plusdom.value },
{ column: "protectionnaturelle", colName: 'Protection naturelle', getter: (actor, context) => actor.system.attributs.protection.value > 0 ? actor.system.attributs.protection.value : '' },
{ column: "description", getter: (actor, context) => Mapping.getDescription(actor) },
{ column: "armure", getter: (actor, context) => Mapping.getArmure(actor, context) },
{ column: "protectionarmure", colName: 'Protection', getter: (actor, context) => Mapping.getProtectionArmure(actor, context) },
{ column: "malus_armure", getter: (actor, context) => Mapping.getMalusArmure(actor, context) },
{ column: "reve_actuel", rollClass: 'roll-reve-actuel', colName: 'Rêve actuel', getter: (actor, context) => actor.system.reve.reve.value },
{ column: "vie_actuel", rollClass: 'jet-vie', getter: (actor, context) => actor.system.sante.vie.value },
{ column: "endurance_actuel", rollClass: 'jet-vie', getter: (actor, context) => actor.system.sante.endurance.value },
{ column: "esquive", getter: (actor, context) => Mapping.getEsquive(context) },
{ column: "esquive_armure", getter: (actor, context) => Mapping.getEsquiveArmure(context) },
{ column: "competences", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_COMPETENCES) },
{ column: "draconic", getter: (actor, context) => Mapping.getCompetences(actor, CATEGORIES_DRACONIC) },
]
const MAPPING_ARMES = TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('name', i))
.concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('niveau', i)))
.concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('init', i)))
.concat(TABLEAU_ARMES.map(i => ColumnMappingFactory.createMappingArme('dommages', i)))
const MAPPING_SORTS = TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('voie', i))
.concat(TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('description', i)))
.concat(TABLEAU_SORTS.map(i => ColumnMappingFactory.createMappingSort('bonus', i)))
const MAPPING = MAPPING_BASE
.concat(MAPPING_ARMES)
.concat(MAPPING_SORTS)
export class Mapping {
static getMapping() {
return MAPPING
}
static getColumns() {
return MAPPING.map(it => it.column)
}
static getValues(actor) {
const context = Mapping.prepareContext(actor)
return MAPPING.map(it => it.getter(actor, context))
}
static getAsObject(actor) {
const context = Mapping.prepareContext(actor)
return Object.fromEntries(MAPPING.map(it => [it.column, {
colName: it.colName ?? it.column,
value: it.getter(actor, context)
}]))
}
static getValues(actor) {
const context = Mapping.prepareContext(actor)
return MAPPING.map(it => it.getter(actor, context))
}
static prepareContext(actor) {
return {
armes: Mapping.prepareArmes(actor),
armure: Mapping.prepareArmure(actor),
esquive: Mapping.prepareEsquive(actor),
sorts: Mapping.prepareSorts(actor)
}
}
static prepareArmes(actor) {
const armes = actor.items.filter(it => it.type == ITEM_TYPES.arme)
return armes.map(arme =>
[
arme.system.tir != "" ? Mapping.prepareArme(actor, arme, 'tir') : undefined,
arme.system.lancer = "" ? Mapping.prepareArme(actor, arme, 'lancer') : undefined,
arme.system.unemain ? Mapping.prepareArme(actor, arme, 'unemain') : undefined,
arme.system.deuxmains ? Mapping.prepareArme(actor, arme, 'deuxmains') : undefined,
!(arme.system.unemain || arme.system.deuxmains) ? Mapping.prepareArme(actor, arme, 'competence') : undefined
]
.filter(it => it != undefined)
).reduce((a, b) => a.concat(b), [])
}
static prepareArme(actor, arme, maniement) {
const nameCompArme = RdDItemArme.getCompetenceArme(arme, maniement)
const competence = actor.getCompetence(nameCompArme)
if (RdDItemCompetence.isNiveauBase(competence)) {
return undefined
}
const dmgArme = RdDItemArme.dommagesReels(arme, maniement)
const dommages = dmgArme + RdDBonus.bonusDmg(actor, maniement, dmgArme)
return {
name: arme.name,
niveau: Misc.toSignedString(competence.system.niveau),
init: Mapping.calculBaseInit(actor, competence.system.categorie) + competence.system.niveau,
dommages: Misc.toSignedString(dommages)
}
}
static calculBaseInit(actor, categorie) {
const mapping = MAPPING_BASE.find(it => it.column == categorie)
if (mapping) {
switch (categorie) {
case 'melee':
case 'tir':
case 'lancer':
const caracteristique = Number(actor.system.carac[categorie].value)
return Math.floor(caracteristique / 2)
}
}
return 0
}
static prepareArmure(actor) {
const armures = actor.itemTypes[ITEM_TYPES.armure].filter(it => it.system.equipe)
if (armures.length > 1) {
console.warn(`${actor.name} a équipé ${armures.length} armures, seule la première sera considérée`)
}
if (armures.length > 0) {
const armure = armures[0]
return {
name: armure.name,
protection: armure.system.protection,
malus: armure.system.malus ?? 0
}
}
return {
name: '',
protection: actor.system.attributs.protection.value,
malus: 0
}
}
static prepareEsquive(actor) {
const esquives = actor.getCompetences("Esquive")
if (esquives.length > 0) {
const esquive = esquives[0]
return {
name: esquive.name,
niveau: esquive.system.niveau
}
}
return undefined
}
static prepareSorts(actor) {
const codeVoies = Mapping.getCompetencesCategorie(actor, CATEGORIES_DRACONIC)
.map(it => RdDItemSort.getVoieCode(it))
return actor.itemTypes[ITEM_TYPES.sort].map(it => Mapping.prepareSort(it, codeVoies))
.sort(Misc.ascending(it => `${it.voie} : ${it.description}`))
}
static prepareSort(sort, voies) {
return {
voie: RdDItemSort.getCodeDraconic(sort, voies),
description: Mapping.descriptionSort(sort),
bonus: Mapping.bonusCase(sort)
}
}
static descriptionSort(sort) {
const ptSeuil = Array(sort.system.coutseuil).map(it => '*')
const caseTMR = sort.system.caseTMRspeciale.length > 0 ? Mapping.toVar(sort.system.caseTMRspeciale) : Misc.upperFirst(TMRType[sort.system.caseTMR].name)
const ptreve = Mapping.addSpaceToNonNumeric(sort.system.ptreve)
const diff = Mapping.addSpaceToNonNumeric(sort.system.difficulte)
return `${sort.name}${ptSeuil} (${caseTMR}) R${diff} r${ptreve}`
}
static addSpaceToNonNumeric(value) {
return Number.isNumeric(value) ? value : ' ' + Mapping.toVar(value)
}
static toVar(value) {
return value.replace('variable', 'var')
}
static bonusCase(sort) {
const list = RdDItemSort.bonuscaseStringToList(sort.system.bonuscase).sort(Misc.descending(it => it.bonus))
if (list.length > 0) {
const bonus = list[0]
return `+${bonus.bonus}% en ${bonus.case}`
}
return ''
}
static getDescription(actor) {
const sexe = actor.system.sexe
const sexeFeminin = sexe.length > 0 && sexe.charAt(0).toLowerCase() == 'f' ? 'Née' : 'Né'
const race = ['', 'humain'].includes(Grammar.toLowerCaseNoAccent(actor.system.race)) ? '' : (actor.system.race + ' ')
const heure = actor.system.heure
const hn = `${sexeFeminin} à l'heure ${RdDTimestamp.definition(heure).avecArticle}`
const age = actor.system.age ? `${actor.system.age} ans` : undefined
const taille = actor.system.taille
const poids = actor.system.poids
const cheveux = actor.system.cheveux ? `cheveux ${actor.system.cheveux}` : undefined
const yeux = actor.system.yeux ? `yeux ${actor.system.yeux}` : undefined
const beaute = actor.system.beaute ? `beauté ${actor.system.beaute}` : undefined
const list = [race, hn, age, taille, poids, cheveux, yeux, beaute]
return Misc.join(list.filter(it => it), ', ')
}
static getArmure(actor, context) {
return context.armure?.name ?? ''
}
static getProtectionArmure(actor, context) {
const naturelle = Number(actor.system.attributs.protection.value)
if (context?.armure?.protection == undefined) {
return naturelle
}
if (Number.isNumeric(context?.armure?.protection)) {
return Number(context?.armure?.protection ?? 0) + naturelle
}
return context?.armure.protection + (naturelle > 0 ? `+${naturelle}` : '')
}
static getMalusArmure(actor, context) {
return context?.armure?.malus ?? 0
}
static getEsquive(context) {
if (context.esquive) {
return Misc.toSignedString(context.esquive.niveau)
}
return ''
}
static getEsquiveArmure(context) {
if (context.esquive) {
const niveau = context.esquive.niveau + context.armure.malus
return Misc.toSignedString(niveau)
}
return ''
}
static getCompetences(actor, categories) {
const competences = Mapping.getCompetencesCategorie(actor, categories)
if (competences.length == 0) {
return ''
}
const byCategories = Mapping.competencesByCategoriesByNiveau(competences, categories)
const txtByCategories = Object.values(byCategories)
.map(it => it.competencesParNiveau)
.map(byNiveau => {
const niveaux = Object.keys(byNiveau).map(it => Number(it)).sort(Misc.ascending())
if (niveaux.length == 0) {
return ''
}
const txtCategorieByNiveau = niveaux.map(niveau => {
const names = Misc.join(byNiveau[niveau].map(it => it.name).sort(Misc.ascending()), ', ')
return names + ' ' + Misc.toSignedString(niveau)
})
const txtCategorie = Misc.join(txtCategorieByNiveau, ' / ')
return txtCategorie
}).filter(it => it != '')
return Misc.join(txtByCategories, ' / ')
}
static competencesByCategoriesByNiveau(competences, categories) {
return categories.map(c => {
return {
categorie: c,
competencesParNiveau: Misc.classify(
competences.filter(comp => comp.system.categorie == c),
comp => comp.system.niveau)
}
})
}
static getArme(actor, context, part, numero) {
if (numero < context.armes.length) {
return context.armes[numero][part] ?? ''
}
return ''
}
static getCompetencesCategorie(actor, categories) {
return actor.itemTypes[ITEM_TYPES.competence]
.filter(it => categories.includes(it.system.categorie))
.filter(it => !RdDItemCompetence.isNiveauBase(it))
}
static getSort(actor, context, part, numero) {
if (numero < context.sorts.length) {
return context.sorts[numero][part]
}
return ''
}
}

View File

@@ -0,0 +1,188 @@
import { SHOW_DICE } from "../../constants.js";
import { Misc } from "../../misc.js";
import { RdDCarac } from "../../rdd-carac.js";
import { RdDDice } from "../../rdd-dice.js";
import { RdDNameGen } from "../../rdd-namegen.js";
import { RdDTimestamp } from "../../time/rdd-timestamp.js";
const PATHS = [
'name',
'system.sexe',
'system.age',
'system.taille',
'system.poids',
'system.main',
'system.heure',
'system.cheveux',
'system.yeux'
]
const RANDOM_VALUES = {
'system.sexe': { 'masculin': 1, 'féminin': 1 },
'system.main': { 'droitier': 51, 'gaucher': 15, 'ambidectre': 6 },
'system.cheveux': { 'noirs': 2, 'bruns': 5, 'châtains clair': 5, 'blonds': 4, 'blonds très clair': 1, 'roux carotte': 1, 'roux cuivré': 3 },
'system.yeux': { 'noirs': 2, 'noisettes': 3, 'bruns vert': 4, 'verts': 3, 'bleus clair': 3, 'bleus gris': 2, 'gris': 1, 'mauves': 1, 'indigos': 1 },
}
export class AppPersonnageAleatoire extends FormApplication {
static preloadHandlebars() {
loadTemplates([
'systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs',
])
}
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor/random/app-personnage-aleatoire.hbs",
title: "Génération aléatoire",
width: 'fit-content',
height: 'fit-content',
classes: ['app-personnage-aleatoire'],
popOut: true,
resizable: true
}, { inplace: false })
}
constructor(actor) {
super({})
this.actor = actor
this.current = foundry.utils.duplicate(actor)
this.checked = {
'name': false,
'system.sexe': true,
'system.age': true,
'system.taille': true,
'system.poids': true,
'system.main': true,
'system.heure': true,
'system.cheveux': true,
'system.yeux': true
}
}
async getData(options) {
return foundry.utils.mergeObject(await super.getData(options), {
actor: this.actor,
current: this.current,
checked: this.checked,
options: { isGM: game.user.isGM }
})
}
activateListeners(html) {
super.activateListeners(html)
this.html = html
this.html.find("button.button-cancel").click(async event => await this.close())
this.html.find("button.button-apply").click(async event => await this.onApply())
this.html.find("input.current-value").change(async event => await this.onChange(event))
this.html.find("div.random-field[data-path='system.heure'] select.current-value").change(async event => await this.onChange(event))
this.html.find("a.random").click(async event => await this.onRandom(event))
this.html.find("a.reset").click(async event => await this.onReset(event))
this.html.find("a.randomize-selected").click(async event => await this.onRandomizeSelected())
this.html.find("input.check-for-random").click(async event => await this.onCheckForRandom(event))
}
async _updateObject(event, formData) { }
async onApply() {
const updates = Object.fromEntries(
PATHS.filter(path => game.user.isGM || path != 'name')
.map(path => [path, this.current[path]])
)
await this.actor.update(updates)
await this.close()
}
getPath(selector) {
const fields = this.html.find(selector).parents("div.random-field:first")
return fields[0].attributes['data-path'].value
}
async onChange(event) {
const path = this.getPath(event.currentTarget)
this.current[path] = event.currentTarget.value
}
async onRandom(event) {
const path = this.getPath(event.currentTarget)
await this.setRandom(path);
this.render()
}
async onReset(event) {
const path = this.getPath(event.currentTarget)
this.current[path] = this.actor[path]
await this.render()
}
async onCheckForRandom(event) {
const path = this.getPath(event.currentTarget)
this.checked[path] = event.currentTarget.checked
this.render()
}
async onRandomizeSelected() {
const paths = this.html.find("input.check-for-random:checked")
.parents("div.random-field")
.toArray()
.map(it => it.attributes['data-path'].value)
await Promise.all(paths.map(path => this.setRandom(path)))
this.render()
}
async setRandom(path) {
this.current[path] = await this.random(path);
}
async random(path) {
switch (path) {
case 'name':
return await RdDNameGen.generate()
case 'system.sexe':
case 'system.main':
case 'system.cheveux':
case 'system.yeux':
return await this.randomFromMap(RANDOM_VALUES[path])
case 'system.poids':
return await this.randomPoids()
case 'system.taille':
return await this.randomTaille()
case 'system.age':
return await RdDDice.rollTotal('(2d4kl)*10 + 1d7xo + 2d20kl')
case 'system.heure':
return RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "selfroll", showDice: SHOW_DICE })).key
}
return 'unknown'
}
async randomFromMap(valuesMap) {
const max = Object.values(valuesMap).reduce(Misc.sum(), 0)
const total = await RdDDice.rollTotal(`1d${max}`)
let sum = 0
for (let entry of Object.entries(valuesMap)) {
sum = sum + entry[1]
if (sum >= total) {
return entry[0]
}
}
return Object.keys(valuesMap)[0]
}
async randomPoids() {
const caracTaille = RdDCarac.getCaracDerivee(this.current.system.carac.taille.value)
const range = caracTaille.poidsMax - caracTaille.poidsMin + 1
const total = await RdDDice.rollTotal(`1d${range} + ${caracTaille.poidsMin}`)
return total + ' kg'
}
async randomTaille() {
const caracTaille = RdDCarac.getCaracDerivee(this.current.system.carac.taille.value)
const base = this.current.system.carac.taille.value * 2 + 60 + caracTaille.poidsMin
const variation = Math.floor((caracTaille.poidsMax - caracTaille.poidsMin + base / 5) / 2)
const total = await RdDDice.rollTotal(`2d${variation} + ${base}`)
const cm = total % 100
const m = (total - cm) / 100
return `${m}m${cm}`
}
}

View File

@@ -24,7 +24,7 @@ export class DialogCreateSigneDraconique extends Dialog {
} }
constructor(dialogData, html) { constructor(dialogData, html) {
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 500, height: 650, 'z-index': 99999 }; let options = { classes: ["DialogCreateSigneDraconiqueActors"], width: 500, height: 650, 'z-index': 99999 };
let conf = { let conf = {
title: "Créer un signe", title: "Créer un signe",
content: html, content: html,

View File

@@ -1,5 +1,5 @@
import { RdDItemCompetenceCreature } from "./item-competencecreature.js" import { RdDItemCompetenceCreature } from "./item-competencecreature.js"
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
import { RdDCombatManager } from "./rdd-combat.js"; import { RdDCombatManager } from "./rdd-combat.js";
const nomCategorieParade = { const nomCategorieParade = {
@@ -20,19 +20,35 @@ const nomCategorieParade = {
export class RdDItemArme extends Item { export class RdDItemArme extends Item {
static isArme(item) { static isArme(item) {
return item.type == TYPES.arme || RdDItemCompetenceCreature.getCategorieAttaque(item); return item.type == ITEM_TYPES.arme || RdDItemCompetenceCreature.getCategorieAttaque(item);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getArme(arme) { static getArme(arme) {
switch (arme ? arme.type : '') { switch (arme ? arme.type : '') {
case TYPES.arme: return arme; case ITEM_TYPES.arme: return arme;
case TYPES.competencecreature: case ITEM_TYPES.competencecreature:
return RdDItemCompetenceCreature.armeCreature(arme); return RdDItemCompetenceCreature.armeCreature(arme);
} }
return RdDItemArme.mainsNues(); return RdDItemArme.mainsNues();
} }
static getCompetenceArme(arme, maniement) {
switch (arme.type) {
case ITEM_TYPES.competencecreature:
return arme.name
case ITEM_TYPES.arme:
switch (maniement) {
case 'competence': return arme.system.competence;
case 'unemain': return RdDItemArme.competence1Mains(arme);
case 'deuxmains': return RdDItemArme.competence2Mains(arme);
case 'tir': return arme.system.tir;
case 'lancer': return arme.system.lancer;
}
}
return undefined
}
static computeNiveauArmes(armes, competences) { static computeNiveauArmes(armes, competences) {
for (const arme of armes) { for (const arme of armes) {
arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences); arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
@@ -68,14 +84,14 @@ export class RdDItemArme extends Item {
return armeData.system.categorie_parade; return armeData.system.categorie_parade;
} }
// pour compatibilité avec des personnages existants // pour compatibilité avec des personnages existants
if (armeData.type == TYPES.competencecreature || armeData.system.categorie == 'creature') { if (armeData.type == ITEM_TYPES.competencecreature || armeData.system.categorie == 'creature') {
return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : ''); return armeData.system.categorie_parade || (armeData.system.isparade ? 'armes-naturelles' : '');
} }
if (!armeData.type.match(/arme|competencecreature/)) { if (!armeData.type.match(/arme|competencecreature/)) {
return ''; return '';
} }
if (armeData.system.competence == undefined) { if (armeData.system.competence == undefined) {
return TYPES.competencecreature; return ITEM_TYPES.competencecreature;
} }
let compname = armeData.system.competence.toLowerCase(); let compname = armeData.system.competence.toLowerCase();
if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return ''; if (compname.match(/^(dague de jet|javelot|fouet|arc|arbalête|fronde|hache de jet|fléau)$/)) return '';
@@ -132,43 +148,46 @@ export class RdDItemArme extends Item {
return true; return true;
} }
/* -------------------------------------------- */ static dommagesReels(arme, maniement) {
static armeUneOuDeuxMains(armeData, aUneMain) { switch (maniement) {
if (armeData && !armeData.system.cac) { case 'tir':
armeData.system.unemain = armeData.system.unemain || !armeData.system.deuxmains; case 'lancer':
const uneOuDeuxMains = armeData.system.unemain && armeData.system.deuxmains; case 'competence':
const containsSlash = !Number.isInteger(armeData.system.dommages) && armeData.system.dommages.includes("/"); return Number(arme.system.dommages)
if (containsSlash) { // Sanity check
armeData = foundry.utils.duplicate(armeData);
const tableauDegats = armeData.system.dommages.split("/");
if (aUneMain)
armeData.system.dommagesReels = Number(tableauDegats[0]);
else // 2 mains
armeData.system.dommagesReels = Number(tableauDegats[1]);
}
else {
armeData.system.dommagesReels = Number(armeData.system.dommages);
}
if (uneOuDeuxMains != containsSlash) {
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + armeData.name + " ne sont pas corrects (ie sous la forme X/Y)");
}
} }
return armeData; if (arme.system.unemain && arme.system.deuxmains) {
const containsSlash = !Number.isInteger(arme.system.dommages) && arme.system.dommages.includes("/")
if (!containsSlash) {
ui.notifications.info("Les dommages de l'arme à 1/2 mains " + arme.name + " ne sont pas corrects (ie sous la forme X/Y)");
return Number(arme.system.dommages)
}
const tableauDegats = arme.system.dommages.split("/");
return Number(tableauDegats[maniement == 'unemain' ? 0 : 1])
}
return Number(arme.system.dommages);
} }
static competence2Mains(arme) {
return arme.system.competence.replace(" 1 main", " 2 mains"); /* -------------------------------------------- */
static armeUneOuDeuxMains(arme, aUneMain) {
if (arme && !arme.system.cac) {
arme = foundry.utils.duplicate(arme);
arme.system.dommagesReels = RdDItemArme.dommagesReels(arme, aUneMain ? 'unemain' : 'deuxmains')
}
return arme;
} }
static competence1Mains(arme) { static competence1Mains(arme) {
return arme.system.competence.replace(" 2 mains", " 1 main"); return arme.system.competence.replace(" 2 mains", " 1 main");
} }
static competence2Mains(arme) {
return arme.system.competence.replace(" 1 main", " 2 mains");
}
static isArmeUtilisable(arme) { static isArmeUtilisable(arme) {
switch (arme.type) { switch (arme.type) {
case TYPES.arme: return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0) case ITEM_TYPES.arme: return arme.system.equipe && (arme.system.resistance > 0 || arme.system.portee_courte > 0)
case TYPES.competencecreature: return true case ITEM_TYPES.competencecreature: return true
} }
return false return false
} }
@@ -180,11 +199,11 @@ export class RdDItemArme extends Item {
static corpsACorps(actor) { static corpsACorps(actor) {
let competence = actor?.getCompetenceCorpsACorps() ?? { system: { niveau: -6 } }; let competence = actor?.getCompetenceCorpsACorps() ?? { system: { niveau: -6 } };
let melee = actor? actor.system.carac['melee'].value : 0 let melee = actor ? actor.system.carac['melee'].value : 0
return { return {
_id: competence?.id, _id: competence?.id,
name: 'Corps à corps', name: 'Corps à corps',
type: TYPES.arme, type: ITEM_TYPES.arme,
img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp', img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp',
system: { system: {
initiative: RdDCombatManager.calculInitiative(competence.system.niveau, melee), initiative: RdDCombatManager.calculInitiative(competence.system.niveau, melee),

View File

@@ -1,4 +1,5 @@
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { RdDItem } from "./item.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
const competenceTroncs = [["Esquive", "Dague", "Corps à corps"], const competenceTroncs = [["Esquive", "Dague", "Corps à corps"],
@@ -23,12 +24,12 @@ const limitesArchetypes = [
]; ];
/* -------------------------------------------- */ /* -------------------------------------------- */
const categoriesCompetences = { export const CATEGORIES_COMPETENCES = {
"generale": { base: -4, label: "Générales" }, "generale": { base: -4, label: "Générales" },
"particuliere": { base: -8, label: "Particulières" }, "particuliere": { base: -8, label: "Particulières" },
"specialisee": { base: -11, label: "Spécialisées" }, "specialisee": { base: -11, label: "Spécialisées" },
"connaissance": { base: -11, label: "Connaissances" }, "connaissance": { base: -11, label: "Connaissances" },
"draconic": { base: -11, label: "Draconics" }, "draconic": { base: -11, label: "Draconic" },
"melee": { base: -6, label: "Mêlée" }, "melee": { base: -6, label: "Mêlée" },
"tir": { base: -8, label: "Tir" }, "tir": { base: -8, label: "Tir" },
"lancer": { base: -8, label: "Lancer" } "lancer": { base: -8, label: "Lancer" }
@@ -48,16 +49,14 @@ function _buildCumulXP() {
const competence_xp_cumul = _buildCumulXP(); const competence_xp_cumul = _buildCumulXP();
export class RdDItemCompetence extends Item { export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static getCategories() {
return categoriesCompetences;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static getLabelCategorie(category) { static getLabelCategorie(category) {
return categoriesCompetences[category].label; return CATEGORIES_COMPETENCES[category].label;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getNiveauBase(category, categories = categoriesCompetences) { /* -------------------------------------------- */
static getNiveauBase(category, itemType) {
let categories = RdDItem.getCategories(itemType)
return categories[category]?.base ?? 0; return categories[category]?.base ?? 0;
} }
@@ -191,7 +190,7 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isNiveauBase(item) { static isNiveauBase(item) {
return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie, item.getCategories()); return Number(item.system.niveau) == RdDItemCompetence.getNiveauBase(item.system.categorie, item.type);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@@ -1,8 +1,8 @@
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
import { RdDCombatManager } from "./rdd-combat.js"; import { RdDCombatManager } from "./rdd-combat.js";
const categories = { export const CATEGORIES_COMPETENCES_CREATURES = {
"generale": { base: 0, label: "Générale" }, "generale": { base: 0, label: "Générale" },
"naturelle": { base: 0, label: "Arme naturelle" }, "naturelle": { base: 0, label: "Arme naturelle" },
"melee": { base: 0, label: "Mêlée" }, "melee": { base: 0, label: "Mêlée" },
@@ -15,10 +15,6 @@ const categories = {
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDItemCompetenceCreature extends Item { export class RdDItemCompetenceCreature extends Item {
static getCategories() {
return categories;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static setRollDataCreature(rollData) { static setRollDataCreature(rollData) {
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } } rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.system.carac_value } }
@@ -54,7 +50,7 @@ export class RdDItemCompetenceCreature extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isCompetenceAttaque(item) { static isCompetenceAttaque(item) {
if (item.type == TYPES.competencecreature) { if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) { switch (item.system.categorie) {
case "melee": case "melee":
case "tir": case "tir":
@@ -68,7 +64,7 @@ export class RdDItemCompetenceCreature extends Item {
} }
static getCategorieAttaque(item) { static getCategorieAttaque(item) {
if (item.type == TYPES.competencecreature) { if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) { switch (item.system.categorie) {
case "melee": case "melee":
case "tir": case "tir":
@@ -82,7 +78,7 @@ export class RdDItemCompetenceCreature extends Item {
return undefined return undefined
} }
static isDommages(item) { static isDommages(item) {
if (item.type == TYPES.competencecreature) { if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) { switch (item.system.categorie) {
case "melee": case "melee":
case "tir": case "tir":
@@ -94,7 +90,7 @@ export class RdDItemCompetenceCreature extends Item {
return false return false
} }
static isParade(item) { static isParade(item) {
if (item.type == TYPES.competencecreature) { if (item.type == ITEM_TYPES.competencecreature) {
switch (item.system.categorie) { switch (item.system.categorie) {
case "melee": case "melee":
case "naturelle": case "naturelle":

View File

@@ -12,7 +12,7 @@ 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 { TYPES } from "./item.js"; import { ITEM_TYPES, RdDItem } from "./item.js";
/** /**
* Extend the basic ItemSheet for RdD specific items * Extend the basic ItemSheet for RdD specific items
@@ -53,7 +53,8 @@ export class RdDItemSheet extends ItemSheet {
} }
get title() { get title() {
return `${Misc.typeName('Item', this.item.type)}: ${this.item.name}`; const owner = (this.item.parent instanceof Actor) ? `(${this.item.parent.name})` : '';
return `${Misc.typeName('Item', this.item.type)}: ${this.item.name} ${owner}`;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -98,15 +99,15 @@ export class RdDItemSheet extends ItemSheet {
description: await TextEditor.enrichHTML(this.item.system.description, { async: true }), description: await TextEditor.enrichHTML(this.item.system.description, { async: true }),
descriptionmj: await TextEditor.enrichHTML(this.item.system.descriptionmj, { async: true }), descriptionmj: await TextEditor.enrichHTML(this.item.system.descriptionmj, { async: true }),
isComestible: this.item.getUtilisationCuisine(), isComestible: this.item.getUtilisationCuisine(),
options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable) options: RdDSheetUtility.mergeDocumentRights(this.options, this.item, this.isEditable),
} }
if (this.item.type == TYPES.competencecreature) { if (this.item.type == ITEM_TYPES.competencecreature) {
formData.isparade = RdDItemCompetenceCreature.isParade(this.item) formData.isparade = RdDItemCompetenceCreature.isParade(this.item)
formData.isdommages = RdDItemCompetenceCreature.isDommages(this.item) formData.isdommages = RdDItemCompetenceCreature.isDommages(this.item)
} }
const competences = await SystemCompendiums.getCompetences('personnage'); const competences = await SystemCompendiums.getCompetences('personnage');
formData.categories = this.item.getCategories() formData.categories = RdDItem.getCategories(this.item.type)
if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') { if (this.item.type == 'tache' || this.item.type == 'livre' || this.item.type == 'meditation' || this.item.type == 'oeuvre') {
formData.caracList = foundry.utils.duplicate(game.model.Actor.personnage.carac) formData.caracList = foundry.utils.duplicate(game.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.model.Actor.personnage.reve.reve) formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.model.Actor.personnage.reve.reve)
@@ -257,7 +258,7 @@ export class RdDItemSheet extends ItemSheet {
if (this.item.isCompetence()) { if (this.item.isCompetence()) {
const categorie = event.currentTarget.value; const categorie = event.currentTarget.value;
const level = RdDItemCompetence.getNiveauBase(categorie, this.item.getCategories()); const level = RdDItemCompetence.getNiveauBase(categorie, this.item.type);
this.item.system.base = level; this.item.system.base = level;
this.html.find('[name="system.base"]').val(level); this.html.find('[name="system.base"]').val(level);
} }

View File

@@ -1,9 +1,59 @@
import { Grammar } from "./grammar.js";
import { RdDItemCompetence } from "./item-competence.js";
import { ITEM_TYPES } from "./item.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
const VOIES_DRACONIC = [
{ code: 'O', label: "Voie d'Oniros", short: 'Oniros', ordre: 'a' },
{ code: 'H', label: "Voie d'Hypnos", short: 'Hypnos', ordre: 'b' },
{ code: 'N', label: "Voie de Narcos", short: 'Narcos', ordre: 'c' },
{ code: 'T', label: "Voie de Thanatos", short: 'Thanatos', ordre: 'd' },
{ code: 'O/H/N/T', label: "Oniros/Hypnos/Narcos/Thanatos", short: 'Oniros/Hypnos/Narcos/Thanatos', ordre: 'e' },
{ code: 'O/H/N', label: "Oniros/Hypnos/Narcos", short: "Oniros/Hypnos/Narcos", ordre: 'f' }
]
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDItemSort extends Item { export class RdDItemSort extends Item {
static getDraconicsSort(draconicList, sort) {
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
case "lecture d'aura":
case "detection d'aura":
return draconicList;
case "annulation de magie":
return draconicList.filter(it => !RdDItemCompetence.isThanatos(it));
}
return [RdDItemCompetence.getVoieDraconic(draconicList, sort.system.draconic)];
}
static getOrdreCode(code) {
return (VOIES_DRACONIC.find(it => it.code == code)?.ordre ?? '?')
}
static getVoieCode(voie) {
return VOIES_DRACONIC.find(it => voie.name.includes(it.short))?.code ?? '?'
}
static getCodeDraconic(sort, voies = ['O', 'H', 'N', 'T']) {
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
case "lecture d'aura":
case "detection d'aura":
return RdDItemSort.$voiesConnues('O/H/N/T', voies)
case "annulation de magie":
return RdDItemSort.$voiesConnues('O/H/N', voies)
}
const voie = VOIES_DRACONIC.find(it => it.label.includes(sort.system.draconic))
return voie?.code ?? sort.system.draconic
}
static $voiesConnues(voiesSort, voies) {
const codes = voies.filter(it => voiesSort.includes(it))
.sort(Misc.ascending(it => RdDItemSort.getOrdreCode(it)))
return Misc.join(codes ?? [''], '/');
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static isDifficulteVariable(sort) { static isDifficulteVariable(sort) {
return sort && (sort.system.difficulte.toLowerCase() == "variable"); return sort && (sort.system.difficulte.toLowerCase() == "variable");
@@ -31,9 +81,9 @@ export class RdDItemSort extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static buildBonusCaseList(bonuscase, newCase) { static buildBonusCaseList(bonuscase, newCase) {
const list = RdDItemSort._bonuscaseStringToList(bonuscase) const list = RdDItemSort.bonuscaseStringToList(bonuscase)
if (newCase) { if (newCase) {
return list.concat({ case: "Nouvelle", bonus: 0 }); list.push({ case: "Nouvelle", bonus: 0 })
} }
return list; return list;
} }
@@ -44,7 +94,7 @@ export class RdDItemSort extends Item {
*/ */
static getBonusCaseList(item, newCase = false) { static getBonusCaseList(item, newCase = false) {
// Gestion spéciale case bonus // Gestion spéciale case bonus
if (item.type == 'sort') { if (item.type == ITEM_TYPES.sort) {
return RdDItemSort.buildBonusCaseList(item.system.bonuscase, newCase); return RdDItemSort.buildBonusCaseList(item.system.bonuscase, newCase);
} }
return undefined; return undefined;
@@ -104,8 +154,11 @@ export class RdDItemSort extends Item {
.sort(Misc.ascending()) .sort(Misc.ascending())
.join(','); .join(',');
} }
static _bonuscaseStringToList(bonuscase) { static bonuscaseStringToList(bonuscase) {
return (bonuscase ?? '').split(',').map(it => { if (bonuscase == undefined || bonuscase == '') {
return []
}
return bonuscase.split(',').map(it => {
const b = it.split(':'); const b = it.split(':');
return { case: b[0], bonus: b[1] }; return { case: b[0], bonus: b[1] };
}); });

View File

@@ -6,10 +6,18 @@ 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";
import { RdDRaretes } from "./item/raretes.js"; import { RdDRaretes } from "./item/raretes.js";
import { RdDItemCompetence } from "./item-competence.js"; import { CATEGORIES_COMPETENCES } from "./item-competence.js";
import { RdDItemCompetenceCreature } from "./item-competencecreature.js"; import { CATEGORIES_COMPETENCES_CREATURES } from "./item-competencecreature.js";
export const TYPES = { export const ACTOR_TYPES = {
personnage: 'personnage',
creature: 'creature',
entite: 'entite',
commerce: 'commerce',
vehicule: 'vehicule'
}
export const ITEM_TYPES = {
competence: 'competence', competence: 'competence',
competencecreature: 'competencecreature', competencecreature: 'competencecreature',
empoignade: 'empoignade', empoignade: 'empoignade',
@@ -56,33 +64,33 @@ export const TYPES = {
} }
const typesInventaireMateriel = [ const typesInventaireMateriel = [
TYPES.arme, ITEM_TYPES.arme,
TYPES.armure, ITEM_TYPES.armure,
TYPES.conteneur, ITEM_TYPES.conteneur,
TYPES.faune, ITEM_TYPES.faune,
TYPES.gemme, ITEM_TYPES.gemme,
TYPES.herbe, ITEM_TYPES.herbe,
TYPES.plante, ITEM_TYPES.plante,
TYPES.ingredient, ITEM_TYPES.ingredient,
TYPES.livre, ITEM_TYPES.livre,
TYPES.monnaie, ITEM_TYPES.monnaie,
TYPES.munition, ITEM_TYPES.munition,
TYPES.nourritureboisson, ITEM_TYPES.nourritureboisson,
TYPES.objet, ITEM_TYPES.objet,
TYPES.potion, ITEM_TYPES.potion,
] ]
const typesInventaire = { const typesInventaire = {
materiel: typesInventaireMateriel, materiel: typesInventaireMateriel,
all: ['service'].concat(typesInventaireMateriel), all: ['service'].concat(typesInventaireMateriel),
} }
const typesObjetsOeuvres = [TYPES.oeuvre, TYPES.recettecuisine, TYPES.musique, TYPES.chant, TYPES.danse, TYPES.jeu] const typesObjetsOeuvres = [ITEM_TYPES.oeuvre, ITEM_TYPES.recettecuisine, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.jeu]
const typesObjetsDraconiques = [TYPES.queue, TYPES.ombre, TYPES.souffle, TYPES.tete, TYPES.signedraconique, TYPES.sortreserve, TYPES.rencontre] const typesObjetsDraconiques = [ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.tete, ITEM_TYPES.signedraconique, ITEM_TYPES.sortreserve, ITEM_TYPES.rencontre]
const typesObjetsConnaissance = [TYPES.meditation, TYPES.recettealchimique, TYPES.sort] const typesObjetsConnaissance = [ITEM_TYPES.meditation, ITEM_TYPES.recettealchimique, ITEM_TYPES.sort]
const typesObjetsEffet = [TYPES.possession, TYPES.poison, TYPES.maladie, TYPES.blessure] const typesObjetsEffet = [ITEM_TYPES.possession, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.blessure]
const typesObjetsCompetence = [TYPES.competence, TYPES.competencecreature] const typesObjetsCompetence = [ITEM_TYPES.competence, ITEM_TYPES.competencecreature]
const typesObjetsTemporels = [TYPES.blessure, TYPES.poison, TYPES.maladie, TYPES.queue, TYPES.ombre, TYPES.souffle, TYPES.signedraconique, TYPES.rencontre] const typesObjetsTemporels = [ITEM_TYPES.blessure, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.signedraconique, ITEM_TYPES.rencontre]
const typesObjetsEquipable = [TYPES.arme, TYPES.armure, 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 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
@@ -141,12 +149,12 @@ export class RdDItem extends Item {
static isFieldInventaireModifiable(type, field) { static isFieldInventaireModifiable(type, field) {
switch (field) { switch (field) {
case 'quantite': case 'quantite':
if ([TYPES.conteneur].includes(type)) { if ([ITEM_TYPES.conteneur].includes(type)) {
return false; return false;
} }
break; break;
case 'cout': case 'cout':
if ([TYPES.monnaie].includes(type)) { if ([ITEM_TYPES.monnaie].includes(type)) {
return game.user.isGM; return game.user.isGM;
} }
break; break;
@@ -164,9 +172,11 @@ export class RdDItem extends Item {
static getItemTypesInventaire(mode = 'materiel') { static getItemTypesInventaire(mode = 'materiel') {
return typesInventaire[mode ?? 'materiel'] return typesInventaire[mode ?? 'materiel']
} }
static getItemTypesDraconiques() { static getItemTypesDraconiques() {
return typesObjetsDraconiques; return typesObjetsDraconiques;
} }
static getItemTypesEnvironnement() { static getItemTypesEnvironnement() {
return typesEnvironnement; return typesEnvironnement;
} }
@@ -175,6 +185,16 @@ export class RdDItem extends Item {
return typesObjetsOeuvres return typesObjetsOeuvres
} }
static getCategories(itemType) {
switch (itemType) {
case ITEM_TYPES.competence:
return CATEGORIES_COMPETENCES
case ITEM_TYPES.competencecreature:
return CATEGORIES_COMPETENCES_CREATURES
}
return {}
}
constructor(docData, context = {}) { constructor(docData, context = {}) {
if (!context.rdd?.ready) { if (!context.rdd?.ready) {
foundry.utils.mergeObject(context, { rdd: { ready: true } }); foundry.utils.mergeObject(context, { rdd: { ready: true } });
@@ -189,20 +209,21 @@ export class RdDItem extends Item {
if (!docData.img) { if (!docData.img) {
docData.img = RdDItem.getDefaultImg(docData.type); docData.img = RdDItem.getDefaultImg(docData.type);
} }
context.rdd = undefined
super(docData, context); super(docData, context);
} }
getUniteQuantite() { getUniteQuantite() {
switch (this.type) { switch (this.type) {
case TYPES.monnaie: return "(Pièces)" case ITEM_TYPES.monnaie: return "(Pièces)"
case TYPES.herbe: case ITEM_TYPES.herbe:
switch (this.system.categorie) { switch (this.system.categorie) {
case 'Alchimie': case 'Repos': case 'Soin': case 'Alchimie': case 'Repos': case 'Soin':
return "(Brins)" return "(Brins)"
case 'Cuisine': return ''; case 'Cuisine': return '';
} }
return ''; return '';
case TYPES.ingredient: return "(Pépins ou Brins)" case ITEM_TYPES.ingredient: return "(Pépins ou Brins)"
} }
return ''; return '';
} }
@@ -211,13 +232,13 @@ export class RdDItem extends Item {
return typesObjetsEquipable.includes(this.type) return typesObjetsEquipable.includes(this.type)
} }
isCompetencePersonnage() { return this.type == TYPES.competence } isCompetencePersonnage() { return this.type == ITEM_TYPES.competence }
isCompetenceCreature() { return this.type == TYPES.competencecreature } isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature }
isConteneur() { return this.type == TYPES.conteneur; } isConteneur() { return this.type == ITEM_TYPES.conteneur; }
isMonnaie() { return this.type == TYPES.monnaie; } isMonnaie() { return this.type == ITEM_TYPES.monnaie; }
isPotion() { return this.type == TYPES.potion; } isPotion() { return this.type == ITEM_TYPES.potion; }
isNourritureBoisson() { return this.type == TYPES.nourritureboisson; } isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; }
isService() { return this.type == TYPES.service; } isService() { return this.type == ITEM_TYPES.service; }
isCompetence() { return typesObjetsCompetence.includes(this.type) } isCompetence() { return typesObjetsCompetence.includes(this.type) }
isEsquive() { isEsquive() {
@@ -236,30 +257,23 @@ export class RdDItem extends Item {
return this.isCompetence() && ['melee', 'tir', 'lancer'].includes(this.system.categorie) return this.isCompetence() && ['melee', 'tir', 'lancer'].includes(this.system.categorie)
} }
isCompetencePossession() { return TYPES.competencecreature == this.type && this.system.categorie == "possession" } isCompetencePossession() { return ITEM_TYPES.competencecreature == this.type && this.system.categorie == "possession" }
isTemporel() { return typesObjetsTemporels.includes(this.type) } isTemporel() { return typesObjetsTemporels.includes(this.type) }
isOeuvre() { return typesObjetsOeuvres.includes(this.type) } isOeuvre() { return typesObjetsOeuvres.includes(this.type) }
isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) } isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
isQueueDragon() { return [TYPES.queue, TYPES.ombre].includes(this.type) } isQueueDragon() { return [ITEM_TYPES.queue, ITEM_TYPES.ombre].includes(this.type) }
isEffet() { return typesObjetsEffet.includes(this.type) } isEffet() { return typesObjetsEffet.includes(this.type) }
isConnaissance() { return typesObjetsConnaissance.includes(this.type) } isConnaissance() { return typesObjetsConnaissance.includes(this.type) }
isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); } isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); }
isBoisson() { return this.isNourritureBoisson() && this.system.boisson; } isBoisson() { return this.isNourritureBoisson() && this.system.boisson; }
isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; } isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; }
isHerbeAPotion() { return this.type == TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); } isHerbeAPotion() { return this.type == ITEM_TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
isBlessure() { return this.type == TYPES.blessure } isBlessure() { return this.type == ITEM_TYPES.blessure }
isPresentDansMilieux(milieux) { isPresentDansMilieux(milieux) {
return this.getEnvironnements(milieux).length > 0 return this.getEnvironnements(milieux).length > 0
} }
getCategories() {
switch (this.type) {
case TYPES.competence: return RdDItemCompetence.getCategories()
case TYPES.competencecreature: return RdDItemCompetenceCreature.getCategories()
}
return {}
}
getEnvironnements(milieux = undefined) { getEnvironnements(milieux = undefined) {
const environnements = this.isInventaire() ? this.system.environnement : undefined; const environnements = this.isInventaire() ? this.system.environnement : undefined;
@@ -340,15 +354,15 @@ export class RdDItem extends Item {
getUtilisation() { getUtilisation() {
switch (this.type) { switch (this.type) {
case TYPES.potion: case ITEM_TYPES.potion:
switch (this.system.categorie) { switch (this.system.categorie) {
case 'Alchimie': case 'AlchimieEnchante': case 'AlchimieAutre': return 'alchimie' case 'Alchimie': case 'AlchimieEnchante': case 'AlchimieAutre': return 'alchimie'
case 'Cuisine': return 'cuisine' case 'Cuisine': return 'cuisine'
case 'Remede': case 'Repos': case 'ReposEnchante': case 'Soin': case 'SoinEnchante': return 'soins' case 'Remede': case 'Repos': case 'ReposEnchante': case 'Soin': case 'SoinEnchante': return 'soins'
} }
return ''; return '';
case TYPES.nourritureboisson: return 'cuisine'; case ITEM_TYPES.nourritureboisson: return 'cuisine';
case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case 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) {
case 'Cuisine': return 'cuisine'; case 'Cuisine': return 'cuisine';
case 'Toxique': case 'Poison': return 'poison'; case 'Toxique': case 'Poison': return 'poison';
@@ -363,9 +377,9 @@ export class RdDItem extends Item {
getUtilisationCuisine() { getUtilisationCuisine() {
if (this.getUtilisation() == 'cuisine') { if (this.getUtilisation() == 'cuisine') {
switch (this.type) { switch (this.type) {
case TYPES.nourritureboisson: case ITEM_TYPES.nourritureboisson:
return 'pret'; return 'pret';
case TYPES.herbe: case TYPES.faune: case TYPES.ingredient: case TYPES.plante: case ITEM_TYPES.herbe: case ITEM_TYPES.faune: case ITEM_TYPES.ingredient: case ITEM_TYPES.plante:
return 'brut'; return 'brut';
} }
} }
@@ -373,7 +387,7 @@ export class RdDItem extends Item {
} }
isCristalAlchimique() { isCristalAlchimique() {
return this.type == 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() { isMagique() {
@@ -401,11 +415,11 @@ export class RdDItem extends Item {
getEnc() { getEnc() {
switch (this.type) { switch (this.type) {
case TYPES.service: case ITEM_TYPES.service:
return 0; return 0;
case TYPES.herbe: case ITEM_TYPES.herbe:
return this.getEncHerbe(); return this.getEncHerbe();
case TYPES.gemme: case ITEM_TYPES.gemme:
return encPepin * this.system.taille; return encPepin * this.system.taille;
} }
return Math.max(this.system.encombrement ?? 0, 0); return Math.max(this.system.encombrement ?? 0, 0);
@@ -483,7 +497,7 @@ export class RdDItem extends Item {
getActionPrincipale(options = { warnIfNot: true }) { getActionPrincipale(options = { warnIfNot: true }) {
switch (this.type) { switch (this.type) {
case TYPES.conteneur: return 'Ouvrir'; case ITEM_TYPES.conteneur: return 'Ouvrir';
} }
if (this.actor?.isPersonnage()) { if (this.actor?.isPersonnage()) {
const warn = options.warnIfNot; const warn = options.warnIfNot;
@@ -491,11 +505,11 @@ export class RdDItem extends Item {
return 'Cuisiner'; return 'Cuisiner';
} }
switch (this.type) { switch (this.type) {
case TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn); case ITEM_TYPES.nourritureboisson: return this._actionOrWarnQuantiteZero(this.system.boisson ? 'Boire' : 'Manger', warn);
case TYPES.potion: return this._actionOrWarnQuantiteZero('Consommer', warn); case ITEM_TYPES.potion: return this._actionOrWarnQuantiteZero('Consommer', warn);
case TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn); case ITEM_TYPES.livre: return this._actionOrWarnQuantiteZero('Lire', warn);
case TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined; case ITEM_TYPES.herbe: return this.isHerbeAPotion() ? this._actionOrWarnQuantiteZero('Décoction', warn) : undefined;
case TYPES.queue: case TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined; case ITEM_TYPES.queue: case ITEM_TYPES.ombre: return this.system.refoulement > 0 ? 'Refouler' : undefined;
} }
} }
return undefined; return undefined;

View File

@@ -2,7 +2,7 @@ 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, TYPES } from "./item.js"; import { RdDItem, ITEM_TYPES } 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 { RdDCalendrier } from "./time/rdd-calendrier.js"; import { RdDCalendrier } from "./time/rdd-calendrier.js";
@@ -465,7 +465,7 @@ class _10_7_19_CategorieCompetenceCreature extends Migration {
async migrate() { async migrate() {
await this.applyItemsUpdates(items => items await this.applyItemsUpdates(items => items
.filter(it => TYPES.competencecreature == it.type) .filter(it => ITEM_TYPES.competencecreature == it.type)
.map(it => this.migrateCompetenceCreature(it)) .map(it => this.migrateCompetenceCreature(it))
); );
} }
@@ -502,7 +502,7 @@ class _10_7_19_PossessionsEntiteVictime extends Migration {
async migrate() { async migrate() {
await this.applyItemsUpdates(items => items await this.applyItemsUpdates(items => items
.filter(it => TYPES.possession == it.type) .filter(it => ITEM_TYPES.possession == it.type)
.map(it => this.migratePossession(it)) .map(it => this.migratePossession(it))
); );
} }
@@ -569,7 +569,7 @@ export class Migrations {
} }
if (foundry.utils.isNewerVersion(game.system.version, currentVersion)) { if (foundry.utils.isNewerVersion(game.system.version, currentVersion)) {
// if (true) { /* comment previous and uncomment here to test before upgrade */ // if (true) { /* comment previous and uncomment here to test before upgrade */
const migrations = Migrations.getMigrations().filter(m => isNewerVersion(m.version, currentVersion)); const migrations = Migrations.getMigrations().filter(m => foundry.utils.isNewerVersion(m.version, currentVersion));
if (migrations.length > 0) { if (migrations.length > 0) {
migrations.sort((a, b) => this.compareVersions(a, b)); migrations.sort((a, b) => this.compareVersions(a, b));
migrations.forEach(async (m) => { migrations.forEach(async (m) => {

View File

@@ -166,8 +166,12 @@ export class Misc {
} }
static firstConnectedGM() { static firstConnectedGM() {
return game.users.sort(Misc.ascending(u => u.id)).find(u => u.isGM && u.active); if (foundry.utils.isNewerVersion(game.release.version, '12.0')) {
return game.users.activeGM
}
return game.users.find(u => u.isGM && u.active);
} }
static connectedGMs() { static connectedGMs() {
return game.users.filter(u => u.isGM && u.active); return game.users.filter(u => u.isGM && u.active);
} }
@@ -185,16 +189,20 @@ export class Misc {
* and there is no connected GM * and there is no connected GM
*/ */
static documentIfResponsible(document) { static documentIfResponsible(document) {
if (document instanceof Document) { if (foundry.utils.isNewerVersion(game.release.version, '12.0')) {
if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) { if (game.users.activeGM || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document)))
{
return document return document
} }
} }
else if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) {
return document
}
return undefined return undefined
} }
static isOwnerPlayer(actor) { static isOwnerPlayer(document) {
return actor.testUserPermission(game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER) return document.testUserPermission && document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
} }
static isOwnerPlayerOrUniqueConnectedGM(actor) { static isOwnerPlayerOrUniqueConnectedGM(actor) {

View File

@@ -15,7 +15,7 @@ export class RdDAudio {
if ( audioData ) { if ( audioData ) {
let audioPath = "systems/foundryvtt-reve-de-dragon/sounds/" + audioData.file; let audioPath = "systems/foundryvtt-reve-de-dragon/sounds/" + audioData.file;
console.log(`foundryvtt-reve-de-dragon | Playing Sound: ${audioPath}`) console.log(`foundryvtt-reve-de-dragon | Playing Sound: ${audioPath}`)
AudioHelper.play({ src: audioPath }, audioData.isGlobal); foundry.audio.AudioHelper.play({ src: audioPath }, audioData.isGlobal);
} }
} }
} }

View File

@@ -31,8 +31,8 @@ export class RdDBonus {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static dmg(rollData, dmgActor, isEntiteIncarnee = false) { static dmg(rollData, actor, isEntiteIncarnee = false) {
const dmgArme = RdDBonus._dmgArme(rollData) const dmgArme = RdDBonus.dmgArme(rollData.arme)
let dmg = { let dmg = {
total: 0, total: 0,
dmgArme: dmgArme, dmgArme: dmgArme,
@@ -41,7 +41,7 @@ export class RdDBonus {
dmgParticuliere: RdDBonus._dmgParticuliere(rollData), dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris.used), dmgSurprise: RdDBonus.dmgBonus(rollData.ajustements?.attaqueDefenseurSurpris.used),
mortalite: RdDBonus._calculMortalite(rollData, isEntiteIncarnee), mortalite: RdDBonus._calculMortalite(rollData, isEntiteIncarnee),
dmgActor: RdDBonus._dmgPerso(dmgActor, rollData.selectedCarac?.label, dmgArme) dmgActor: RdDBonus.bonusDmg(actor, rollData.selectedCarac?.label.toLowerCase(), dmgArme)
} }
dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere; dmg.total = dmg.dmgSurprise + dmg.dmgTactique + dmg.dmgArme + dmg.dmgActor + dmg.dmgParticuliere;
return dmg; return dmg;
@@ -71,11 +71,11 @@ export class RdDBonus {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _dmgArme(rollData) { static dmgArme(arme) {
if (rollData.arme) { if (arme) {
let dmgBase = rollData.arme.system.dommagesReels ?? Number(rollData.arme.system.dommages ?? 0); let dmgBase = arme.system.dommagesReels ?? Number(arme.system.dommages ?? 0);
//Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278) //Le bonus dégats magiques ne peut pas faire dépasser le bonus de l'arme (cf p.278)
return dmgBase + Math.min(dmgBase, rollData.arme.system.magique ? rollData.arme.system.ecaille_efficacite : 0); return dmgBase + Math.min(dmgBase, arme.system.magique ? arme.system.ecaille_efficacite : 0);
} }
return 0; return 0;
} }
@@ -86,13 +86,14 @@ export class RdDBonus {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _dmgPerso(dmgActor, categorie, dmgArme) { static bonusDmg(actor, categorie, dmgArme) {
const dmgActor = actor.getBonusDegat()
if (categorie == undefined) { if (categorie == undefined) {
return 0 return 0
} }
switch (categorie) { switch (categorie) {
case "Tir": return 0; case "tir": return 0;
case "Lancer": return Math.max(0, Math.min(dmgArme, dmgActor)); case "lancer": return Math.max(0, Math.min(dmgArme, dmgActor));
} }
return dmgActor; return dmgActor;
} }

View File

@@ -3,38 +3,38 @@ import { Misc } from "./misc.js";
const TABLE_CARACTERISTIQUES_DERIVEES = { const TABLE_CARACTERISTIQUES_DERIVEES = {
// xp: coût pour passer du niveau inférieur à ce niveau // xp: coût pour passer du niveau inférieur à ce niveau
1: { xp: 3, poids: "moins de 1kg", plusdom: -5, sconst: 0.5, sust: 0.1 }, 1: { xp: 3, poids: "moins de 1kg", poidsMin: 0, poidsMax: 1, plusdom: -5, sconst: 0.5, sust: 0.1 },
2: { xp: 3, poids: "1-5", plusdom: -4, sconst: 0.5, sust: 0.3 }, 2: { xp: 3, poids: "1-5", poidsMin: 1, poidsMax: 5, plusdom: -4, sconst: 0.5, sust: 0.3 },
3: { xp: 4, poids: "6-10", plusdom: -3, sconst: 1, sust: 0.5, beaute: 'hideux' }, 3: { xp: 4, poids: "6-10", poidsMin: 6, poidsMax: 10, plusdom: -3, sconst: 1, sust: 0.5, beaute: 'hideux' },
4: { xp: 4, poids: "11-20", plusdom: -3, sconst: 1, sust: 1, beaute: 'repoussant' }, 4: { xp: 4, poids: "11-20", poidsMin: 11, poidsMax: 20, plusdom: -3, sconst: 1, sust: 1, beaute: 'repoussant' },
5: { xp: 5, poids: "21-30", plusdom: -2, sconst: 1, sust: 1, beaute: 'franchement très laid' }, 5: { xp: 5, poids: "21-30", poidsMin: 21, poidsMax: 30, plusdom: -2, sconst: 1, sust: 1, beaute: 'franchement très laid' },
6: { xp: 5, poids: "31-40", plusdom: -1, sconst: 2, sust: 2, beaute: 'laid' }, 6: { xp: 5, poids: "31-40", poidsMin: 31, poidsMax: 40, plusdom: -1, sconst: 2, sust: 2, beaute: 'laid' },
7: { xp: 6, poids: "41-50", plusdom: -1, sconst: 2, sust: 2, beaute: 'très désavantagé' }, 7: { xp: 6, poids: "41-50", poidsMin: 41, poidsMax: 50, plusdom: -1, sconst: 2, sust: 2, beaute: 'très désavantagé' },
8: { xp: 6, poids: "51-60", plusdom: 0, sconst: 2, sust: 2, beaute: 'désavantagé' }, 8: { xp: 6, poids: "51-60", poidsMin: 51, poidsMax: 60, plusdom: 0, sconst: 2, sust: 2, beaute: 'désavantagé' },
9: { xp: 7, poids: "61-65", plusdom: 0, sconst: 3, sust: 2, beaute: 'pas terrible' }, 9: { xp: 7, poids: "61-65", poidsMin: 61, poidsMax: 65, plusdom: 0, sconst: 3, sust: 2, beaute: 'pas terrible' },
10: { xp: 7, poids: "66-70", plusdom: 0, sconst: 3, sust: 3, beaute: 'commun' }, 10: { xp: 7, poids: "66-70", poidsMin: 66, poidsMax: 70, plusdom: 0, sconst: 3, sust: 3, beaute: 'commun' },
11: { xp: 8, poids: "71-75", plusdom: 0, sconst: 3, sust: 3, beaute: 'pas mal' }, 11: { xp: 8, poids: "71-75", poidsMin: 71, poidsMax: 75, plusdom: 0, sconst: 3, sust: 3, beaute: 'pas mal' },
12: { xp: 8, poids: "76-80", plusdom: +1, sconst: 4, sust: 3, beaute: 'avantagé' }, 12: { xp: 8, poids: "76-80", poidsMin: 76, poidsMax: 80, plusdom: +1, sconst: 4, sust: 3, beaute: 'avantagé' },
13: { xp: 9, poids: "81-90", plusdom: +1, sconst: 4, sust: 3, beaute: 'mignon' }, 13: { xp: 9, poids: "81-90", poidsMin: 81, poidsMax: 90, plusdom: +1, sconst: 4, sust: 3, beaute: 'mignon' },
14: { xp: 9, poids: "91-100", plusdom: +2, sconst: 4, sust: 4, beaute: 'beau' }, 14: { xp: 9, poids: "91-100", poidsMin: 91, poidsMax: 100, plusdom: +2, sconst: 4, sust: 4, beaute: 'beau' },
15: { xp: 10, poids: "101-110", plusdom: +2, sconst: 5, sust: 4, beaute: 'très beau' }, 15: { xp: 10, poids: "101-110", poidsMin: 101, poidsMax: 110, plusdom: +2, sconst: 5, sust: 4, beaute: 'très beau' },
16: { xp: 20, poids: "111-120", plusdom: +3, sconst: 5, sust: 4, beaute: 'éblouissant' }, 16: { xp: 20, poids: "111-120", poidsMin: 111, poidsMax: 120, plusdom: +3, sconst: 5, sust: 4, beaute: 'éblouissant' },
17: { xp: 30, poids: "121-131", plusdom: +3, sconst: 5, sust: 5 }, 17: { xp: 30, poids: "121-131", poidsMin: 121, poidsMax: 131, plusdom: +3, sconst: 5, sust: 5 },
18: { xp: 40, poids: "131-141", plusdom: +4, sconst: 6, sust: 5 }, 18: { xp: 40, poids: "131-141", poidsMin: 131, poidsMax: 141, plusdom: +4, sconst: 6, sust: 5 },
19: { xp: 50, poids: "141-150", plusdom: +4, sconst: 6, sust: 5 }, 19: { xp: 50, poids: "141-150", poidsMin: 141, poidsMax: 150, plusdom: +4, sconst: 6, sust: 5 },
20: { xp: 60, poids: "151-160", plusdom: +4, sconst: 6, sust: 6 }, 20: { xp: 60, poids: "151-160", poidsMin: 151, poidsMax: 160, plusdom: +4, sconst: 6, sust: 6 },
21: { xp: 70, poids: "161-180", plusdom: +5, sconst: 7, sust: 6 }, 21: { xp: 70, poids: "161-180", poidsMin: 161, poidsMax: 180, plusdom: +5, sconst: 7, sust: 6 },
22: { xp: 80, poids: "181-200", plusdom: +5, sconst: 7, sust: 7 }, 22: { xp: 80, poids: "181-200", poidsMin: 181, poidsMax: 200, plusdom: +5, sconst: 7, sust: 7 },
23: { xp: 90, poids: "201-300", plusdom: +6, sconst: 7, sust: 8 }, 23: { xp: 90, poids: "201-300", poidsMin: 201, poidsMax: 300, plusdom: +6, sconst: 7, sust: 8 },
24: { xp: 100, poids: "301-400", plusdom: +6, sconst: 8, sust: 9 }, 24: { xp: 100, poids: "301-400", poidsMin: 301, poidsMax: 400, plusdom: +6, sconst: 8, sust: 9 },
25: { xp: 110, poids: "401-500", plusdom: +7, sconst: 8, sust: 10 }, 25: { xp: 110, poids: "401-500", poidsMin: 401, poidsMax: 500, plusdom: +7, sconst: 8, sust: 10 },
26: { xp: 120, poids: "501-600", plusdom: +7, sconst: 8, sust: 11 }, 26: { xp: 120, poids: "501-600", poidsMin: 501, poidsMax: 600, plusdom: +7, sconst: 8, sust: 11 },
27: { xp: 130, poids: "601-700", plusdom: +8, sconst: 9, sust: 12 }, 27: { xp: 130, poids: "601-700", poidsMin: 601, poidsMax: 700, plusdom: +8, sconst: 9, sust: 12 },
28: { xp: 140, poids: "701-800", plusdom: +8, sconst: 9, sust: 13 }, 28: { xp: 140, poids: "701-800", poidsMin: 701, poidsMax: 800, plusdom: +8, sconst: 9, sust: 13 },
29: { xp: 150, poids: "801-900", plusdom: +9, sconst: 9, sust: 14 }, 29: { xp: 150, poids: "801-900", poidsMin: 801, poidsMax: 900, plusdom: +9, sconst: 9, sust: 14 },
30: { xp: 160, poids: "901-1000", plusdom: +9, sconst: 10, sust: 15 }, 30: { xp: 160, poids: "901-1000", poidsMin: 901, poidsMax: 1000, plusdom: +9, sconst: 10, sust: 15 },
31: { xp: 170, poids: "1001-1500", plusdom: +10, sconst: 10, sust: 16 }, 31: { xp: 170, poids: "1001-1500", poidsMin: 1001, poidsMax: 1500, plusdom: +10, sconst: 10, sust: 16 },
32: { xp: 180, poids: "1501-2000", plusdom: +11, sconst: 10, sust: 17 } 32: { xp: 180, poids: "1501-2000", poidsMin: 1501, poidsMax: 2000, plusdom: +11, sconst: 10, sust: 17 }
}; };
export class RdDCarac { export class RdDCarac {

View File

@@ -75,6 +75,12 @@ export class RdDCombatManager extends Combat {
} }
} }
} }
static calculAjustementInit(actor, arme) {
const efficacite = (arme?.system.magique) ? arme.system.ecaille_efficacite : 0
const etatGeneral = actor.getEtatGeneral() ?? 0
return efficacite + etatGeneral
}
/************************************************************************************/ /************************************************************************************/
async rollInitiative(ids, formula = undefined, messageOptions = {}) { async rollInitiative(ids, formula = undefined, messageOptions = {}) {
@@ -84,12 +90,14 @@ export class RdDCombatManager extends Combat {
// calculate initiative // calculate initiative
for (let cId = 0; cId < ids.length; cId++) { for (let cId = 0; cId < ids.length; cId++) {
const combatant = this.combatants.get(ids[cId]); const combatant = this.combatants.get(ids[cId]);
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, 0); const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, undefined);
let rollFormula = formula ?? RdDCombatManager.formuleInitiative(2, 10, 0, ajustement);
if (!formula) { if (!formula) {
if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') { if (combatant.actor.type == 'creature' || combatant.actor.type == 'entite') {
const competence = combatant.actor.items.find(it => RdDItemCompetenceCreature.isCompetenceAttaque(it)) const competence = combatant.actor.items.find(it => RdDItemCompetenceCreature.isCompetenceAttaque(it))
if (competence) { if (competence) {
rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, 0); rollFormula = RdDCombatManager.formuleInitiative(2, competence.system.carac_value, competence.system.niveau, etatGeneral);
} }
} else { } else {
const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe) const armeCombat = combatant.actor.itemTypes['arme'].find(it => it.system.equipe)
@@ -109,8 +117,9 @@ export class RdDCombatManager extends Combat {
if (competence && competence.system.defaut_carac) { if (competence && competence.system.defaut_carac) {
const carac = combatant.actor.system.carac[competence.system.defaut_carac].value; const carac = combatant.actor.system.carac[competence.system.defaut_carac].value;
const niveau = competence.system.niveau; const niveau = competence.system.niveau;
const bonusEcaille = (armeCombat?.system.magique) ? armeCombat.system.ecaille_efficacite : 0;
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, bonusEcaille); const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, armeCombat)
rollFormula = RdDCombatManager.formuleInitiative(2, carac, niveau, ajustement);
} else { } else {
ui.notifications.warn(`Votre arme ${armeCombat.name} n'a pas de compétence renseignée`); ui.notifications.warn(`Votre arme ${armeCombat.name} n'a pas de compétence renseignée`);
} }
@@ -214,13 +223,16 @@ export class RdDCombatManager extends Combat {
static $prepareAttaqueArme(infoAttaque) { static $prepareAttaqueArme(infoAttaque) {
const comp = infoAttaque.competences.find(c => c.name == infoAttaque.competence); const comp = infoAttaque.competences.find(c => c.name == infoAttaque.competence);
const attaque = foundry.utils.duplicate(infoAttaque.arme); const arme = infoAttaque.arme;
const attaque = foundry.utils.duplicate(arme);
attaque.action = 'attaque'; attaque.action = 'attaque';
attaque.system.competence = infoAttaque.competence; attaque.system.competence = infoAttaque.competence;
attaque.system.dommagesReels = infoAttaque.dommagesReel; attaque.system.dommagesReels = infoAttaque.dommagesReel;
attaque.system.infoMain = infoAttaque.infoMain; attaque.system.infoMain = infoAttaque.infoMain;
attaque.system.niveau = comp.system.niveau; attaque.system.niveau = comp.system.niveau;
attaque.system.initiative = RdDCombatManager.calculInitiative(comp.system.niveau, infoAttaque.carac[comp.system.defaut_carac].value);
const ajustement = (arme?.parent?.getEtatGeneral() ?? 0) + (arme?.system.magique) ? arme.system.ecaille_efficacite : 0;
attaque.system.initiative = RdDCombatManager.calculInitiative(comp.system.niveau, infoAttaque.carac[comp.system.defaut_carac].value, ajustement);
return attaque; return attaque;
} }
@@ -335,7 +347,6 @@ export class RdDCombatManager extends Combat {
ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`) ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
return []; return [];
} }
let initInfo = ""; let initInfo = "";
let initOffset = 0; let initOffset = 0;
let caracForInit = 0; let caracForInit = 0;
@@ -370,9 +381,9 @@ export class RdDCombatManager extends Combat {
initOffset = RdDCombatManager._baseInitOffset(compData.system.categorie, action); initOffset = RdDCombatManager._baseInitOffset(compData.system.categorie, action);
} }
let malus = combatant.actor.getEtatGeneral(); // Prise en compte état général
// Cas des créatures et entités vs personnages // Cas des créatures et entités vs personnages
let rollFormula = RdDCombatManager.formuleInitiative(initOffset, caracForInit, compNiveau, malus); const ajustement = RdDCombatManager.calculAjustementInit(combatant.actor, action)
let rollFormula = RdDCombatManager.formuleInitiative(initOffset, caracForInit, compNiveau, ajustement);
// Garder la trace de l'arme/compétence utilisée pour l'iniative // Garder la trace de l'arme/compétence utilisée pour l'iniative
combatant.initiativeData = { arme: action } // pour reclasser l'init au round 0 combatant.initiativeData = { arme: action } // pour reclasser l'init au round 0
game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo }); game.combat.rollInitiative(combatantId, rollFormula, { initInfo: initInfo });
@@ -787,7 +798,7 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
_prepareAttaque(competence, arme) { _prepareAttaque(competence, arme) {
let rollData = { let rollData = {
passeArme: randomID(16), passeArme: foundry.utils.randomID(16),
mortalite: arme?.system.mortalite, mortalite: arme?.system.mortalite,
competence: competence, competence: competence,
surprise: this.attacker.getSurprise(true), surprise: this.attacker.getSurprise(true),
@@ -853,7 +864,7 @@ export class RdDCombat {
async _onAttaqueNormale(attackerRoll) { async _onAttaqueNormale(attackerRoll) {
console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll); console.log("RdDCombat.onAttaqueNormale >>>", attackerRoll);
attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker.getBonusDegat(), this.defender.isEntite()); attackerRoll.dmg = RdDBonus.dmg(attackerRoll, this.attacker, this.defender.isEntite());
let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} } let defenderRoll = { attackerRoll: attackerRoll, passeArme: attackerRoll.passeArme, show: {} }
attackerRoll.show = { attackerRoll.show = {
cible: this.target ? this.defender.name : 'la cible', cible: this.target ? this.defender.name : 'la cible',

View File

@@ -81,7 +81,7 @@ export class RdDCommands {
this.registerCommand({ path: ["/sommeil"], func: (content, msg, params) => this.sommeil(msg, params), descr: "Prépare le passage de journée pour chateau dormant" }); this.registerCommand({ path: ["/sommeil"], func: (content, msg, params) => this.sommeil(msg, params), descr: "Prépare le passage de journée pour chateau dormant" });
this.registerCommand({ path: ["/meteo"], func: (content, msg, params) => this.getMeteo(msg, params), descr: "Propose une météo marine" }); this.registerCommand({ path: ["/meteo"], func: (content, msg, params) => this.getMeteo(msg, params), descr: "Propose une météo marine" });
this.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.getName(msg, params), descr: "Génère un nom aléatoire" }); this.registerCommand({ path: ["/nom"], func: (content, msg, params) => RdDNameGen.proposeName(msg, params), descr: "Génère un nom aléatoire" });
this.registerCommand({ this.registerCommand({
path: ["/tmr"], func: (content, msg, params) => this.findTMR(msg, params), path: ["/tmr"], func: (content, msg, params) => this.findTMR(msg, params),

View File

@@ -1,9 +1,11 @@
import { Grammar } from "./grammar.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
export class RdDConfirm { export class RdDConfirm {
/* -------------------------------------------- */ /* -------------------------------------------- */
static confirmer(options, autresActions) { static confirmer(options, autresActions) {
if (options.settingConfirmer && !ReglesOptionnelles.isSet(options.settingConfirmer)) {
return options.onAction()
}
let buttons = { let buttons = {
"action": RdDConfirm._createButtonAction(options), "action": RdDConfirm._createButtonAction(options),
"cancel": RdDConfirm._createButtonCancel() "cancel": RdDConfirm._createButtonCancel()

View File

@@ -36,8 +36,8 @@ export class DeTMR extends Die {
super(termData); super(termData);
} }
async evaluate() { async evaluate(options) {
super.evaluate(); await super.evaluate(options);
this.explode("x=8"); this.explode("x=8");
return this; return this;
} }
@@ -73,8 +73,8 @@ export class DeDraconique extends Die {
super(termData); super(termData);
} }
async evaluate() { async evaluate(options) {
super.evaluate(); await super.evaluate(options);
this.explode("x=7"); this.explode("x=7");
return this; return this;
} }
@@ -132,6 +132,10 @@ export class RdDDice {
} }
} }
static async rollHeure(options = { showDice: HIDE_DICE }) {
return await RdDDice.rollTotal("1dh", options) - 1
}
static async rollTotal(formula, options = { showDice: HIDE_DICE }) { static async rollTotal(formula, options = { showDice: HIDE_DICE }) {
return (await RdDDice.roll(formula, options)).total; return (await RdDDice.roll(formula, options)).total;
} }

View File

@@ -5,7 +5,7 @@ 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 { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -92,18 +92,18 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isEmpoignadeEnCours(actor) { static isEmpoignadeEnCours(actor) {
return actor.itemTypes[TYPES.empoignade].find(it => it.system.pointsemp > 0) return actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.pointsemp > 0)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getEmpoignadeById(actor, id) { static getEmpoignadeById(actor, id) {
let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id) let emp = actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id)
return emp && foundry.utils.duplicate(emp) || undefined; return emp && foundry.utils.duplicate(emp) || undefined;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getEmpoignade(attacker, defender) { static getEmpoignade(attacker, defender) {
let emp = attacker.itemTypes[TYPES.empoignade].find(it => let emp = attacker.itemTypes[ITEM_TYPES.empoignade].find(it =>
(it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) || (it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) ||
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id) (it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
) )
@@ -248,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, attacker, 'chat-empoignade-resultat.html'); let msg = await RdDResolutionTable.displayRollData(rollData, defender, 'chat-empoignade-resultat.html');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
@@ -427,7 +427,7 @@ export class RdDEmpoignade {
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", img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
system: { description: "", empoignadeid: 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 }
}, },
{ {
temporary: true temporary: true

View File

@@ -6,7 +6,7 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js";
export class RdDHerbes extends Item { export class RdDHerbes extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async initializeHerbes() { static async onReady() {
this.herbesSoins = await RdDHerbes.listCategorieHerbes('Soin'); this.herbesSoins = await RdDHerbes.listCategorieHerbes('Soin');
this.herbesRepos = await RdDHerbes.listCategorieHerbes('Repos'); this.herbesRepos = await RdDHerbes.listCategorieHerbes('Repos');
} }

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 { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
export class RdDHotbar { export class RdDHotbar {
@@ -35,7 +35,7 @@ export class RdDHotbar {
static async addToHotbar(item, slot) { static async addToHotbar(item, slot) {
switch (item?.type ?? '') { switch (item?.type ?? '') {
case TYPES.arme: case ITEM_TYPES.arme:
{ {
// Les armes peuvent avoir plusieurs usages // Les armes peuvent avoir plusieurs usages
if (item.system.competence != '') { if (item.system.competence != '') {
@@ -54,12 +54,12 @@ export class RdDHotbar {
} }
} }
return return
case TYPES.competencecreature: case ITEM_TYPES.competencecreature:
const categorie = RdDItemCompetenceCreature.getCategorieAttaque(item) ?? 'competence'; const categorie = RdDItemCompetenceCreature.getCategorieAttaque(item) ?? 'competence';
await this.createItemMacro(item, slot, categorie) await this.createItemMacro(item, slot, categorie)
return return
default: default:
case TYPES.competence: case ITEM_TYPES.competence:
await this.createItemMacro(item, slot++, 'competence') await this.createItemMacro(item, slot++, 'competence')
if (item.isCorpsACorps()) { if (item.isCorpsACorps()) {
await this.createItemMacro(item, slot++, 'pugilat') await this.createItemMacro(item, slot++, 'pugilat')
@@ -79,7 +79,7 @@ export class RdDHotbar {
* Actor - open actor sheet * Actor - open actor sheet
* Journal - open journal sheet * Journal - open journal sheet
*/ */
static initDropbar() { static init() {
Hooks.on('hotbarDrop', (bar, documentData, slot) => { Hooks.on('hotbarDrop', (bar, documentData, slot) => {
@@ -88,9 +88,9 @@ export class RdDHotbar {
const item = fromUuidSync(documentData.uuid) ?? this.actor.items.get(documentData.uuid) const item = fromUuidSync(documentData.uuid) ?? this.actor.items.get(documentData.uuid)
console.log('DROP', documentData, item) console.log('DROP', documentData, item)
switch (item?.type) { switch (item?.type) {
case TYPES.arme: case ITEM_TYPES.arme:
case TYPES.competence: case ITEM_TYPES.competence:
case TYPES.competencecreature: case ITEM_TYPES.competencecreature:
this.addToHotbar(item, slot) this.addToHotbar(item, slot)
return false return false
} }
@@ -116,9 +116,9 @@ export class RdDHotbar {
// Trigger the item roll // Trigger the item roll
switch (item.type) { switch (item.type) {
case TYPES.arme: case ITEM_TYPES.arme:
return actor.rollArme(item, categorieArme); return actor.rollArme(item, categorieArme);
case TYPES.competence: case ITEM_TYPES.competence:
if (item.isCorpsACorps()) { if (item.isCorpsACorps()) {
switch (categorieArme) { switch (categorieArme) {
case 'pugilat': case 'pugilat':
@@ -128,7 +128,7 @@ export class RdDHotbar {
} }
} }
return actor.rollCompetence(item); return actor.rollCompetence(item);
case TYPES.competencecreature: case ITEM_TYPES.competencecreature:
return item.system.iscombat && !item.system.isparade return item.system.iscombat && !item.system.isparade
? actor.rollArme(item, categorieArme) ? actor.rollArme(item, categorieArme)
: actor.rollCompetence(item); : actor.rollCompetence(item);

View File

@@ -1,69 +1,73 @@
import { SYSTEM_RDD, SYSTEM_SOCKET_ID, RDD_CONFIG } from "./constants.js"; import { SYSTEM_RDD, SYSTEM_SOCKET_ID, RDD_CONFIG } from "./constants.js"
import { Migrations } from './migrations.js'; import { Migrations } from './migrations.js'
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js"
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js"
import { TMRRencontres } from "./tmr-rencontres.js"; import { TMRRencontres } from "./tmr-rencontres.js"
import { RdDCalendrier } from "./time/rdd-calendrier.js"; import { RdDCalendrier } from "./time/rdd-calendrier.js"
import { RdDTimestamp } from "./time/rdd-timestamp.js"; import { RdDTimestamp } from "./time/rdd-timestamp.js"
import { DialogChronologie } from "./dialog-chronologie.js"; import { DialogChronologie } from "./dialog-chronologie.js"
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js"
import { RdDTokenHud } from "./rdd-token-hud.js"; import { RdDTokenHud } from "./rdd-token-hud.js"
import { RdDCommands } from "./rdd-commands.js"; import { RdDCommands } from "./rdd-commands.js"
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js"; import { RdDCombatManager, RdDCombat } from "./rdd-combat.js"
import { ChatUtility } from "./chat-utility.js"; import { ChatUtility } from "./chat-utility.js"
import { StatusEffects } from "./settings/status-effects.js"; import { StatusEffects } from "./settings/status-effects.js"
import { RdDCompendiumOrganiser } from "./rdd-compendium-organiser.js"; 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 { 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"
import { SystemCompendiums } from "./settings/system-compendiums.js"; import { SystemCompendiums } from "./settings/system-compendiums.js"
import { Environnement } from "./environnement.js"; import { Environnement } from "./environnement.js"
import { RdDActor } from "./actor.js"; import { RdDActor } from "./actor.js"
import { RdDBaseActor } from "./actor/base-actor.js"; import { RdDBaseActor } from "./actor/base-actor.js"
import { RdDCommerce } from "./actor/commerce.js"; import { RdDCommerce } from "./actor/commerce.js"
import { RdDEntite } from "./actor/entite.js"; import { RdDEntite } from "./actor/entite.js"
import { RdDVehicule } from "./actor/vehicule.js"; import { RdDVehicule } from "./actor/vehicule.js"
import { RdDActorSheet } from "./actor-sheet.js"; import { RdDActorSheet } from "./actor-sheet.js"
import { RdDCommerceSheet } from "./actor/commerce-sheet.js"; import { RdDCommerceSheet } from "./actor/commerce-sheet.js"
import { RdDCreatureSheet } from "./actor/creature-sheet.js"; import { RdDCreatureSheet } from "./actor/creature-sheet.js"
import { RdDActorEntiteSheet } from "./actor/entite-sheet.js"; import { RdDActorEntiteSheet } from "./actor/entite-sheet.js"
import { RdDActorVehiculeSheet } from "./actor/vehicule-sheet.js"; import { RdDActorVehiculeSheet } from "./actor/vehicule-sheet.js"
import { RdDItem } from "./item.js"; import { RdDItem } from "./item.js"
import { RdDItemBlessure } from "./item/blessure.js"; import { RdDItemBlessure } from "./item/blessure.js"
import { RdDItemService } from "./item/service.js"; import { RdDItemService } from "./item/service.js"
import { RdDItemMaladie } from "./item/maladie.js"; import { RdDItemMaladie } from "./item/maladie.js"
import { RdDItemPoison } from "./item/poison.js"; import { RdDItemPoison } from "./item/poison.js"
import { RdDItemSigneDraconique } from "./item/signedraconique.js"; import { RdDItemSigneDraconique } from "./item/signedraconique.js"
import { RdDItemQueue } from "./item/queue.js"; import { RdDItemQueue } from "./item/queue.js"
import { RdDItemOmbre } from "./item/ombre.js"; import { RdDItemOmbre } from "./item/ombre.js"
import { RdDItemSouffle } from "./item/souffle.js"; import { RdDItemSouffle } from "./item/souffle.js"
import { RdDRencontre } from "./item/rencontre.js"; import { RdDRencontre } from "./item/rencontre.js"
import { RdDItemSheet } from "./item-sheet.js"; import { RdDItemSheet } from "./item-sheet.js"
import { RdDBlessureItemSheet } from "./item/sheet-blessure.js"; import { RdDBlessureItemSheet } from "./item/sheet-blessure.js"
import { RdDServiceItemSheet } from "./item/sheet-service.js"; import { RdDServiceItemSheet } from "./item/sheet-service.js"
import { RdDRencontreItemSheet } from "./item/sheet-rencontre.js"; import { RdDRencontreItemSheet } from "./item/sheet-rencontre.js"
import { RdDHerbeItemSheet } from "./item/sheet-herbe.js"; import { RdDHerbeItemSheet } from "./item/sheet-herbe.js"
import { RdDPlanteItemSheet } from "./item/sheet-plante.js"; import { RdDPlanteItemSheet } from "./item/sheet-plante.js"
import { RdDIngredientItemSheet } from "./item/sheet-ingredient.js"; import { RdDIngredientItemSheet } from "./item/sheet-ingredient.js"
import { RdDFauneItemSheet } from "./item/sheet-faune.js"; import { RdDFauneItemSheet } from "./item/sheet-faune.js"
import { RdDConteneurItemSheet } from "./item/sheet-conteneur.js"; import { RdDConteneurItemSheet } from "./item/sheet-conteneur.js"
import { RdDSigneDraconiqueItemSheet } from "./item/sheet-signedraconique.js"; import { RdDSigneDraconiqueItemSheet } from "./item/sheet-signedraconique.js"
import { RdDItemInventaireSheet } from "./item/sheet-base-inventaire.js"; import { RdDItemInventaireSheet } from "./item/sheet-base-inventaire.js"
import { AppAstrologie } from "./sommeil/app-astrologie.js"; import { AppAstrologie } from "./sommeil/app-astrologie.js"
import { RdDItemArmure } from "./item/armure.js"; import { RdDItemArmure } from "./item/armure.js"
import { AutoAdjustDarkness as AutoAdjustDarkness } from "./time/auto-adjust-darkness.js"; import { AutoAdjustDarkness as AutoAdjustDarkness } from "./time/auto-adjust-darkness.js"
import { RdDCreature } from "./actor/creature.js"; import { RdDCreature } from "./actor/creature.js"
import { RdDTMRDialog } from "./rdd-tmr-dialog.js"; import { RdDTMRDialog } from "./rdd-tmr-dialog.js"
import { OptionsAvancees } from "./settings/options-avancees.js"
import { ExportScriptarium } from "./actor/export-scriptarium/export-scriptarium.js"
import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js"
import { RdDActorExportSheet } from "./actor/export-scriptarium/actor-encart-sheet.js"
/** /**
* RdD system * RdD system
@@ -80,8 +84,9 @@ export class SystemReveDeDragon {
} }
constructor() { constructor() {
this.RdDUtility = RdDUtility; this.config = RDD_CONFIG
this.RdDHotbar = RdDHotbar; this.RdDUtility = RdDUtility
this.RdDHotbar = RdDHotbar
this.itemClasses = { this.itemClasses = {
armure: RdDItemArmure, armure: RdDItemArmure,
blessure: RdDItemBlessure, blessure: RdDItemBlessure,
@@ -107,43 +112,43 @@ export class SystemReveDeDragon {
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
/* -------------------------------------------- */ /* -------------------------------------------- */
async onInit() { async onInit() {
game.system.rdd = this; game.system.rdd = this
game.system.rdd.config = RDD_CONFIG; this.AppAstrologie = AppAstrologie
this.AppAstrologie = AppAstrologie;
console.log(`Initializing Reve de Dragon System`); console.log(`Initializing Reve de Dragon System`)
// preload handlebars templates // preload handlebars templates
RdDUtility.preloadHandlebarsTemplates(); RdDUtility.preloadHandlebarsTemplates()
AppPersonnageAleatoire.preloadHandlebars()
/* -------------------------------------------- */ /* -------------------------------------------- */
this.initSystemSettings(); this.initSystemSettings()
/* -------------------------------------------- */ /* -------------------------------------------- */
// Set an initiative formula for the system // Set an initiative formula for the system
CONFIG.Combat.initiative = { CONFIG.Combat.initiative = {
formula: "1+(1d6/10)", formula: "1+(1d6/10)",
decimals: 2 decimals: 2
}; }
/* -------------------------------------------- */ /* -------------------------------------------- */
game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => { game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => {
console.log(">>>>> MSG RECV", sockmsg); console.log(">>>>> MSG RECV", sockmsg)
try { try {
RdDUtility.onSocketMessage(sockmsg); RdDUtility.onSocketMessage(sockmsg)
RdDCombat.onSocketMessage(sockmsg); RdDCombat.onSocketMessage(sockmsg)
ChatUtility.onSocketMessage(sockmsg); ChatUtility.onSocketMessage(sockmsg)
RdDBaseActor.onSocketMessage(sockmsg); RdDBaseActor.onSocketMessage(sockmsg)
} catch (e) { } catch (e) {
console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg, ' => ', e) console.error('game.socket.on(SYSTEM_SOCKET_ID) Exception: ', sockmsg, ' => ', e)
} }
}); })
/* -------------------------------------------- */ /* -------------------------------------------- */
// Define custom Entity classes // Define custom Entity classes
CONFIG.Actor.documentClass = RdDBaseActor; CONFIG.Actor.documentClass = RdDBaseActor
CONFIG.Item.documentClass = RdDItem; CONFIG.Item.documentClass = RdDItem
CONFIG.RDD = { CONFIG.RDD = {
resolutionTable: RdDResolutionTable.resolutionTable, resolutionTable: RdDResolutionTable.resolutionTable,
carac_array: RdDUtility.getCaracArray(), carac_array: RdDUtility.getCaracArray(),
@@ -153,30 +158,31 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */ /* -------------------------------------------- */
// Register sheet application classes // Register sheet application classes
Actors.unregisterSheet("core", ActorSheet); Actors.unregisterSheet("core", ActorSheet)
Actors.registerSheet(SYSTEM_RDD, RdDCommerceSheet, { types: ["commerce"], makeDefault: true }); Actors.registerSheet(SYSTEM_RDD, RdDCommerceSheet, { types: ["commerce"], makeDefault: true })
Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true }); Actors.registerSheet(SYSTEM_RDD, RdDActorSheet, { types: ["personnage"], makeDefault: true })
Actors.registerSheet(SYSTEM_RDD, RdDCreatureSheet, { types: ["creature"], makeDefault: true }); Actors.registerSheet(SYSTEM_RDD, RdDCreatureSheet, { types: ["creature"], makeDefault: true })
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()
RdDItemSheet.register(RdDSigneDraconiqueItemSheet); RdDItemSheet.register(RdDSigneDraconiqueItemSheet)
RdDItemSheet.register(RdDRencontreItemSheet); RdDItemSheet.register(RdDRencontreItemSheet)
RdDItemSheet.register(RdDConteneurItemSheet); RdDItemSheet.register(RdDConteneurItemSheet)
RdDItemSheet.register(RdDHerbeItemSheet); RdDItemSheet.register(RdDHerbeItemSheet)
RdDItemSheet.register(RdDFauneItemSheet); RdDItemSheet.register(RdDFauneItemSheet)
RdDItemSheet.register(RdDPlanteItemSheet); RdDItemSheet.register(RdDPlanteItemSheet)
RdDItemSheet.register(RdDIngredientItemSheet); RdDItemSheet.register(RdDIngredientItemSheet)
RdDItemSheet.register(RdDServiceItemSheet); RdDItemSheet.register(RdDServiceItemSheet)
RdDItemSheet.register(RdDBlessureItemSheet); RdDItemSheet.register(RdDBlessureItemSheet)
Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, { Items.registerSheet(SYSTEM_RDD, RdDItemInventaireSheet, {
types: [ types: [
"objet", "arme", "armure", "livre", "potion", "munition", "objet", "arme", "armure", "livre", "potion", "munition",
"monnaie", "nourritureboisson", "gemme", "monnaie", "nourritureboisson", "gemme",
], makeDefault: true ], makeDefault: true
}); })
Items.registerSheet(SYSTEM_RDD, RdDItemSheet, { Items.registerSheet(SYSTEM_RDD, RdDItemSheet, {
types: [ types: [
"competence", "competencecreature", "competence", "competencecreature",
@@ -185,31 +191,32 @@ export class SystemReveDeDragon {
"nombreastral", "tache", "maladie", "poison", "possession", "nombreastral", "tache", "maladie", "poison", "possession",
"tarot", "extraitpoetique", "empoignade" "tarot", "extraitpoetique", "empoignade"
], makeDefault: true ], makeDefault: true
}); })
CONFIG.Combat.documentClass = RdDCombatManager; CONFIG.Combat.documentClass = RdDCombatManager
// préparation des différents modules // préparation des différents modules
AutoAdjustDarkness.init(); AutoAdjustDarkness.init()
RdDTimestamp.init(); RdDTimestamp.init()
RdDCalendrier.init(); RdDCalendrier.init()
SystemCompendiums.init(); SystemCompendiums.init()
DialogChronologie.init(); DialogChronologie.init()
ReglesOptionnelles.init(); ReglesOptionnelles.init()
RdDUtility.init(); OptionsAvancees.init()
RdDDice.init(); RdDUtility.init()
RdDCommands.init(); RdDDice.init()
RdDCombatManager.init(); RdDCommands.init()
RdDTokenHud.init(); RdDCombatManager.init()
RdDBaseActor.init(); RdDTokenHud.init()
RdDCompendiumOrganiser.init(); RdDBaseActor.init()
RdDCompendiumOrganiser.init()
EffetsDraconiques.init() EffetsDraconiques.init()
TMRUtility.init(); TMRUtility.init()
await RdDTMRDialog.init() await RdDTMRDialog.init()
RdDHotbar.initDropbar(); RdDHotbar.init()
RdDPossession.init(); RdDPossession.init()
TMRRencontres.init(); TMRRencontres.init()
Environnement.init(); Environnement.init()
ExportScriptarium.init()
} }
initSystemSettings() { initSystemSettings() {
@@ -225,7 +232,7 @@ export class SystemReveDeDragon {
"avant-encaissement": "Avant l'encaissement", "avant-encaissement": "Avant l'encaissement",
}, },
default: "avant-encaissement" default: "avant-encaissement"
}); })
/* -------------------------------------------- */ /* -------------------------------------------- */
game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", { game.settings.register(SYSTEM_RDD, "supprimer-dialogues-combat-chat", {
@@ -235,7 +242,7 @@ export class SystemReveDeDragon {
config: true, config: true,
default: true, default: true,
type: Boolean type: Boolean
}); })
/* -------------------------------------------- */ /* -------------------------------------------- */
game.settings.register(SYSTEM_RDD, "activer-sons-audio", { game.settings.register(SYSTEM_RDD, "activer-sons-audio", {
@@ -245,7 +252,8 @@ export class SystemReveDeDragon {
config: true, config: true,
default: true, default: true,
type: Boolean type: Boolean
}); })
/* -------------------------------------------- */ /* -------------------------------------------- */
game.settings.register(SYSTEM_RDD, "appliquer-famine-soif", { game.settings.register(SYSTEM_RDD, "appliquer-famine-soif", {
name: "Notifier de la famine et la soif pour", name: "Notifier de la famine et la soif pour",
@@ -259,7 +267,7 @@ export class SystemReveDeDragon {
"famine-soif": "la famine et la soif", "famine-soif": "la famine et la soif",
}, },
default: "aucun" default: "aucun"
}); })
} }
async onReady() { async onReady() {
@@ -267,47 +275,47 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
/* -------------------------------------------- */ /* -------------------------------------------- */
game.system.rdd.calendrier = new RdDCalendrier(); game.system.rdd.calendrier = new RdDCalendrier()
if (Misc.isUniqueConnectedGM()) { if (Misc.isUniqueConnectedGM()) {
new Migrations().migrate(); new Migrations().migrate()
this.messageDeBienvenue(); this.messageDeBienvenue()
import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter=>{ import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => {
console.log("ClassCounter loaded", moduleCounter) console.log("ClassCounter loaded", moduleCounter)
moduleCounter.ClassCounter.registerUsageCount() moduleCounter.ClassCounter.registerUsageCount()
}).catch(err=> }).catch(err =>
console.log("No stats available, giving up.") console.log("No stats available, giving up.")
) )
} }
StatusEffects.onReady(); StatusEffects.onReady()
RdDHerbes.initializeHerbes(); RdDHerbes.onReady()
RdDDice.onReady(); RdDDice.onReady()
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Affiche/Init le calendrier */ /* Affiche/Init le calendrier */
game.system.rdd.calendrier.display(); game.system.rdd.calendrier.display()
// Avertissement si joueur sans personnage // Avertissement si joueur sans personnage
if (!game.user.isGM && game.user.character == undefined) { if (!game.user.isGM && game.user.character == undefined) {
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !"); ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !")
ChatMessage.create({ ChatMessage.create({
content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !", content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !",
user: game.user.id user: game.user.id
}); })
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
messageDeBienvenue() { messageDeBienvenue() {
if (game.user.isGM) { if (game.user.isGM) {
ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">'); ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">')
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user.id,
content: `<div id="message-bienvenue-rdd"><span class="rdd-roll-part">Bienvenue dans le Rêve des Dragons !</span> content: `<div id="message-bienvenue-rdd"><span class="rdd-roll-part">Bienvenue dans le Rêve des Dragons !</span>
<br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs} <br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs}
<br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div> <br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div>
` }); ` })
} }
} }
} }
SystemReveDeDragon.start(); SystemReveDeDragon.start()

View File

@@ -11,13 +11,17 @@ const words = ['pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i',
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDNameGen { export class RdDNameGen {
static async getName(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.html`, {
nom: Misc.upperFirst(await RdDDice.rollOneOf(words) + await RdDDice.rollOneOf(words)) nom: await RdDNameGen.generate()
}); });
ChatMessage.create({ content: html, whisper: ChatMessage.getWhisperRecipients("GM") }); ChatMessage.create({ content: html, whisper: ChatMessage.getWhisperRecipients("GM") });
} }
static async generate() {
return Misc.upperFirst(await RdDDice.rollOneOf(words) + await RdDDice.rollOneOf(words));
}
static async onCreerActeur(event) { static async onCreerActeur(event) {
const button = event.currentTarget; const button = event.currentTarget;
await RdDBaseActor.create({ await RdDBaseActor.create({

View File

@@ -3,7 +3,7 @@ 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 { TYPES } from "./item.js"; import { ITEM_TYPES } from "./item.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
/* On part du principe qu'une entité démarre tjs /* On part du principe qu'une entité démarre tjs
@@ -20,9 +20,9 @@ export class RdDPossession {
/* -------------------------------------------- */ /* -------------------------------------------- */
static searchPossessionFromEntite(attacker, defender) { static searchPossessionFromEntite(attacker, defender) {
let poss = attacker.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id); let poss = attacker.items.find(poss => poss.type == ITEM_TYPES.possession && poss.system.victime.actorid == defender.id);
if (!poss) { if (!poss) {
poss = defender.items.find(poss => poss.type == TYPES.possession && poss.system.victime.actorid == defender.id); poss = defender.items.find(poss => poss.type == ITEM_TYPES.possession && poss.system.victime.actorid == defender.id);
} }
return poss && foundry.utils.duplicate(poss) || undefined; return poss && foundry.utils.duplicate(poss) || undefined;
} }
@@ -131,7 +131,7 @@ 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.attacker, 'chat-resultat-possession.html'); await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html');
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -171,7 +171,7 @@ export class RdDPossession {
rollData.possession = possession rollData.possession = possession
RdDPossession.$updateEtatPossession(rollData.possession) RdDPossession.$updateEtatPossession(rollData.possession)
await RdDResolutionTable.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.html') await RdDResolutionTable.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.html')
if (rollData.possession.isPosseder || rollData.possession.isConjurer) { if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
// conjuration // conjuration
victime.deleteEmbeddedDocuments("Item", [rollData.possession._id]) victime.deleteEmbeddedDocuments("Item", [rollData.possession._id])
@@ -230,7 +230,7 @@ export class RdDPossession {
system: { system: {
description: "", typepossession: attacker.name, description: "", typepossession: attacker.name,
possede: false, possede: false,
possessionid: randomID(16), possessionid: foundry.utils.randomID(16),
entite: { actorid: attacker.id }, entite: { actorid: attacker.id },
victime: { actorid: defender.id }, victime: { actorid: defender.id },
compteur: 0 compteur: 0

View File

@@ -97,7 +97,7 @@ export class RdDResolutionTable {
} }
static actorChatName(actor) { static actorChatName(actor) {
return actor?.userName ?? game.user.name; return actor?.name ?? game.user.name;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@@ -307,7 +307,7 @@ export class RdDRoll extends Dialog {
async updateRollResult(html) { async updateRollResult(html) {
const rollData = this.rollData; const rollData = this.rollData;
rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor.getBonusDegat()) rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor)
rollData.caracValue = parseInt(rollData.selectedCarac.value) rollData.caracValue = parseInt(rollData.selectedCarac.value)
rollData.dmg.mortalite = rollData.dmg.mortalite ?? 'mortel'; rollData.dmg.mortalite = rollData.dmg.mortalite ?? 'mortel';
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac); rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);

View File

@@ -16,7 +16,7 @@ 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 { RdDTimestamp } from "./time/rdd-timestamp.js";
import { TYPES } from "./item.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 = {
@@ -129,7 +129,7 @@ export class RdDTMRDialog extends Dialog {
this.html.find('form.tmr-dialog *').click(event => this.subdialog?.bringToTop()); this.html.find('form.tmr-dialog *').click(event => this.subdialog?.bringToTop());
// Roll Sort // Roll Sort
this.html.find('.lancer-sort').click(event => this.actor.rollUnSort(this._getCoordActor())); this.html.find('.lancer-sort').click(event => this.lancerUnSort());
this.html.find('.lire-signe-draconique').click(event => this.actor.rollLireSigneDraconique(this._getCoordActor())); this.html.find('.lire-signe-draconique').click(event => this.actor.rollLireSigneDraconique(this._getCoordActor()));
this.html.find('img.tmr-move').click(event => this.deplacementTMR(this.html.find(event.currentTarget)?.data('move'))); this.html.find('img.tmr-move').click(event => this.deplacementTMR(this.html.find(event.currentTarget)?.data('move')));
@@ -142,6 +142,13 @@ export class RdDTMRDialog extends Dialog {
this.updateValuesDisplay(); this.updateValuesDisplay();
} }
lancerUnSort() {
if (this.subdialog) {
return this.forceTMRContinueAction();
}
return this.actor.rollUnSort(this._getCoordActor());
}
async onDeplacement() { async onDeplacement() {
await this.manageRencontre(TMRUtility.getTMR(this._getCoordActor())); await this.manageRencontre(TMRUtility.getTMR(this._getCoordActor()));
} }
@@ -164,23 +171,25 @@ export class RdDTMRDialog extends Dialog {
async forceTMRDisplay() { async forceTMRDisplay() {
if (this.rendered) { if (this.rendered) {
this.bringToTop() this.bringToTop()
if (this.subdialog?.bringToTop) { this.bringSubDialogToTop();
this.subdialog.bringToTop(); }
} }
bringSubDialogToTop() {
if (this.subdialog?.bringToTop && this.subdialog?.element[0]) {
this.subdialog.bringToTop();
} }
} }
async restoreTMRAfterAction() { async restoreTMRAfterAction() {
this.subdialog = undefined this.subdialog = undefined
await this.maximize(); await this.maximize()
this.bringToTop(); this.bringToTop()
} }
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');
if (this.subdialog?.bringToTop) { this.bringSubDialogToTop();
this.subdialog.bringToTop();
}
return; return;
} }
@@ -199,11 +208,11 @@ export class RdDTMRDialog extends Dialog {
} }
get sortsReserve() { get sortsReserve() {
return this.actor.itemTypes[TYPES.sortreserve]; return this.actor.itemTypes[ITEM_TYPES.sortreserve];
} }
getSortsReserve(coord) { getSortsReserve(coord) {
return this.actor.itemTypes[TYPES.sortreserve].filter(// Reserve sur une case fleuve ou normale return this.actor.itemTypes[ITEM_TYPES.sortreserve].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
@@ -261,7 +270,7 @@ export class RdDTMRDialog extends Dialog {
} }
_getTokensSortsReserve() { _getTokensSortsReserve() {
const sortsReserve = this.actor.itemTypes[TYPES.sortreserve]; const sortsReserve = this.actor.itemTypes[ITEM_TYPES.sortreserve];
return Misc.concat(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)))
} }

View File

@@ -19,6 +19,7 @@ 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";
/* -------------------------------------------- */ /* -------------------------------------------- */
// This table starts at 0 -> niveau -10 // This table starts at 0 -> niveau -10
@@ -262,8 +263,6 @@ export class RdDUtility {
]; ];
Handlebars.registerHelper('either', (a, b) => a ?? b); Handlebars.registerHelper('either', (a, b) => a ?? b);
Handlebars.registerHelper('computeResolutionScore', (row, col) => RdDResolutionTable.computePercentage(row, col));
Handlebars.registerHelper('computeResolutionChances', (row, col) => RdDResolutionTable.computeChances(row, col));
Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null')); Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null'));
Handlebars.registerHelper('lowerFirst', str => Misc.lowerFirst(str ?? 'Null')); Handlebars.registerHelper('lowerFirst', str => Misc.lowerFirst(str ?? 'Null'));
Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? ''); Handlebars.registerHelper('upper', str => str?.toUpperCase() ?? '');
@@ -272,6 +271,10 @@ export class RdDUtility {
Handlebars.registerHelper('apostrophe', (article, str) => Grammar.apostrophe(article, str)); Handlebars.registerHelper('apostrophe', (article, str) => Grammar.apostrophe(article, str));
Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str)); Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str));
Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args)); Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args));
Handlebars.registerHelper('RDD_CONFIG', path => RDD_CONFIG[path])
Handlebars.registerHelper('computeResolutionScore', (row, col) => RdDResolutionTable.computePercentage(row, col));
Handlebars.registerHelper('computeResolutionChances', (row, col) => RdDResolutionTable.computeChances(row, col));
Handlebars.registerHelper('buildLigneInventaire', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildLigneInventaire(item, options)); }); Handlebars.registerHelper('buildLigneInventaire', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildLigneInventaire(item, options)); });
Handlebars.registerHelper('buildInventaireConteneur', (actorId, itemId, options) => { return new Handlebars.SafeString(RdDUtility.buildInventaireConteneur(actorId, itemId, options)); }); Handlebars.registerHelper('buildInventaireConteneur', (actorId, itemId, options) => { return new Handlebars.SafeString(RdDUtility.buildInventaireConteneur(actorId, itemId, options)); });
Handlebars.registerHelper('buildContenuConteneur', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildContenuConteneur(item, options)); }); Handlebars.registerHelper('buildContenuConteneur', (item, options) => { return new Handlebars.SafeString(RdDUtility.buildContenuConteneur(item, options)); });
@@ -289,6 +292,7 @@ export class RdDUtility {
Handlebars.registerHelper('array-includes', (array, value) => array.includes(value)); Handlebars.registerHelper('array-includes', (array, value) => array.includes(value));
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1))); Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
Handlebars.registerHelper('isLastIndex', (index, list) => index+1 >= list.length);
Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionnelles.isUsing(option)); Handlebars.registerHelper('regle-optionnelle', (option) => ReglesOptionnelles.isUsing(option));
Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name))); Handlebars.registerHelper('trier', list => list.sort((a, b) => a.name.localeCompare(b.name)));
Handlebars.registerHelper('filtreTriCompetences', competences => RdDItemCompetence.triVisible(competences)); Handlebars.registerHelper('filtreTriCompetences', competences => RdDItemCompetence.triVisible(competences));
@@ -355,13 +359,15 @@ export class RdDUtility {
let objetVersConteneur = {}; let objetVersConteneur = {};
// Attribution des objets aux conteneurs // Attribution des objets aux conteneurs
for (let conteneur of conteneurs) { for (let conteneur of conteneurs) {
conteneur.subItems = []; if (conteneur.isConteneur()) {
for (let id of conteneur.system.contenu ?? []) { conteneur.subItems = [];
let objet = inventaires.find(objet => (id == objet._id)); for (let id of conteneur.system.contenu ?? []) {
if (objet) { let objet = inventaires.find(objet => (id == objet._id));
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template if (objet) {
objetVersConteneur[id] = conteneur._id; objet.estContenu = true;
conteneur.subItems.push(objet); objetVersConteneur[id] = conteneur._id;
conteneur.subItems.push(objet);
}
} }
} }
} }
@@ -764,7 +770,7 @@ export class RdDUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static createMonnaie(name, cout, img = "", enc = 0.01) { static createMonnaie(name, cout, img = "", enc = 0.01) {
let piece = { let piece = {
name: name, type: 'monnaie', img: img, _id: randomID(16), name: name, type: 'monnaie', img: img, _id: foundry.utils.randomID(16),
dasystemta: { dasystemta: {
quantite: 0, quantite: 0,
cout: cout, cout: cout,

View File

@@ -111,7 +111,7 @@ export const referenceAjustements = {
isVisible: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0, isVisible: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
isUsed: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0, isUsed: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
getLabel: (rollData, actor) => "Ecaille d'Efficacité: ", getLabel: (rollData, actor) => "Ecaille d'Efficacité: ",
getValue: (rollData, actor) => Math.max(Number(rollData.arme?.system.ecaille_efficacite), 0), getValue: (rollData, actor) => rollData.arme?.system.magique ? Math.max(Number(rollData.arme?.system.ecaille_efficacite), 0) : 0,
}, },
finesse: { finesse: {
isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData), isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData),

View File

@@ -0,0 +1,91 @@
import { SYSTEM_RDD } from "../constants.js"
import { Misc } from "../misc.js"
export const EXPORT_CSV_SCRIPTARIUM = 'export-csv-scriptarium'
const OPTIONS_AVANCEES = [
{ group: 'Menus', name: EXPORT_CSV_SCRIPTARIUM, descr: "Proposer le menu d'export csv Scriptarium" },
]
export class OptionsAvancees extends FormApplication {
static init() {
for (const regle of OPTIONS_AVANCEES) {
const name = regle.name
const id = OptionsAvancees._getId(name)
game.settings.register(SYSTEM_RDD, id, { name: id, scope: regle.scope ?? "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean })
}
game.settings.registerMenu(SYSTEM_RDD, "rdd-options-avancees", {
name: "Configurer les options avancées",
label: "Options avancées",
hint: "Ouvre la fenêtre de configuration des options avancées",
icon: "fas fa-bars",
type: OptionsAvancees
})
}
constructor(...args) {
super(...args)
}
static _getId(name) {
return `rdd-advanced-${name}`
}
static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, {
id: "options-avancees",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/options-avancees.hbs",
height: 650,
width: 550,
minimizable: false,
closeOnSubmit: true,
title: "Options avancées"
}, { inplace: false })
}
getData() {
let formData = super.getData()
const regles = OPTIONS_AVANCEES.filter(it => game.user.isGM || it.scope == "client")
.map(it => {
it = foundry.utils.duplicate(it)
it.id = OptionsAvancees._getId(it.name)
it.active = OptionsAvancees.isSet(it.name)
return it
})
formData.regles = regles
formData.groups = Misc.classify(regles, it => it.group)
return formData
}
static getSettingKey(name){
return `${SYSTEM_RDD}.${this._getId(name)}`
}
static isUsing(name) {
return OptionsAvancees.isSet(name)
}
static isSet(name) {
return game.settings.get(SYSTEM_RDD, OptionsAvancees._getId(name))
}
static set(name, value) {
return game.settings.set(SYSTEM_RDD, OptionsAvancees._getId(name), value ? true : false)
}
activateListeners(html) {
html.find(".select-option").click((event) => {
if (event.currentTarget.attributes.name) {
let id = event.currentTarget.attributes.name.value
let isChecked = event.currentTarget.checked
game.settings.set(SYSTEM_RDD, id, isChecked)
}
})
}
async _updateObject(event, formData) {
this.close()
}
}

View File

@@ -73,7 +73,7 @@ export class ReglesOptionnelles extends FormApplication {
static get defaultOptions() { static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
id: "regles-optionnelles", id: "regles-optionnelles",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.html", template: "systems/foundryvtt-reve-de-dragon/templates/settings/regles-optionnelles.hbs",
height: 650, height: 650,
width: 550, width: 550,
minimizable: false, minimizable: false,

View File

@@ -1,3 +1,4 @@
import { ChatUtility } from "../chat-utility.js";
import { HIDE_DICE, SYSTEM_RDD } from "../constants.js"; import { HIDE_DICE, SYSTEM_RDD } from "../constants.js";
import { RdDItem } from "../item.js"; import { RdDItem } from "../item.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
@@ -290,7 +291,7 @@ export class CompendiumTableHelpers {
sound: CONFIG.sounds.dice, sound: CONFIG.sounds.dice,
content: flavorContent content: flavorContent
}; };
ChatMessage.create(messageData, { rollMode: "gmroll" }); await ChatUtility.createChatWithRollMode(game.user.id, messageData)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -306,7 +307,7 @@ export class CompendiumTableHelpers {
whisper: game.user.id, whisper: game.user.id,
content: flavorContent content: flavorContent
}; };
ChatMessage.create(messageData, { rollMode: "gmroll" }); await ChatUtility.createChatWithRollMode(game.user.id, messageData)
} }
} }

View File

@@ -1,7 +1,6 @@
import { MAX_NOMBRE_ASTRAL, RdDTimestamp, WORLD_TIMESTAMP_SETTING } from "./rdd-timestamp.js"; import { MAX_NOMBRE_ASTRAL, RdDTimestamp, WORLD_TIMESTAMP_SETTING } from "./rdd-timestamp.js";
import { RdDCalendrierEditor } from "./rdd-calendrier-editor.js"; import { RdDCalendrierEditor } from "./rdd-calendrier-editor.js";
import { RdDResolutionTable } from "../rdd-resolution-table.js"; import { RdDResolutionTable } from "../rdd-resolution-table.js";
import { RdDUtility } from "../rdd-utility.js";
import { RdDDice } from "../rdd-dice.js"; import { RdDDice } from "../rdd-dice.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { DialogChronologie } from "../dialog-chronologie.js"; import { DialogChronologie } from "../dialog-chronologie.js";
@@ -123,9 +122,9 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
fillCalendrierData(formData = {}) { fillCalendrierData(formData = {}) {
foundry.utils.mergeObject(formData, this.timestamp.toCalendrier()); foundry.utils.mergeObject(formData, this.timestamp.toCalendrier());
formData.isGM = game.user.isGM; formData.isGM = game.user.isGM
formData.heures = RdDTimestamp.definitions() formData.heures = RdDTimestamp.definitions()
formData.horlogeAnalogique = this.horlogeAnalogique; formData.horlogeAnalogique = this.horlogeAnalogique
formData.autoDarkness = AutoAdjustDarkness.isAuto() formData.autoDarkness = AutoAdjustDarkness.isAuto()
return formData; return formData;
} }
@@ -228,7 +227,7 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
async ajouterNombreAstral(indexDate) { async ajouterNombreAstral(indexDate) {
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: HIDE_DICE, rollMode: "selfroll" }); const nombreAstral = await RdDDice.rollHeure( { showDice: HIDE_DICE, rollMode: "selfroll" });
return { return {
nombreAstral: nombreAstral, nombreAstral: nombreAstral,
lectures: [], lectures: [],

View File

@@ -15,18 +15,18 @@ export const RDD_MINUTES_PAR_JOUR = 1440; //RDD_HEURES_PAR_JOUR * RDD_MINUTES_PA
const ROUNDS_PAR_MINUTE = 10; const ROUNDS_PAR_MINUTE = 10;
const DEFINITION_HEURES = [ const DEFINITION_HEURES = [
{ key: "vaisseau", label: "Vaisseau", lettreFont: 'v', saison: "Printemps", darkness: 0.9 }, { key: "vaisseau", article: "du ", label: "Vaisseau", lettreFont: 'v', saison: "Printemps", darkness: 0.9 },
{ key: "sirene", label: "Sirène", lettreFont: 'i', saison: "Printemps", darkness: 0.1 }, { key: "sirene", article: "de la ", label: "Sirène", lettreFont: 'i', saison: "Printemps", darkness: 0.1 },
{ key: "faucon", label: "Faucon", lettreFont: 'f', saison: "Printemps", darkness: 0 }, { key: "faucon", article: "du ", label: "Faucon", lettreFont: 'f', saison: "Printemps", darkness: 0 },
{ key: "couronne", label: "Couronne", lettreFont: '', saison: "Eté", darkness: 0 }, { key: "couronne", article: "de la ", label: "Couronne", lettreFont: '', saison: "Eté", darkness: 0 },
{ key: "dragon", label: "Dragon", lettreFont: 'd', saison: "Eté", darkness: 0 }, { key: "dragon", article: "du ", label: "Dragon", lettreFont: 'd', saison: "Eté", darkness: 0 },
{ key: "epees", label: "Epées", lettreFont: 'e', saison: "Eté", darkness: 0 }, { key: "epees", article: "des ", label: "Epées", lettreFont: 'e', saison: "Eté", darkness: 0 },
{ key: "lyre", label: "Lyre", lettreFont: 'l', saison: "Automne", darkness: 0.1 }, { key: "lyre", article: "de la ", label: "Lyre", lettreFont: 'l', saison: "Automne", darkness: 0.1 },
{ key: "serpent", label: "Serpent", lettreFont: 's', saison: "Automne", darkness: 0.9 }, { key: "serpent", article: "du ", label: "Serpent", lettreFont: 's', saison: "Automne", darkness: 0.9 },
{ key: "poissonacrobate", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne", darkness: 1 }, { key: "poissonacrobate", article: "du ", label: "Poisson Acrobate", lettreFont: 'p', saison: "Automne", darkness: 1 },
{ key: "araignee", label: "Araignée", lettreFont: 'a', saison: "Hiver", darkness: 1 }, { key: "araignee", article: "de l'", label: "Araignée", lettreFont: 'a', saison: "Hiver", darkness: 1 },
{ key: "roseau", label: "Roseau", lettreFont: 'r', saison: "Hiver", darkness: 1 }, { key: "roseau", article: "du ", label: "Roseau", lettreFont: 'r', saison: "Hiver", darkness: 1 },
{ key: "chateaudormant", label: "Château Dormant", lettreFont: 'c', saison: "Hiver", darkness: 1 }, { key: "chateaudormant", article: "du ", label: "Château Dormant", lettreFont: 'c', saison: "Hiver", darkness: 1 },
] ]
const FORMULES_DUREE = [ const FORMULES_DUREE = [
@@ -64,6 +64,7 @@ export class RdDTimestamp {
DEFINITION_HEURES[i].hh = RdDTimestamp.hh(i); DEFINITION_HEURES[i].hh = RdDTimestamp.hh(i);
DEFINITION_HEURES[i].icon = RdDTimestamp.iconeHeure(i); DEFINITION_HEURES[i].icon = RdDTimestamp.iconeHeure(i);
DEFINITION_HEURES[i].webp = DEFINITION_HEURES[i].icon.replace(".svg", ".webp"); DEFINITION_HEURES[i].webp = DEFINITION_HEURES[i].icon.replace(".svg", ".webp");
DEFINITION_HEURES[i].avecArticle = DEFINITION_HEURES[i].article + DEFINITION_HEURES[i].label
} }
} }
@@ -241,7 +242,7 @@ export class RdDTimestamp {
get darkness() { get darkness() {
const darknessDebut = 100 * RdDTimestamp.definition(this.heure).darkness const darknessDebut = 100 * RdDTimestamp.definition(this.heure).darkness
const darknessFin = 100 * RdDTimestamp.definition(this.heure + 1).darkness const darknessFin = 100 * RdDTimestamp.definition(this.heure + 1).darkness
const darknessMinute = Math.round((darknessFin - darknessDebut) * this.minute / RDD_MINUTES_PAR_HEURES); const darknessMinute = Math.round((darknessFin - darknessDebut) * this.minute / RDD_MINUTES_PAR_HEURES);
return (darknessDebut + darknessMinute) / 100 return (darknessDebut + darknessMinute) / 100
} }

View File

@@ -1,4 +1,4 @@
import { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.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";
@@ -12,10 +12,10 @@ export class Draconique {
static init() { static init() {
} }
static isCaseTMR(item) { return item.type == TYPES.casetmr; } static isCaseTMR(item) { return item.type == ITEM_TYPES.casetmr; }
static isQueueDragon(item) { return item.isQueueDragon(); } static isQueueDragon(item) { return item.isQueueDragon(); }
static isSouffleDragon(item) { return item.type == TYPES.souffle; } static isSouffleDragon(item) { return item.type == ITEM_TYPES.souffle; }
static isTeteDragon(item) { return item.type == TYPES.tete; } static isTeteDragon(item) { return item.type == ITEM_TYPES.tete; }
static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); } static isQueueSouffle(item) { return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item); }
static register(draconique, code = undefined) { static register(draconique, code = undefined) {

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 { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
export class EffetsDraconiques { export class EffetsDraconiques {
static carteTmr = new CarteTmr(); static carteTmr = new CarteTmr();
@@ -122,11 +122,11 @@ export class EffetsDraconiques {
} }
static tetesDragon(actor, name) { static tetesDragon(actor, name) {
return actor.itemTypes[TYPES.tete].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name)); return actor.itemTypes[ITEM_TYPES.tete].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
} }
static soufflesDragon(actor, name) { static soufflesDragon(actor, name) {
return actor.itemTypes[TYPES.souffle].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name)); return actor.itemTypes[ITEM_TYPES.souffle].filter(it => Grammar.includesLowerCaseNoAccent(it.name, name));
} }
static queuesDragon(actor, name) { static queuesDragon(actor, name) {
@@ -134,7 +134,7 @@ export class EffetsDraconiques {
} }
static queuesSoufflesDragon(actor, name) { static queuesSoufflesDragon(actor, name) {
return actor.filterItems(it => [TYPES.queue, TYPES.ombre, TYPES.souffle].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, name)); return actor.filterItems(it => [ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle].includes(it.type) && Grammar.includesLowerCaseNoAccent(it.name, name));
} }
static countAugmentationSeuil(actor) { static countAugmentationSeuil(actor) {

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 { TYPES } from "../item.js"; import { ITEM_TYPES } from "../item.js";
import { TMRAnimations } from "./animation.js"; import { TMRAnimations } from "./animation.js";
export class UrgenceDraconique extends Draconique { export class UrgenceDraconique extends Draconique {
@@ -14,7 +14,7 @@ export class UrgenceDraconique extends Draconique {
match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); } match(item) { return Draconique.isQueueDragon(item) && Grammar.toLowerCaseNoAccent(item.name).includes('urgence draconique'); }
manualMessage() { return false } manualMessage() { return false }
async onActorCreateOwned(actor, queue) { async onActorCreateOwned(actor, queue) {
const coordSortsReserve = actor.itemTypes[TYPES.sortreserve].map(it => it.system.coord) ?? []; const coordSortsReserve = actor.itemTypes[ITEM_TYPES.sortreserve].map(it => it.system.coord) ?? [];
if (coordSortsReserve.length == 0) { if (coordSortsReserve.length == 0) {
// La queue se transforme en idée fixe // La queue se transforme en idée fixe
const ideeFixe = await RdDRollTables.getIdeeFixe(); const ideeFixe = await RdDRollTables.getIdeeFixe();

View File

@@ -1,6 +1,7 @@
import { TYPES } from "../item.js" import { ITEM_TYPES } from "../item.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"
const CODES_COMPETENCES_VOYAGE = ['Extérieur', 'Forêt', 'Montagne', 'Marais', 'Glace', 'Equitation'] const CODES_COMPETENCES_VOYAGE = ['Extérieur', 'Forêt', 'Montagne', 'Marais', 'Glace', 'Equitation']
const TABLEAU_FATIGUE_MARCHE = [ const TABLEAU_FATIGUE_MARCHE = [
@@ -36,7 +37,7 @@ export class DialogFatigueVoyage extends Dialog {
const parameters = { const parameters = {
tableauFatigueMarche: TABLEAU_FATIGUE_MARCHE, tableauFatigueMarche: TABLEAU_FATIGUE_MARCHE,
playerActors: game.actors.filter(actor => actor.isPersonnageJoueur()) playerActors: game.actors.filter(actor => actor.isPersonnageJoueur())
.map(actor => DialogFatigueVoyage.prepareActor(actor)), .map(actor => DialogFatigueVoyage.prepareActorParameters(actor)),
nombreHeures: 1, nombreHeures: 1,
} }
DialogFatigueVoyage.setModeDeplacement(parameters, undefined, undefined) DialogFatigueVoyage.setModeDeplacement(parameters, undefined, undefined)
@@ -53,21 +54,37 @@ export class DialogFatigueVoyage extends Dialog {
parameters.typeTerrain = ligneFatigueMarche parameters.typeTerrain = ligneFatigueMarche
parameters.vitesseDeplacement = rythme.vitesse parameters.vitesseDeplacement = rythme.vitesse
parameters.fatigueHoraire = rythme.fatigue parameters.fatigueHoraire = rythme.fatigue
parameters.playerActors.forEach(voyageur =>
DialogFatigueVoyage.selectSurvie(voyageur, parameters.typeTerrain.code)
)
} }
static prepareActor(actor) { static prepareActorParameters(actor) {
const competencesVoyage = {} const actorParameters = {
CODES_COMPETENCES_VOYAGE.forEach(codeSurvie => id: actor.id,
competencesVoyage[codeSurvie] = RdDItemCompetence.findCompetence(actor.itemTypes[TYPES.competence], codeSurvie, { onMessage: () => { } })
)
return {
actor: actor, actor: actor,
selected: true, selected: true,
ajustementFatigue: 0, ajustementFatigue: 0,
competencesVoyage: competencesVoyage survies: {}
} }
const competencesVoyage = {}
CODES_COMPETENCES_VOYAGE.forEach(codeSurvie => {
competencesVoyage[codeSurvie] = RdDItemCompetence.findCompetence(actor.itemTypes[ITEM_TYPES.competence], codeSurvie, { onMessage: () => { } })
})
TABLEAU_FATIGUE_MARCHE.forEach(terrain => {
actorParameters.survies[terrain.code] = Misc.join(
terrain.survies.map(survie => {
const niveau = competencesVoyage[survie]?.system.niveau
return `${survie}: ${niveau}`
}),
', ')
})
return actorParameters
} }
static selectSurvie(actorParameters, code) {
actorParameters.survieCourante = actorParameters.survies[code]
}
constructor(html, parameters) { constructor(html, parameters) {
const options = { const options = {
@@ -97,6 +114,7 @@ export class DialogFatigueVoyage extends Dialog {
this.html.find('select[name="code-terrain"]').change(event => this.changeParameters()) this.html.find('select[name="code-terrain"]').change(event => this.changeParameters())
this.html.find('select[name="vitesse-deplacement"]').change(event => this.changeParameters()) this.html.find('select[name="vitesse-deplacement"]').change(event => this.changeParameters())
this.html.find('input[name="nombre-heures"]').change(event => this.changeParameters()) this.html.find('input[name="nombre-heures"]').change(event => this.changeParameters())
this.html.find('.list-item input[name="ajustement-fatigue"]').change(event => this.changeParameters())
this.html.find('button[name="appliquer-fatigue"]').click(event => this.appliquerFatigue()) this.html.find('button[name="appliquer-fatigue"]').click(event => this.appliquerFatigue())
} }
@@ -118,6 +136,10 @@ export class DialogFatigueVoyage extends Dialog {
selectVitesseDeplacement.append(await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs', rythme)) selectVitesseDeplacement.append(await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs', rythme))
}) })
selectVitesseDeplacement.val(this.parameters.vitesseDeplacement).change() selectVitesseDeplacement.val(this.parameters.vitesseDeplacement).change()
Promise.all(this.getActorRows()
.map(async row => row.find('label.voyage-liste-survies').text(this.$extractActorParameters(row).survieCourante)
))
} }
} }
@@ -132,16 +154,24 @@ export class DialogFatigueVoyage extends Dialog {
} }
async setFatigue() { async setFatigue() {
this.html.find('input[name="base-fatigue"]').val(this.parameters.nombreHeures * this.parameters.fatigueHoraire) const baseFatigue = this.parameters.nombreHeures * this.parameters.fatigueHoraire
this.html.find('input[name="base-fatigue"]').val(baseFatigue)
this.updateActorTotalFatigue(baseFatigue)
}
async updateActorTotalFatigue(baseFatigue) {
Promise.all(this.getActorRows()
.map(async row => {
const actor = this.$extractActorParameters(row)
row.find('input[name="total-fatigue"]').val(actor.ajustement + baseFatigue)
}))
} }
async appliquerFatigue() { async appliquerFatigue() {
const fatigueBase = parseInt(this.html.find('input[name="base-fatigue"]').val() ?? 0) const fatigueBase = parseInt(this.html.find('input[name="base-fatigue"]').val() ?? 0)
const actors = jQuery.map( this.getActorRows()
this.html.find('div.fatigue-actors-list li.list-item'), .map(row => this.$extractActorParameters(row))
it => this.$extractActor(this.html.find(it)) .filter(it => it.selected)
)
actors.filter(it => it.selected)
.forEach(async it => { .forEach(async it => {
const perteFatigue = fatigueBase + it.ajustement const perteFatigue = fatigueBase + it.ajustement
ChatMessage.create({ ChatMessage.create({
@@ -161,16 +191,24 @@ export class DialogFatigueVoyage extends Dialog {
}) })
} }
$extractActor(actorRow) { getActorRows() {
const actor = game.actors.get(actorRow.data('actor-id')) return jQuery.map(
this.html.find('div.fatigue-actors-list li.list-item'),
it => this.html.find(it))
}
$extractActorParameters(actorRow) {
const actorId = actorRow.data('actor-id')
const actorParameters = this.parameters.playerActors.find(it => it.id == actorId)
const actor = game.actors.get(actorId)
if (!actor) { if (!actor) {
ui.notifications.warn(`Acteur ${it.actorId} introuvable`) ui.notifications.warn(`Acteur ${it.actorId} introuvable`)
return {}
} }
return { actorParameters.ajustement = parseInt(actorRow.find('input[name="ajustement-fatigue"]').val() ?? 0)
actor: actor, actorParameters.selected = actor && actorRow.find('input[name="selectionner-acteur"]').is(':checked')
ajustement: parseInt(actorRow.find('input[name="ajustement-fatigue"]').val() ?? 0), return actorParameters
selected: actor && actorRow.find('input[name="selectionner-acteur"]').is(':checked')
}
} }
async close() { async close() {

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 56 KiB

View File

@@ -326,7 +326,7 @@ table {border: 1px solid #7a7971;}
display: grid; display: grid;
grid-column: span 2 / span 2; grid-column: span 2 / span 2;
grid-template-columns: repeat(2, minmax(0, 1fr)); grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 10px; gap: 30px;
margin: 10px 0; margin: 10px 0;
padding: 0; padding: 0;
} }
@@ -411,6 +411,11 @@ table {border: 1px solid #7a7971;}
text-align: left; text-align: left;
} }
.flex-group-top {
vertical-align: top;
align-self: start;
}
.flex-group-right { .flex-group-right {
-webkit-box-pack: end; -webkit-box-pack: end;
-ms-flex-pack: end; -ms-flex-pack: end;
@@ -572,6 +577,15 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) {
border: none; border: none;
padding: 0.1rem; padding: 0.1rem;
} }
.context-menu-img {
max-width: 2rem;
max-height: 1rem;
flex-grow: 0;
margin: 0.2rem 0.3rem 0 0;
vertical-align: middle;
border: none;
padding: 0rem;
}
.button-img { .button-img {
vertical-align: baseline; vertical-align: baseline;
@@ -666,6 +680,7 @@ input:is(.blessure-premiers_soins, .blessure-soins_complets) {
} }
.carac-label { .carac-label {
font-weight: bold;
flex-basis: 40%; flex-basis: 40%;
} }
.rdd.sheet .window-content .sheet-body .carac-list .caracteristique > .utiliser-attribut { .rdd.sheet .window-content .sheet-body .carac-list .caracteristique > .utiliser-attribut {
@@ -1174,9 +1189,6 @@ ul.chat-list li:nth-child(odd) {
padding: 0.5rem; padding: 0.5rem;
cursor: pointer; cursor: pointer;
} }
.carac-label {
font-weight: bold;
}
.list-item { .list-item {
margin: 0.1rem; margin: 0.1rem;
box-shadow: inset 0px 0px 1px #00000096; box-shadow: inset 0px 0px 1px #00000096;
@@ -1374,7 +1386,7 @@ table.table-nombres-astraux tr:hover {
flex-direction: column; flex-direction: column;
position: absolute; position: absolute;
top: 4.6rem; top: 4.6rem;
right: 3.5rem; left: -19rem;
} }
.token-hud-ext.soins { .token-hud-ext.soins {
flex-direction: column; flex-direction: column;

View File

@@ -1,8 +1,8 @@
{ {
"id": "foundryvtt-reve-de-dragon", "id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon", "title": "Rêve de Dragon",
"version": "12.0.0", "version": "12.0.12",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.0.zip", "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.12.zip",
"manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json", "manifest": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/v11/system.json",
"changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md", "changelog": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v11/changelog.md",
"compatibility": { "compatibility": {
@@ -534,6 +534,7 @@
}, },
"primaryTokenAttribute": "sante.vie", "primaryTokenAttribute": "sante.vie",
"secondaryTokenAttribute": "sante.endurance", "secondaryTokenAttribute": "sante.endurance",
"background": "systems/foundryvtt-reve-de-dragon/styles/img/reve-de-dragon-cover.webp",
"media": [ "media": [
{ {
"type": "icon", "type": "icon",

View File

@@ -15,12 +15,14 @@
} }
}, },
"background": { "background": {
"metier": "",
"biographie": "Histoire personnelle...", "biographie": "Histoire personnelle...",
"notes": "Notes", "notes": "Notes",
"notesmj": "Notes du MJ", "notesmj": "Notes du MJ",
"race": "Humain", "race": "Humain",
"yeux": "", "yeux": "",
"cheveux": "", "cheveux": "",
"taille": "",
"poids": "", "poids": "",
"heure": "", "heure": "",
"sexe": "", "sexe": "",

View File

@@ -172,6 +172,10 @@
<label for="system.poids">Poids :</label> <label for="system.poids">Poids :</label>
<input class="flex-grow" type="text" name="system.poids" value="{{system.poids}}" data-dtype="String"/> <input class="flex-grow" type="text" name="system.poids" value="{{system.poids}}" data-dtype="String"/>
</li> </li>
<li class="item flexrow list-item">
<label for="system.metier">Métier :</label>
<input class="flex-grow" type="text" name="system.metier" value="{{system.metier}}" data-dtype="String"/>
</li>
</ul> </ul>
<ul class="item-list alterne-list"> <ul class="item-list alterne-list">
<li class="item flexrow list-item"> <li class="item flexrow list-item">
@@ -201,6 +205,7 @@
<label for="system.yeux">Yeux :</label> <label for="system.yeux">Yeux :</label>
<input class="flex-grow" type="text" name="system.yeux" value="{{system.yeux}}" data-dtype="String"/> <input class="flex-grow" type="text" name="system.yeux" value="{{system.yeux}}" data-dtype="String"/>
</li> </li>
<a class="chat-card-button description-aleatoire" data-tooltip="Déterminer aléatoirement les détails de description">Description <i class="fa-solid fa-dice-d20"></i></a>
</ul> </ul>
</article> </article>

View File

@@ -55,7 +55,7 @@
<li class="caracteristique flexrow list-item" data-tooltip="Niveau d'éthylisme"> <li class="caracteristique flexrow list-item" data-tooltip="Niveau d'éthylisme">
<label class="derivee-label" for="system.compteurs.ethylisme.value">{{system.compteurs.ethylisme.label}}</label> <label class="derivee-label" for="system.compteurs.ethylisme.value">{{system.compteurs.ethylisme.label}}</label>
<select class="derivee-value" name="system.compteurs.ethylisme.value" data-dtype="Number"> <select class="derivee-value" name="system.compteurs.ethylisme.value" data-dtype="Number">
{{selectOptions @root.config.niveauEthylisme selected=system.compteurs.ethylisme.value valueAttr="value" nameAttr="value" labelAttr="label"}} {{selectOptions (RDD_CONFIG 'niveauEthylisme') selected=system.compteurs.ethylisme.value valueAttr="value" nameAttr="value" labelAttr="label"}}
</select> </select>
</li> </li>

View File

@@ -2,13 +2,13 @@
<li class="caracteristique flexrow list-item"> <li class="caracteristique flexrow list-item">
<span class="carac-label" name="catEntite">Catégorie : </span> <span class="carac-label" name="catEntite">Catégorie : </span>
<select name="system.definition.categorieentite" value="{{system.definition.categorieentite}}" data-dtype="String" {{#unless @root.options.vueDetaillee}}disabled{{/unless}}> <select name="system.definition.categorieentite" value="{{system.definition.categorieentite}}" data-dtype="String" {{#unless @root.options.vueDetaillee}}disabled{{/unless}}>
{{selectOptions @root.config.categorieEntite selected=system.definition.categorieentite}} {{selectOptions (RDD_CONFIG 'categorieEntite') selected=system.definition.categorieentite}}
</select> </select>
</li> </li>
<li class="caracteristique flexrow list-item"> <li class="caracteristique flexrow list-item">
<span class="carac-label" name="typeEntite">Type d'entité : </span> <span class="carac-label" name="typeEntite">Type d'entité : </span>
<select name="system.definition.typeentite" value="{{system.definition.typeentite}}" data-dtype="String" {{#unless @root.options.vueDetaillee}}disabled{{/unless}}> <select name="system.definition.typeentite" value="{{system.definition.typeentite}}" data-dtype="String" {{#unless @root.options.vueDetaillee}}disabled{{/unless}}>
{{selectOptions @root.config.typeEntite selected=system.definition.typeentite}} {{selectOptions (RDD_CONFIG 'typeEntite') selected=system.definition.typeentite}}
</select> </select>
</li> </li>
{{#each system.attributs as |attr key|}} {{#each system.attributs as |attr key|}}

View File

@@ -7,7 +7,7 @@
<label class="carac-xp"/> <label class="carac-xp"/>
{{else}} {{else}}
{{#if carac.derivee}} {{#if carac.derivee}}
<span class="carac-label" name="system.carac.{{key}}.label"><a name={{key}}>{{carac.label}}</a></span> <span class="carac-label roll-carac" name="system.carac.{{key}}.label"><a name={{key}}>{{carac.label}}</a></span>
<label class="competence-value">{{carac.value}}</label> <label class="competence-value">{{carac.value}}</label>
<label class="carac-xp"/> <label class="carac-xp"/>
{{else}} {{else}}
@@ -22,7 +22,7 @@
</a> </a>
</span> </span>
{{else}} {{else}}
<span class="carac-label tooltip" name="system.carac.{{key}}.label"><a name={{key}}>{{carac.label}}</a></span> <span class="carac-label roll-carac tooltip" name="system.carac.{{key}}.label"><a name={{key}}>{{carac.label}}</a></span>
{{/if}} {{/if}}
<input class="carac-value" type="text" name="system.carac.{{key}}.value" value="{{carac.value}}" data-dtype="{{carac.type}}" {{#unless @root.options.vueDetaillee}}disabled{{/unless}} /> <input class="carac-value" type="text" name="system.carac.{{key}}.value" value="{{carac.value}}" data-dtype="{{carac.type}}" {{#unless @root.options.vueDetaillee}}disabled{{/unless}} />
<span class="carac-xp tooltip"> <span class="carac-xp tooltip">

View File

@@ -25,14 +25,14 @@
<span class="competence-value">{{plusMoins arme.system.niveau}}</span> <span class="competence-value">{{plusMoins arme.system.niveau}}</span>
<span class="competence-value">{{plusMoins arme.system.dommagesReels}}</span> <span class="competence-value">{{plusMoins arme.system.dommagesReels}}</span>
<span class="competence-value"></span> <span class="competence-value"></span>
<span class="initiative-value arme-initiative"><a data-tooltip="{{arme.name}}: initiative {{plusMoins arme.system.initiative}}">{{arme.system.initiative}}</a></span> <span class="initiative-value arme-initiative"><a data-tooltip="{{arme.name}}: initiative {{arme.system.initiative}}">{{arme.system.initiative}}</a></span>
</li> </li>
{{/each}} {{/each}}
{{#each esquives as |esq key|}} {{#each esquives as |esq key|}}
<li class="item flexrow list-item" data-item-id="{{esq._id}}" <li class="item flexrow list-item" data-item-id="{{esq._id}}"
data-tooltip="{{esq.name}}: niveau {{plusMoins esq.system.niveau}}"> data-tooltip="{{esq.name}}: niveau {{plusMoins esq.system.niveau}}">
<span class="competence-label"> <span class="competence-label">
<a class="competence-label" name="{{esq.name}}"> <a class="roll-competence" name="{{esq.name}}">
<img class="sheet-competence-img" src="{{esq.img}}" /> <img class="sheet-competence-img" src="{{esq.img}}" />
<span>{{esq.name}}</span> <span>{{esq.name}}</span>
</a> </a>

View File

@@ -1,7 +1,7 @@
<ol class="item-list alterne-list"> <ol class="item-list alterne-list">
{{#each (trier competences) as |comp key|}} {{#each (trier competences) as |comp key|}}
<li class="item flexrow list-item" data-item-id="{{comp._id}}"> <li class="item flexrow list-item" data-item-id="{{comp._id}}">
<a class="competence-label"> <a class="competence-label roll-competence">
<img class="sheet-competence-img" src="{{comp.img}}" data-tooltip="{{comp.name}}"/> <img class="sheet-competence-img" src="{{comp.img}}" data-tooltip="{{comp.name}}"/>
<span>{{comp.name}}</span> <span>{{comp.name}}</span>
</a> </a>

View File

@@ -1,6 +1,6 @@
{{#unless system.isHidden}} {{#unless system.isHidden}}
<li class="item flexrow list-item {{#if system.isLevelUp}}xp-level-up tooltip{{/if}}" data-item-id="{{_id}}"> <li class="item flexrow list-item {{#if system.isLevelUp}}xp-level-up tooltip{{/if}}" data-item-id="{{_id}}">
<a class="competence-label" name="{{name}}" data-tooltip="Niveau {{plusMoins system.niveau}} en {{name}}"> <a class="competence-label roll-competence" name="{{name}}" data-tooltip="Niveau {{plusMoins system.niveau}} en {{name}}">
<img class="sheet-competence-img" src="{{img}}"/> <img class="sheet-competence-img" src="{{img}}"/>
<span>{{name}}</span> <span>{{name}}</span>
</a> </a>

View File

@@ -0,0 +1,105 @@
<form class="{{cssClass}}" autocomplete="off" >
<section class="sheet-header">
<div class="flexrow">
<h1 class="flex-grow charname">{{name}}</h1>
{{#if options.exportScriptarium}}
<span class="flex-group-right flex-shrink chat-card-button-area"><a class="button-export chat-card-button">Export </a></span>
{{/if}}
</div>
</section>
<section class="sheet-body" style=:"margin-bottom: 3rem;">
<div>
<strong>{{export.name.value}}</strong>{{#if export.description.value}}, {{export.description.value}}{{/if}}
</div>
<hr>
<div class="grid-2col">
<div class="flexcol flex-group-top">
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.taille}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.apparence}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.constitution}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.force}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.agilite}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.dexterite}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.vue}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.ouie}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.odoratgout}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.volonte}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.empathie}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.intellect}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-compteur.hbs" carac=export.reve actuel=export.reve_actuel}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac.hbs" carac=export.chance}}
</div>
<div class="flexcol flex-group-top">
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee.hbs" carac=export.melee}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee.hbs" carac=export.tir}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee.hbs" carac=export.lancer}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee.hbs" carac=export.derobee}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee-compteur.hbs" carac=export.vie actuel=export.vie_actuel}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee-compteur.hbs" carac=export.endurance actuel=export.vie_actuel}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee.hbs" carac=export.plusdom}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/protection.hbs" export}}
</div>
</div>
<hr>
<div>
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs" name=' ' niveau='Niv' init='Init' dommages='+dom'}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs" name=export.arme_name_0.value niveau=export.arme_niveau_0.value init=export.arme_init_0.value dommages=export.arme_dommages_0.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs" name=export.arme_name_1.value niveau=export.arme_niveau_1.value init=export.arme_init_1.value dommages=export.arme_dommages_1.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs" name=export.arme_name_2.value niveau=export.arme_niveau_2.value init=export.arme_init_2.value dommages=export.arme_dommages_2.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs" name=export.arme_name_3.value niveau=export.arme_niveau_3.value init=export.arme_init_3.value dommages=export.arme_dommages_3.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs" name=export.arme_name_4.value niveau=export.arme_niveau_4.value init=export.arme_init_4.value dommages=export.arme_dommages_4.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs" name=export.arme_name_5.value niveau=export.arme_niveau_5.value init=export.arme_init_5.value dommages=export.arme_dommages_5.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs" name=export.arme_name_6.value niveau=export.arme_niveau_6.value init=export.arme_init_6.value dommages=export.arme_dommages_6.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs" name=export.arme_name_7.value niveau=export.arme_niveau_7.value init=export.arme_init_7.value dommages=export.arme_dommages_7.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs" name=export.arme_name_8.value niveau=export.arme_niveau_8.value init=export.arme_init_8.value dommages=export.arme_dommages_8.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/arme.hbs" name=export.arme_name_9.value niveau=export.arme_niveau_9.value init=export.arme_init_9.value dommages=export.arme_dommages_9.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/esquive.hbs" name='Esquive' niveau=export.esquive.value}}
{{#if (gt export.malue_armure.value 0)}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/esquive.hbs" name='Esquive (avec armure)' niveau=export.esquive_armure.value}}
{{/if}}
</div>
<hr>
<div>
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/competences.hbs" competences=competences}}
</div>
<hr>
<div>
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/competences.hbs" competences=draconic }}
</div>
<hr>
<div>
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_0.value description=export.sort_description_0.value bonus=export.sort_bonus_0.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_1.value description=export.sort_description_1.value bonus=export.sort_bonus_1.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_2.value description=export.sort_description_2.value bonus=export.sort_bonus_2.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_3.value description=export.sort_description_3.value bonus=export.sort_bonus_3.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_4.value description=export.sort_description_4.value bonus=export.sort_bonus_4.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_5.value description=export.sort_description_5.value bonus=export.sort_bonus_5.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_6.value description=export.sort_description_6.value bonus=export.sort_bonus_6.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_7.value description=export.sort_description_7.value bonus=export.sort_bonus_7.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_8.value description=export.sort_description_8.value bonus=export.sort_bonus_8.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_9.value description=export.sort_description_9.value bonus=export.sort_bonus_9.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_10.value description=export.sort_description_10.value bonus=export.sort_bonus_10.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_11.value description=export.sort_description_11.value bonus=export.sort_bonus_11.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_12.value description=export.sort_description_12.value bonus=export.sort_bonus_12.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_13.value description=export.sort_description_13.value bonus=export.sort_bonus_13.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_14.value description=export.sort_description_14.value bonus=export.sort_bonus_14.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_15.value description=export.sort_description_15.value bonus=export.sort_bonus_15.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_16.value description=export.sort_description_16.value bonus=export.sort_bonus_16.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_17.value description=export.sort_description_17.value bonus=export.sort_bonus_17.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_18.value description=export.sort_description_18.value bonus=export.sort_bonus_18.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_19.value description=export.sort_description_19.value bonus=export.sort_bonus_19.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_20.value description=export.sort_description_20.value bonus=export.sort_bonus_20.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_21.value description=export.sort_description_21.value bonus=export.sort_bonus_21.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_22.value description=export.sort_description_22.value bonus=export.sort_bonus_22.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_23.value description=export.sort_description_23.value bonus=export.sort_bonus_23.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_24.value description=export.sort_description_24.value bonus=export.sort_bonus_24.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_25.value description=export.sort_description_25.value bonus=export.sort_bonus_25.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_26.value description=export.sort_description_26.value bonus=export.sort_bonus_26.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_27.value description=export.sort_description_27.value bonus=export.sort_bonus_27.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_28.value description=export.sort_description_28.value bonus=export.sort_bonus_28.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/sort.hbs" voie=export.sort_voie_29.value description=export.sort_description_29.value bonus=export.sort_bonus_29.value}}
<div>&nbsp;</div>
<div>&nbsp;</div>
</div>
</section>
</form>

View File

@@ -0,0 +1,15 @@
{{#if name}}
<div class="flexrow">
<div>{{upperFirst name}}</div>
<div class="flexrow">
<div>{{niveau}}</div>
{{#if init}}
<div>{{init}}</div>
<div>{{dommages}}</div>
{{else}}
<div></div>
<div></div>
{{/if}}
</div>
</div>
{{/if}}

View File

@@ -0,0 +1,19 @@
<div class="flexrow">
<div>
{{#if carac.rollClass}}
<a class="{{carac.rollClass}}" name="{{carac.column}}">
{{upper carac.colName}}
</a>
{{else}}
{{upper carac.colName}}
{{/if}}
</div>
<div class="flex-group-right {{actuel.rollClass}}">
<a>
{{#unless (eq carac.value actuel.value)}}
{{actuel.value}} /
{{/unless}}
{{carac.value}}
</a>
</div>
</div>

View File

@@ -0,0 +1,19 @@
<div class="flexrow">
<div>
{{#if carac.rollClass}}
<a class="{{carac.rollClass}}" name="{{carac.column}}">
{{upperFirst carac.colName}}
</a>
{{else}}
{{upperFirst carac.colName}}
{{/if}}
</div>
<div class="flex-group-right {{actuel.rollClass}}">
<a>
{{#unless (eq carac.value actuel.value)}}
{{actuel.value}} /
{{/unless}}
{{carac.value}}
</a>
</div>
</div>

View File

@@ -0,0 +1,12 @@
<div class="flexrow">
<div>
{{#if carac.rollClass}}
<a class="{{carac.rollClass}}" name="{{carac.column}}">
{{upperFirst carac.colName}}
</a>
{{else}}
{{upperFirst carac.colName}}
{{/if}}
</div>
<div class="flex-group-right">{{carac.value}}</div>
</div>

View File

@@ -0,0 +1,10 @@
<div class="flexrow">
<div>
{{#if carac.rollClass}}
<a class="{{carac.rollClass}}" name="{{carac.column}}">{{upper carac.colName}}</a>
{{else}}
{{upper carac.colName}}
{{/if}}
</div>
<div class="flex-group-right">{{carac.value}}</div>
</div>

View File

@@ -0,0 +1,9 @@
{{#each competences as |group|}}
{{#if @index}}/{{/if}}
{{#with group}}
{{#each list as |comp|}}
<span class="item" data-item-id="{{comp._id}}"><a class="roll-competence">{{comp.name}}</a></span>{{~#unless (isLastIndex @index ../list)~}},{{/unless~}}
{{/each}}
{{numberFormat niveau decimals=0 sign=true}}
{{/with}}
{{/each}}

View File

@@ -0,0 +1,10 @@
{{#if name}}
<div class="flexrow">
<div>{{upperFirst name}}</div>
<div class="flexrow">
<div>{{niveau}}</div>
<div></div>
<div></div>
</div>
</div>
{{/if}}

View File

@@ -0,0 +1,7 @@
{{#if protectionnaturelle.value}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee.hbs" carac=protectionnaturelle}}
{{/if}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/export-scriptarium/carac-derivee.hbs" carac=protectionarmure}}
{{#if armure.value}}
<div class="flexrow flex-group-right"><i>{{armure.value}}</i></div>
{{/if}}

View File

@@ -0,0 +1,11 @@
{{#if voie}}
<div class="flexrow">
<div style="flex-grow: 0.4;">{{voie}}</div>
<div class="flex-grow-2">{{upperFirst description}}</div>
{{#if bonus}}
<div>{{bonus}}</div>
{{else}}
<div></div>
{{/if}}
</div>
{{/if}}

View File

@@ -30,7 +30,7 @@
</li> </li>
<li> <li>
<label class="compteur"> <label class="compteur">
<span class="ptreve-actuel" data-tooltip="Faire un jet de Rêve actuel (ou jet de résistance)"><a>Rêve</a></span> <span class="roll-reve-actuel" data-tooltip="Faire un jet de Rêve actuel (ou jet de résistance)"><a>Rêve</a></span>
<a class="ptreve-actuel-moins"><i class="fa-solid fa-square-minus"></i></a> <a class="ptreve-actuel-moins"><i class="fa-solid fa-square-minus"></i></a>
<input class="resource-content" class="pointsreve-value" type="text" name="system.reve.reve.value" value="{{system.reve.reve.value}}" data-dtype="Number" /> <input class="resource-content" class="pointsreve-value" type="text" name="system.reve.reve.value" value="{{system.reve.reve.value}}" data-dtype="Number" />
<span>/ {{system.reve.seuil.value}}</span> <span>/ {{system.reve.seuil.value}}</span>

View File

@@ -0,0 +1,53 @@
<form class="app-personnage-aleatoire">
<h2>Génération aléatoire pour {{actor.name}}</h2>
<div class="flex-group-left">
{{#if options.isGM}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs"
label="Nom" path="name" type="text" value=current.name checked=checked.name
}}
{{/if}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs"
label="Sexe" path="system.sexe" type="text"
value=current.system.sexe checked=checked.system.sexe
}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs"
label="Age" path="system.age" type="entier" min=10 max=100
value=current.system.age checked=checked.system.age
}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs"
label="Taille" path="system.taille" type="text"
value=current.system.taille checked=checked.system.taille
}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs"
label="Poids" path="system.poids" type="text"
value=current.system.poids checked=checked.system.poids
}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs"
label="Main directrice" path="system.main" type="text"
value=current.system.main checked=checked.system.main
}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs"
label="Heure de naissance" path="system.heure" type="heure"
value=current.system.heure checked=checked.system.heure
}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs"
label="Cheveux" path="system.cheveux" type="text"
value=current.system.cheveux checked=checked.system.cheveux
}}
{{>"systems/foundryvtt-reve-de-dragon/templates/actor/random/champ-aleatoire.hbs"
label="Yeux" path="system.yeux" type="text"
value=current.system.yeux checked=checked.system.yeux
}}
</div>
<hr>
<div style="text-align: right;">
<a class="chat-card-button randomize-selected">Générer les valeurs sélectionnés</a>
</div>
<br>
<div class="flexrow">
<button class="button-cancel">Annuler</button>
<button class="button-apply">Appliquer à {{actor.name}}</button>
</div>
<br>
</form>

View File

@@ -0,0 +1,19 @@
<div class="flexrow random-field" data-path="{{path}}">
<label for="{{path}}">{{label}}:</label>
{{#if (eq type 'entier')}}
<input class="current-value" name="current.{{path}}" value="{{value}}" placeholder="{{label}}" type="number" data-dtype="Number" min="{{min}}" max="{{max}}"/>
{{else if (eq type 'heure')}}
<select class="current-value" name="current.{{path}}" value="{{value}}" type="text" data-dtype="String">
{{#select value}}
{{> "systems/foundryvtt-reve-de-dragon/templates/enum-heures.html"}}
{{/select}}
</select>
{{else}}
<input class="current-value" name="current.{{path}}" value="{{value}}" placeholder="{{label}}" type="text" data-dtype="String"/>
{{/if}}
<div class="item-controls">
<a class="random" data-action="random" data-tooltip="Aléatoire"><i class="fa-solid fa-dice-d20"></i></a>
<a class="reset" data-action="reset" data-tooltip="Reset"><i class="fa-solid fa-eraser"></i></a>
<input class="check-for-random" type="checkbox" data-tooltip="Sélectionné pour génération automatique" {{#if checked}}checked{{/if}}/>
</div>
</div>

View File

@@ -1,5 +1,5 @@
<h4>Tirage aléatoire: {{typeName}}</h4> <h4>Tirage aléatoire: {{document.name}}</h4>
<div>{{document.pack}}</div> <div>Tirage de {{typeName}} aléatoire depuis {{document.pack}}</div>
<div>Jet {{roll.formula}} : {{roll.total}}{{percentages}}</div> <div>Jet {{roll.formula}} : {{roll.total}}{{percentages}}</div>
<hr> <hr>
<div> <div>

View File

@@ -6,7 +6,7 @@
type="number" data-dtype="Number" min="1" max="28" type="number" data-dtype="Number" min="1" max="28"
name="{{path}}.jourDuMois" value="{{jourDuMois}}" /> name="{{path}}.jourDuMois" value="{{jourDuMois}}" />
<select {{#if disabled}}{{disabled}}{{/if}} name="{{path}}.mois" class="calendar-signe-heure" data-dtype="String"> <select {{#if disabled}}{{disabled}}{{/if}} name="{{path}}.mois" class="calendar-signe-heure" data-dtype="String">
{{select config.heuresRdD selected=mois.key labelAttr="label" nameAttr="value" valueAttr="value"}} {{selectOptions (RDD_CONFIG 'heuresRdD') selected=mois.key labelAttr="label" nameAttr="value" valueAttr="value"}}
</select> </select>
{{timestamp-imgSigne mois}} {{timestamp-imgSigne mois}}
<input {{#if disabled}}{{disabled}}{{/if}} type="number" class="number-x2" name="{{path}}.annee" value="{{annee}}" data-dtype="Number"/> <input {{#if disabled}}{{disabled}}{{/if}} type="number" class="number-x2" name="{{path}}.annee" value="{{annee}}" data-dtype="Number"/>
@@ -15,7 +15,7 @@
<label></label> <label></label>
<label>heure</label> <label>heure</label>
<select {{#if disabled}}{{disabled}}{{/if}} name="{{path}}.heure" class="calendar-signe-heure" data-dtype="String"> <select {{#if disabled}}{{disabled}}{{/if}} name="{{path}}.heure" class="calendar-signe-heure" data-dtype="String">
{{select config.heuresRdD selected=heure.key labelAttr="label" nameAttr="value" valueAttr="value"}} {{selectOptions (RDD_CONFIG 'heuresRdD') selected=heure.key labelAttr="label" nameAttr="value" valueAttr="value"}}
</select> </select>
{{timestamp-imgSigne heure}} {{timestamp-imgSigne heure}}
<input {{#if disabled}}{{disabled}}{{/if}} type="number" class="number-x2" name="{{path}}.minute" value="{{minute}}" data-dtype="Number"/> <input {{#if disabled}}{{disabled}}{{/if}} type="number" class="number-x2" name="{{path}}.minute" value="{{minute}}" data-dtype="Number"/>

View File

@@ -3,3 +3,5 @@
<option value="{{competence.name}}">{{competence.name}}</option> <option value="{{competence.name}}">{{competence.name}}</option>
{{/if}} {{/if}}
{{/each}} {{/each}}
<option value="O/H/N/T">Oniros/Hypnos/Narcos/Thanatos</option>
<option value="O/H/N">Oniros/Hypnos/Narcos</option>

View File

@@ -18,6 +18,7 @@
<a class="milieu-add"><i class="fas fa-plus-circle"></i></a> <a class="milieu-add"><i class="fas fa-plus-circle"></i></a>
</span> </span>
</div> </div>
{{#each system.environnement as |env key|}} {{#each system.environnement as |env key|}}
<div class="form-group environnement-milieu" data-milieu="{{env.milieu}}"> <div class="form-group environnement-milieu" data-milieu="{{env.milieu}}">
<label> <label>
@@ -26,7 +27,7 @@
</label> </label>
<span class="flexrow"> <span class="flexrow">
<select name="milieu-{{key}}-rarete" class="environnement-rarete flex-shrink" data-dtype="String"> <select name="milieu-{{key}}-rarete" class="environnement-rarete flex-shrink" data-dtype="String">
{{selectOptions config.rarete selected=env.rarete labelAttr="label" valueAttr="value" nameAttr="value"}} {{selectOptions (RDD_CONFIG 'raretes') selected=env.rarete labelAttr="label" valueAttr="value" nameAttr="value"}}
</select> </select>
{{rangePicker name="milieu-{{key}}-frequence" value=env.frequence min=(rarete-getChamp env.rarete 'min') max=(rarete-getChamp env.rarete 'max') step=1}} {{rangePicker name="milieu-{{key}}-frequence" value=env.frequence min=(rarete-getChamp env.rarete 'min') max=(rarete-getChamp env.rarete 'max') step=1}}
<label>[{{rarete-getChamp env.rarete 'min'}}-{{rarete-getChamp env.rarete 'max'}}]</label> <label>[{{rarete-getChamp env.rarete 'min'}}-{{rarete-getChamp env.rarete 'max'}}]</label>

View File

@@ -0,0 +1,13 @@
<form autocomplete="off" onsubmit="event.preventDefault();">
{{#each groups as |group key|}}
<h3>{{key}}</h3>
<ul>
{{#each group as |regle r|}}
<li>
<input class="select-option" type="checkbox" name="{{regle.id}}" {{#if regle.active}}checked{{/if}}/>
<label>{{regle.descr}}</label>
</li>
{{/each}}
</ul>
{{/each}}
</form>

View File

@@ -42,7 +42,8 @@
<li class="competence-header flexrow"> <li class="competence-header flexrow">
<span class="flex-grow-2">Personnage</span> <span class="flex-grow-2">Personnage</span>
<span class="flex-grow-2">Survies</span> <span class="flex-grow-2">Survies</span>
<span class="flex-grow-1" data-tooltip="Ajustements à appliquer pour les personnages se reposant (par exemple, à cheval)">Ajustements</span> <span class="flex-grow-1" data-tooltip="Ajustements à appliquer (par exemple, repos à cheval)">Ajustements</span>
<span class="flex-grow-1" data-tooltip="Total de fatigue pour le voyageur">Total</span>
</li> </li>
{{#each playerActors as |selected|}} {{#each playerActors as |selected|}}
{{>'systems/foundryvtt-reve-de-dragon/templates/voyage/fatigue-actor.hbs' voyageur=selected survies=@root.typeTerrain.survies}} {{>'systems/foundryvtt-reve-de-dragon/templates/voyage/fatigue-actor.hbs' voyageur=selected survies=@root.typeTerrain.survies}}

View File

@@ -8,16 +8,13 @@
</span> </span>
<span class="flex-grow-2"> <span class="flex-grow-2">
<div class="flexcol "> <div class="flexcol ">
<label class="voyage-liste-survies"> <label class="voyage-liste-survies">{{voyageur.survieCourante}}</label>
{{#each voyageur.competencesVoyage as |comp key|}}
{{#if (array-includes ../survies key)}}
{{key}} {{comp.system.niveau}},
{{/if}}
{{/each}}
</label>
</div> </div>
</span> </span>
<span class="flex-grow-1"> <span class="flex-grow-1">
<input type="number" name="ajustement-fatigue" class="number-x2 ajustement-fatigue" data-dtype="Number" value="{{voyageur.ajustementFatigue}}" min="-6" max="6"/> <input type="number" name="ajustement-fatigue" class="number-x2 ajustement-fatigue" data-dtype="Number" value="{{voyageur.ajustementFatigue}}" min="-6" max="6"/>
</span> </span>
<span class="flex-grow-1">
<input type="number" name="total-fatigue" class="number-x2 total-fatigue" data-dtype="Number" value="1" min="0" max="24" disabled/>
</span>
</li> </li>