Compare commits

...

72 Commits

Author SHA1 Message Date
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
9bc2593b8c Sync version to v12 2024-06-12 08:21:03 +02:00
efd02b40a9 Merge pull request 'Version 11.2.22 - Le futur d'Akarlikarlikar' (#702) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #702
2024-06-12 08:16:17 +02:00
feb3116c47 Version 11.2.22 2024-06-12 01:02:03 +02:00
91a870ad91 Merge pull request 'Fix User ... lacks permission to update' (#701) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #701
2024-06-11 07:52:59 +02:00
2bbf606f30 Fix User ... lacks permission to update
Correction de l'erreur qui était affichée chez les joueurs lors de
hooks utilisés pour effectuer des modifications sur des
documents:

- ChatMessage, ajout de flags pour l'heure
- Item au sein d'un Actor pour mettre à jour certains éléments
2024-06-11 02:49:18 +02:00
a385b98126 Various fixes for v12 2024-06-07 11:12:00 +02:00
8775df5285 Merge pull request 'Corrections v12' (#700) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #700
2024-06-01 09:11:18 +02:00
a103239288 Passe de vérification mergeObject
Quand mergeObject est utilisé pour retourner une valeur, faire très
attention à ne pas passer un Item/Actor, ou une de ses sous parties
en premier paramètre sans préciser l'option { inplace: false }

Sinon, le premier paramètre subit une mutation!
2024-06-01 01:53:14 +02:00
0b1c5d0a3d Fix again achatVente
- remplacement des données/JSON dans le html par des Flags sur
  le ChatMessage
- extraction de la gestion des infos de ventes pour rassembler la
  génération du ChatMessage
- on ne perd plus la quantité ou le vendeur
- attention au mergeObject: il modifie le premier parametre, ce
  qui modifiait parfois l'acteur (!!!) et toujours la quantité de
  l'objet du vendeur lors de la création de l'objet de l'acheteur!
2024-06-01 01:50:48 +02:00
e19577eab2 Fix for v12 2024-05-31 21:48:19 +02:00
c3b502ff6c Fix V12 Fenêtre de recherche 2024-05-31 21:42:09 +02:00
db2ca2453e Foundry v11/v12 support 2024-05-27 08:53:57 +02:00
915283a674 Merge pull request '11.2.21 - Le questionnement d'Akarlikarlikar' (#699) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #699
2024-05-27 07:17:09 +02:00
621bb4ebc3 Version 11.2.21 2024-05-27 00:57:12 +02:00
26e805cf46 Ajout de la date/heure aux messages 2024-05-27 00:55:18 +02:00
657566fb11 Les effets s'appliquent aux créatures 2024-05-26 22:43:07 +02:00
26e8853a94 Passage v12 2024-05-26 22:16:42 +02:00
4f69d3cf78 Expérience sur rêve et chance actuels
L'expérience en caractéristique sur les jets de
2024-05-26 22:15:10 +02:00
dfe4b47452 Message de confirmation rencontre TMR
Quand un haut-rêvant monte dans les TMR avec une rencontre en attente,
un message est affiché pour demander confirmation
2024-05-26 22:13:47 +02:00
80719d8c15 Merge pull request '## 11.2.20 - Le soulagement d'Akarlikarlikar' (#698) from VincentVk/foundryvtt-reve-de-dragon:v11 into v11
Reviewed-on: #698
2024-05-13 17:24:51 +02:00
5c59f76c17 Version 11.2.20 2024-05-13 01:58:06 +02:00
65525cfd79 Correction récupération seuil
La récupération de seuil sur Rêve de Dragon était empéchée
par la gestion d'expérience quand aucune expérience n'était
gagnée.

Le même problème pouvait arriver pour d'autres raisons.
2024-05-13 01:58:06 +02:00
042f5d0f69 Cleanup Promise.all pour multi async 2024-05-13 01:50:22 +02:00
19dd3b540c Astrologie: garder toutes les lectures d'un acteur 2024-05-13 01:50:21 +02:00
611b57c149 Adaptation des encaissement alternatifs
Les encaissement alternatifs fonctionnent avec la validation
d'encaissement par le MJ.

- l'ajout de la difficulté d'attaque au dégâts est indiqué dans
les bonus de dégâts
- pour les minimums sur les dés d'encaissement, si le MJ remplace
le jet, les minimums sont alors ignorés.
2024-05-13 01:50:21 +02:00
fedf8f3b29 Fix: accorder entités x2 si validation GR
Les entités pouvaient être accordées 2 fois en cas de validation
par le GR
2024-05-13 01:50:12 +02:00
d1ec67e485 Correction Tooltips foundry
Suite à changement des Tooltips RdD, adaptation des tooltips
standard foundry
2024-05-12 19:37:58 +02:00
7f7148e658 Preparation du passage en v12 2024-05-02 14:08:02 +02:00
81 changed files with 997 additions and 733 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -1,4 +1,87 @@
# 12.0
## 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.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
- L'expérience en caractéristique sur les jets de chance et rêve actuels est mise dans la caractéristique correspondante
- Les effets s'appliquent correctement sur les créatures
- La date et l'heure (draconiques) sont affichées dans les messages du tchat
## 11.2.20 - Le soulagement d'Akarlikarlikar
- L'option "ajout de la difficulté d'attaque à l'encaissement" est affichée comme un modificateur d'encaissement
- Les options d'encaissement alternatives fonctionnent avec la validation de l'encaissement par le gardien
- La fenêtre d'astrologie du gardien affiche toutes les heures lues par un personnage
- Si aucune expérience n'est gagnée, les autres effets à appliquer (comme la récupération de seuil après avoir vaincu un rêve de Dragon) s'appliquent normalement
- Les tooltips de Foundry sont lisibles
- On n'accorde plus les entités de cauchemar deux fois quand le gardien valide les encaissements
- Les messages de récupération de rêve en cas de Rêve de Dragon sont clarifiés
## 11.2.19 - Les hémorroïdes d'Akarlikarlikar ## 11.2.19 - Les hémorroïdes d'Akarlikarlikar
- La validation des jets d'encaissement par le Gardien fonctionne de nouveau - La validation des jets d'encaissement par le Gardien fonctionne de nouveau

4
icons/heures/.directory Normal file
View File

@ -0,0 +1,4 @@
[Dolphin]
Timestamp=2024,5,29,20,57,41.954
Version=4
VisibleRoles=Details_text,Details_size,Details_modificationtime,Details_creationtime,CustomizedDetails

View File

@ -0,0 +1,65 @@
import { SYSTEM_RDD } from "../constants.js";
import { RdDUtility } from "../rdd-utility.js";
const DETAIL_VENTE = 'detailVente';
const NB_LOTS = 'nbLotss';
export class ChatVente {
static getDetailVente(chatMessageId) {
const chatMessage = game.messages.get(chatMessageId)
if (!chatMessage) {
return undefined;
}
const nbLots = chatMessage.getFlag(SYSTEM_RDD, NB_LOTS)
const detail = foundry.utils.duplicate(chatMessage.getFlag(SYSTEM_RDD, DETAIL_VENTE))
if (!detail.item) {
ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes")
return undefined;
}
const vendeur = detail.vendeurId ? game.actors.get(detail.vendeurId) : undefined;
return foundry.utils.mergeObject(detail,
{
alias: vendeur?.name ?? game.user.name,
vendeur,
nbLots: nbLots,
chatMessageIdVente: chatMessageId
})
}
static getDetailAchatVente(chatMessageId) {
const acheteur = RdDUtility.getSelectedActor()
const detail = ChatVente.getDetailVente(chatMessageId)
if (!acheteur && !detail.vendeur) {
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
return undefined;
}
return foundry.utils.mergeObject(detail, { acheteur })
}
static async diminuerQuantiteAchatVente(chatMessageId, quantite) {
const chatMessage = game.messages.get(chatMessageId)
const vente = ChatVente.getDetailVente(chatMessageId)
vente.nbLots = Math.max(0, vente.nbLots - quantite)
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
chatMessage.update({ content: html });
chatMessage.render(true);
}
static async displayAchatVente(vente) {
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
const chatMessage = await ChatMessage.create(RdDUtility.chatDataSetup(html))
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
await chatMessage.setFlag(SYSTEM_RDD, DETAIL_VENTE, {
item: vente.item,
properties: vente.item.getProprietes(),
vendeurId: vente.vendeurId,
tailleLot: vente.tailleLot,
quantiteIllimite: vente.quantiteIllimite,
prixLot: vente.prixLot
})
}
}

View File

@ -1,35 +1,13 @@
import { Misc } from "./misc.js"; import { Misc } from "../misc.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "../rdd-utility.js";
import { ChatVente } from "./chat-vente.js";
export class DialogItemAchat extends Dialog { export class DialogItemAchat extends Dialog {
static preparerAchat(chatButton) { static preparerAchat(chatButton) {
const vendeurId = chatButton.attributes['data-vendeurId']?.value; return ChatVente.getDetailAchatVente(RdDUtility.findChatMessageId(chatButton))
const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined;
const acheteur = RdDUtility.getSelectedActor();
const json = chatButton.attributes['data-jsondata']?.value;
if (!acheteur && !vendeur) {
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
return undefined;
}
if (!json) {
ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes")
return undefined;
}
return {
item: JSON.parse(json),
vendeur,
acheteur,
nbLots: parseInt(chatButton.attributes['data-quantiteNbLots']?.value),
tailleLot: parseInt(chatButton.attributes['data-tailleLot']?.value ?? 1),
prixLot: Number(chatButton.attributes['data-prixLot']?.value ?? 0),
quantiteIllimite: chatButton.attributes['data-quantiteIllimite']?.value == 'true',
chatMessageIdVente: RdDUtility.findChatMessageId(chatButton),
};
} }
static async onAcheter({ item, vendeur, acheteur, tailleLot, prixLot, nbLots, quantiteIllimite, chatMessageIdVente }) { static async onAcheter({ item, vendeur, acheteur, tailleLot, prixLot, nbLots, quantiteIllimite, chatMessageIdVente }) {
const venteData = { const venteData = {
item, item,
@ -38,17 +16,21 @@ export class DialogItemAchat extends Dialog {
acheteur, acheteur,
tailleLot, tailleLot,
quantiteIllimite, quantiteIllimite,
quantiteNbLots: nbLots, nbLots,
choix: { seForcer: false, supprimerSiZero: true }, choix: { seForcer: false, supprimerSiZero: true },
prixLot, prixLot,
isVente: prixLot > 0, isVente: prixLot > 0,
isConsommable: item.type == 'nourritureboisson' && acheteur?.isPersonnage(), isConsommable: item.type == 'nourritureboisson' && acheteur?.isPersonnage(),
chatMessageIdVente chatMessageIdVente
}; }
if (venteData.vendeur?.id == venteData.acheteur?.id) {
ui.notifications.info("Inutile de se vendre à soi-même")
return
}
DialogItemAchat.changeNombreLots(venteData, 1); DialogItemAchat.changeNombreLots(venteData, 1)
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData); const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData)
new DialogItemAchat(html, venteData).render(true); new DialogItemAchat(html, venteData).render(true)
} }
static changeNombreLots(venteData, nombreLots) { static changeNombreLots(venteData, nombreLots) {
@ -116,18 +98,18 @@ export class DialogItemAchat extends Dialog {
this.venteData.choix.seForcer = event.currentTarget.checked; this.venteData.choix.seForcer = event.currentTarget.checked;
} }
setNombreLots(nombreLots) { setNombreLots(nbLots) {
if (!this.venteData.quantiteIllimite) { if (!this.venteData.quantiteIllimite) {
if (!this.venteData.quantiteIllimite && nombreLots > this.venteData.quantiteNbLots) { if (!this.venteData.quantiteIllimite && nbLots > this.venteData.nbLots) {
ui.notifications.warn(`Seulement ${this.venteData.quantiteNbLots} lots disponibles, vous ne pouvez pas en prendre ${nombreLots}`) ui.notifications.warn(`Seulement ${this.venteData.nbLots} lots disponibles, vous ne pouvez pas en prendre ${nbLots}`)
} }
nombreLots = Math.min(nombreLots, this.venteData.quantiteNbLots); nbLots = Math.min(nbLots, this.venteData.nbLots);
} }
DialogItemAchat.changeNombreLots(this.venteData, nombreLots); DialogItemAchat.changeNombreLots(this.venteData, nbLots);
this.html.find(".nombreLots").val(nombreLots); this.html.find(".nombreLots").val(nbLots);
this.html.find(".prixTotal").text(this.venteData.prixTotal); this.html.find(".prixTotal").text(this.venteData.prixTotal);
this.html.find("span.total-sust").text(this.venteData.totalSust); this.html.find("span.total-sust").text(this.venteData.totalSust);
this.html.find("span.total-desaltere").text(this.venteData.totalDesaltere); this.html.find("span.total-desaltere").text(this.venteData.totalDesaltere);

View File

@ -1,29 +1,30 @@
import { HtmlUtility } from "./html-utility.js"; import { HtmlUtility } from "../html-utility.js";
import { RdDUtility } from "../rdd-utility.js";
import { ChatVente } from "./chat-vente.js";
export class DialogItemVente extends Dialog { export class DialogItemVente extends Dialog {
static async display({ item, callback, quantiteMax = undefined }) { static async display({ item, quantiteMax = undefined }) {
const quantite = quantiteMax ?? item.getQuantite() ?? 1; const quantite = quantiteMax ?? item.getQuantite() ?? 1;
const isOwned = item.parent;
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(),
tailleLot: 1, tailleLot: 1,
quantiteNbLots: quantite, nbLots: quantite,
quantiteMaxLots: quantite, maxLots: quantite,
quantiteMax: quantite, quantiteMax: quantite,
quantiteIllimite: item.isItemCommerce() ? quantiteMax == undefined : !isOwned, quantiteIllimite: item.isItemCommerce() ? quantiteMax == undefined : !item.parent,
isOwned: isOwned, isOwned: item.parent,
}; }
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData); const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData);
return new DialogItemVente(venteData, html, callback).render(true); return new DialogItemVente(venteData, html).render(true);
} }
constructor(venteData, html, callback) { constructor(venteData, html) {
let options = { classes: ["dialogvente"], width: 400, height: 'fit-content', 'z-index': 99999 }; let options = { classes: ["dialogvente"], width: 400, height: 'fit-content', 'z-index': 99999 };
let conf = { let conf = {
@ -34,7 +35,6 @@ export class DialogItemVente extends Dialog {
}; };
super(conf, options); super(conf, options);
this.callback = callback;
this.venteData = venteData; this.venteData = venteData;
} }
@ -43,7 +43,7 @@ export class DialogItemVente extends Dialog {
this.html = html; this.html = html;
this.html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value))); this.html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value)));
this.html.find(".quantiteNbLots").change(event => this.setNbLots(Number(event.currentTarget.value))); this.html.find(".nbLots").change(event => this.setNbLots(Number(event.currentTarget.value)));
this.html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked)); this.html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked));
this.html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value))); this.html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value)));
@ -52,7 +52,15 @@ export class DialogItemVente extends Dialog {
async onProposer(it) { async onProposer(it) {
this.updateVente(this.getChoixVente()); this.updateVente(this.getChoixVente());
this.callback(this.venteData);
this.venteData["properties"] = this.venteData.item.getProprietes();
if (this.venteData.isOwned) {
if (this.venteData.nbLots * this.venteData.tailleLot > this.venteData.quantiteMax) {
ui.notifications.warn(`Vous avez ${this.venteData.quantiteMax} ${this.venteData.item.name}, ce n'est pas suffisant pour vendre ${this.venteData.nbLots} de ${this.venteData.tailleLot}`)
return;
}
}
await ChatVente.displayAchatVente(this.venteData)
} }
updateVente(update) { updateVente(update) {
@ -61,7 +69,7 @@ export class DialogItemVente extends Dialog {
getChoixVente() { getChoixVente() {
return { return {
quantiteNbLots: Number(this.html.find(".quantiteNbLots").val()), nbLots: Number(this.html.find(".nbLots").val()),
tailleLot: Number(this.html.find(".tailleLot").val()), tailleLot: Number(this.html.find(".tailleLot").val()),
quantiteIllimite: this.html.find(".quantiteIllimite").is(':checked'), quantiteIllimite: this.html.find(".quantiteIllimite").is(':checked'),
prixLot: Number(this.html.find(".prixLot").val()) prixLot: Number(this.html.find(".prixLot").val())
@ -77,26 +85,26 @@ export class DialogItemVente extends Dialog {
const maxLots = Math.floor(this.venteData.quantiteMax / tailleLot); const maxLots = Math.floor(this.venteData.quantiteMax / tailleLot);
this.updateVente({ this.updateVente({
tailleLot, tailleLot,
quantiteNbLots: Math.min(maxLots, this.venteData.quantiteNbLots), nbLots: Math.min(maxLots, this.venteData.nbLots),
quantiteMaxLots: maxLots, maxLots: maxLots,
prixLot: (tailleLot * this.venteData.prixOrigine).toFixed(2) prixLot: (tailleLot * this.venteData.prixOrigine).toFixed(2)
}); });
this.html.find(".prixLot").val(this.venteData.prixLot); this.html.find(".prixLot").val(this.venteData.prixLot);
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots); this.html.find(".nbLots").val(this.venteData.nbLots);
this.html.find(".quantiteNbLots").attr("max", this.venteData.quantiteMaxLots) this.html.find(".nbLots").attr("max", this.venteData.maxLots)
} }
setNbLots(nbLots) { setNbLots(nbLots) {
this.updateVente({ this.updateVente({
quantiteNbLots: this.venteData.isOwned ? Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots)) : nbLots nbLots: this.venteData.isOwned ? Math.max(0, Math.min(nbLots, this.venteData.maxLots)) : nbLots
}) })
this.html.find(".quantiteNbLots").val(this.venteData.quantiteNbLots); this.html.find(".nbLots").val(this.venteData.nbLots);
} }
setQuantiteIllimite(checked) { setQuantiteIllimite(checked) {
this.updateVente({ quantiteIllimite: checked }) this.updateVente({ quantiteIllimite: checked })
this.html.find(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles"); this.html.find(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles");
HtmlUtility.showControlWhen(this.html.find(".quantiteNbLots"), !this.venteData.quantiteIllimite) HtmlUtility.showControlWhen(this.html.find(".nbLots"), !this.venteData.quantiteIllimite)
} }
} }

View File

@ -16,7 +16,6 @@ import { RdDItem } from "./item.js";
import { RdDItemBlessure } from "./item/blessure.js"; import { RdDItemBlessure } from "./item/blessure.js";
import { RdDEmpoignade } from "./rdd-empoignade.js"; import { RdDEmpoignade } from "./rdd-empoignade.js";
import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js"; import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js";
import { ChatUtility } from "./chat-utility.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -33,22 +32,20 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
width: 550, width: 550,
showCompNiveauBase: false, showCompNiveauBase: false,
vueArchetype: false, vueArchetype: false,
}); }, { inplace: false });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
let formData = await super.getData(); let formData = await super.getData();
foundry.utils.mergeObject(formData, foundry.utils.mergeObject(formData, {
{ editable: this.isEditable,
editable: this.isEditable, cssClass: this.isEditable ? "editable" : "locked",
cssClass: this.isEditable ? "editable" : "locked", limited: this.actor.limited,
effects: this.actor.effects.map(e => foundry.utils.deepClone(e)), owner: this.actor.isOwner,
limited: this.actor.limited, biographie: await TextEditor.enrichHTML(this.actor.system.biographie, { async: true }),
owner: this.actor.isOwner, notes: await TextEditor.enrichHTML(this.actor.system.notes, { async: true }),
biographie: await TextEditor.enrichHTML(this.actor.system.biographie, { async: true }), });
notes: await TextEditor.enrichHTML(this.actor.system.notes, { async: true }),
});
foundry.utils.mergeObject(formData.calc, { foundry.utils.mergeObject(formData.calc, {
surenc: this.actor.computeMalusSurEncombrement(), surenc: this.actor.computeMalusSurEncombrement(),
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr, surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
@ -80,7 +77,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
// toujours avoir une liste d'armes (pour mettre esquive et corps à corps) // toujours avoir une liste d'armes (pour mettre esquive et corps à corps)
const actor = this.actor; const actor = this.actor;
formData.combat = duplicate(formData.armes); formData.combat = foundry.utils.duplicate(formData.armes);
RdDItemArme.computeNiveauArmes(formData.combat, formData.competences); RdDItemArme.computeNiveauArmes(formData.combat, formData.competences);
formData.combat.push(RdDItemArme.mainsNues(actor)); formData.combat.push(RdDItemArme.mainsNues(actor));
formData.combat.push(RdDItemArme.empoignade(actor)); formData.combat.push(RdDItemArme.empoignade(actor));
@ -213,7 +210,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
const key = Number(li.data("key") ?? -1); const key = Number(li.data("key") ?? -1);
await this.actor.deleteExperienceLog(0, key + 1); await this.actor.deleteExperienceLog(0, key + 1);
}); });
// Boutons spéciaux MJs // Boutons spéciaux MJs
this.html.find('.forcer-tmr-aleatoire').click(async event => this.actor.reinsertionAleatoire("Action MJ")) this.html.find('.forcer-tmr-aleatoire').click(async event => this.actor.reinsertionAleatoire("Action MJ"))
this.html.find('.afficher-tmr').click(async event => this.actor.changeTMRVisible()) this.html.find('.afficher-tmr').click(async event => this.actor.changeTMRVisible())
} }
@ -221,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('.ptreve-actuel a').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(duplicate(this._getEventArmeCombat(event)))) this.html.find('.arme-label a').click(async event => this.actor.rollArme(foundry.utils.duplicate(this._getEventArmeCombat(event))))
// Initiative pour l'arme // Initiative pour l'arme
this.html.find('.arme-initiative a').click(async event => { this.html.find('.arme-initiative a').click(async event => {
@ -388,7 +385,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
async _onSplitItem(item, split) { async _onSplitItem(item, split) {
if (split >= 1 && split < item.system.quantite) { if (split >= 1 && split < item.system.quantite) {
await item.diminuerQuantite(split); await item.diminuerQuantite(split);
const splitItem = duplicate(item); const splitItem = foundry.utils.duplicate(item);
splitItem.system.quantite = split; splitItem.system.quantite = split;
await this.actor.createEmbeddedDocuments('Item', [splitItem]) await this.actor.createEmbeddedDocuments('Item', [splitItem])
} }

View File

@ -120,7 +120,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
getActivePoisons() { getActivePoisons() {
return duplicate(this.items.filter(item => item.type == 'poison' && item.system.active)) return foundry.utils.duplicate(this.items.filter(item => item.type == 'poison' && item.system.active))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -143,7 +143,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[TYPES.competence].filter(it => it.system.categorie == 'draconic') }
getBestDraconic() { return 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),
super.getDraconicOuPossession()] super.getDraconicOuPossession()]
@ -347,7 +347,7 @@ export class RdDActor extends RdDBaseActorSang {
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, TYPES.blessure).sort(Misc.ascending(it => it.system.gravite))
await Promise.all(blessures.map(b => b.recuperationBlessure({ await Promise.all(blessures.map(async b => b.recuperationBlessure({
actor: this, actor: this,
timestamp, timestamp,
message, message,
@ -429,7 +429,7 @@ export class RdDActor extends RdDBaseActorSang {
let jetsReve = []; let jetsReve = [];
let dormi = await this.dormirDesHeures(jetsReve, message, heures, options); let dormi = await this.dormirDesHeures(jetsReve, message, heures, options);
if (jetsReve.length > 0) { if (jetsReve.length > 0) {
message.content += `Vous récupérez ${jetsReve.map(it => it < 0 ? '(dragon)' : it).reduce(Misc.joining("+"))} Points de rêve. `; message.content += `Vous récupérez ${jetsReve.map(it => it < 0 ? '0 (réveil)' : it).reduce(Misc.joining("+"))} Points de rêve. `;
} }
if (dormi.etat == 'eveil') { if (dormi.etat == 'eveil') {
await this.reveilReveDeDragon(message, dormi.heures); await this.reveilReveDeDragon(message, dormi.heures);
@ -450,7 +450,6 @@ export class RdDActor extends RdDBaseActorSang {
} }
async reveilReveDeDragon(message, heures) { async reveilReveDeDragon(message, heures) {
message.content += 'Vous êtes réveillé par un Rêve de Dragon.';
const restant = Math.max(this.system.sommeil?.heures - heures, 0) const restant = Math.max(this.system.sommeil?.heures - heures, 0)
if (restant > 0) { if (restant > 0) {
await this.update({ 'system.sommeil': { heures: restant } }); await this.update({ 'system.sommeil': { heures: restant } });
@ -691,7 +690,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
let carac = this.findCaracByName(caracName); let carac = this.findCaracByName(caracName);
if (carac) { if (carac) {
carac = duplicate(carac); carac = foundry.utils.duplicate(carac);
const fromXp = Number(carac.xp); const fromXp = Number(carac.xp);
const fromValue = Number(carac.value); const fromValue = Number(carac.value);
let toXp = fromXp; let toXp = fromXp;
@ -827,7 +826,7 @@ export class RdDActor extends RdDBaseActorSang {
async deleteExperienceLog(from, count) { async deleteExperienceLog(from, count) {
if (from >= 0 && count > 0) { if (from >= 0 && count > 0) {
let expLog = duplicate(this.system.experiencelog); let expLog = foundry.utils.duplicate(this.system.experiencelog);
expLog.splice(from, count); expLog.splice(from, count);
await this.update({ [`system.experiencelog`]: expLog }); await this.update({ [`system.experiencelog`]: expLog });
} }
@ -903,7 +902,7 @@ export class RdDActor extends RdDBaseActorSang {
async ajouterRefoulement(value = 1, refouler) { async ajouterRefoulement(value = 1, refouler) {
let refoulement = this.system.reve.refoulement.value + value; let refoulement = this.system.reve.refoulement.value + value;
const roll = new Roll("1d20"); const roll = new Roll("1d20");
await roll.evaluate({ async: true }); await roll.evaluate();
await roll.toMessage({ flavor: `${this.name} refoule ${refouler} pour ${value} points de refoulement (total: ${refoulement})` }); await roll.toMessage({ flavor: `${this.name} refoule ${refouler} pour ${value} points de refoulement (total: ${refoulement})` });
if (roll.total <= refoulement) { if (roll.total <= refoulement) {
refoulement = 0; refoulement = 0;
@ -992,25 +991,31 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
buildTMRInnaccessible() { buildTMRInnaccessible() {
const tmrInnaccessibles = this.filterItems(it => Draconique.isCaseTMR(it) && return this.items.filter(it => it.type == TYPES.casetmr).filter(it => EffetsDraconiques.isInnaccessible(it)).map(it => it.system.coord)
EffetsDraconiques.isInnaccessible(it));
return tmrInnaccessibles.map(it => it.system.coord);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getTMRRencontres() { getRencontresTMR() {
return this.itemTypes['rencontre']; return this.itemTypes[TYPES.rencontre];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async deleteTMRRencontreAtPosition() { async deleteRencontreTMRAtPosition() {
const demiReve = this.getDemiReve() const rencontreIds = this.itemTypes[TYPES.rencontre].filter(this.filterRencontreTMRDemiReve()).map(it => it.id)
let rencontreIds = this.items.filter(it => it.type == 'rencontre' && it.system.coord == demiReve).map(it => it.id);
if (rencontreIds.length > 0) { if (rencontreIds.length > 0) {
await this.deleteEmbeddedDocuments('Item', rencontreIds); await this.deleteEmbeddedDocuments('Item', rencontreIds)
} }
} }
getRencontreTMREnAttente() {
return this.itemTypes[TYPES.rencontre].find(this.filterRencontreTMRDemiReve())
}
filterRencontreTMRDemiReve() {
const position = this.getDemiReve()
return it => it.system.coord == position
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async addTMRRencontre(currentRencontre) { async addTMRRencontre(currentRencontre) {
const toCreate = currentRencontre.toObject(); const toCreate = currentRencontre.toObject();
@ -1141,7 +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
} }
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);
@ -1312,7 +1317,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async saouler(forceAlcool, alcool = undefined) { async saouler(forceAlcool, alcool = undefined) {
let ethylisme = duplicate(this.system.compteurs.ethylisme); let ethylisme = foundry.utils.duplicate(this.system.compteurs.ethylisme);
const etat = this.getEtatGeneral({ ethylisme: true }); const etat = this.getEtatGeneral({ ethylisme: true });
const nbDoses = Number(this.system.compteurs.ethylisme.nb_doses || 0); const nbDoses = Number(this.system.compteurs.ethylisme.nb_doses || 0);
@ -1333,7 +1338,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
await RdDResolutionTable.rollData(ethylismeData.jetVie); await RdDResolutionTable.rollData(ethylismeData.jetVie);
this._appliquerExperienceRollData(ethylismeData.jetVie); this._gererExperience(ethylismeData.jetVie);
RollDataAjustements.calcul(ethylismeData.jetVie, this); RollDataAjustements.calcul(ethylismeData.jetVie, this);
if (ethylismeData.jetVie.rolled.isSuccess) { if (ethylismeData.jetVie.rolled.isSuccess) {
ethylisme.nb_doses++; ethylisme.nb_doses++;
@ -1365,7 +1370,7 @@ export class RdDActor extends RdDBaseActorSang {
finalLevel: Number(ethylisme.value) + Number(this.system.compteurs.moral.value) finalLevel: Number(ethylisme.value) + Number(this.system.compteurs.moral.value)
} }
await RdDResolutionTable.rollData(ethylismeData.jetVolonte); await RdDResolutionTable.rollData(ethylismeData.jetVolonte);
this._appliquerExperienceRollData(ethylismeData.jetVolonte); this._gererExperience(ethylismeData.jetVolonte);
RollDataAjustements.calcul(ethylismeData.jetVolonte, this); RollDataAjustements.calcul(ethylismeData.jetVolonte, this);
} }
} }
@ -1489,7 +1494,7 @@ export class RdDActor extends RdDBaseActorSang {
const niveauSuivant = Number(carac.value) + 1; const niveauSuivant = Number(carac.value) + 1;
let xpNeeded = RdDCarac.getCaracNextXp(niveauSuivant); let xpNeeded = RdDCarac.getCaracNextXp(niveauSuivant);
if (carac.xp >= xpNeeded) { if (carac.xp >= xpNeeded) {
carac = duplicate(carac); carac = foundry.utils.duplicate(carac);
carac.value = niveauSuivant; carac.value = niveauSuivant;
let checkXp = { let checkXp = {
@ -1519,7 +1524,7 @@ export class RdDActor extends RdDBaseActorSang {
if (compData && newXP > 0) { if (compData && newXP > 0) {
let xpNeeded = RdDItemCompetence.getCompetenceNextXp(compData.system.niveau + 1); let xpNeeded = RdDItemCompetence.getCompetenceNextXp(compData.system.niveau + 1);
if (newXP >= xpNeeded) { if (newXP >= xpNeeded) {
let newCompData = duplicate(compData); let newCompData = foundry.utils.duplicate(compData);
newCompData.system.niveau += 1; newCompData.system.niveau += 1;
newCompData.system.xp = newXP; newCompData.system.xp = newXP;
let checkXp = { let checkXp = {
@ -1543,13 +1548,16 @@ 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) {
const content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-gain-xp.html`, { const content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-gain-xp.html`, {
actor: this, actor: this,
xpData xpData
}); })
if (hideChatMessage) { if (hideChatMessage) {
ChatUtility.blindMessageToGM({ content: content }); ChatUtility.blindMessageToGM({ content: content });
} }
@ -1625,14 +1633,14 @@ export class RdDActor extends RdDBaseActorSang {
return; return;
} }
// Duplication car les pts de reve sont modifiés dans le sort // Duplication car les pts de reve sont modifiés dans le sort
let sorts = duplicate(this.$filterSortList(this.itemTypes['sort'], coord)); let sorts = foundry.utils.duplicate(this.$filterSortList(this.itemTypes['sort'], coord));
if (sorts.length == 0) { if (sorts.length == 0) {
ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`); ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`);
return; return;
} }
const draconicList = this.computeDraconicAndSortIndex(sorts); const draconicList = this.computeDraconicAndSortIndex(sorts);
const reve = duplicate(this.system.carac.reve); const reve = foundry.utils.duplicate(this.system.carac.reve);
const dialog = await this.openRollDialog({ const dialog = await this.openRollDialog({
name: 'lancer-un-sort', name: 'lancer-un-sort',
@ -1779,13 +1787,13 @@ export class RdDActor extends RdDBaseActorSang {
}; };
RollDataAjustements.calcul(rollData, this); RollDataAjustements.calcul(rollData, this);
await RdDResolutionTable.rollData(rollData); await RdDResolutionTable.rollData(rollData);
this._appliquerExperienceRollData(rollData); this._gererExperience(rollData);
await RdDResolutionTable.displayRollData(rollData, this) await RdDResolutionTable.displayRollData(rollData, this)
return rollData.rolled; return rollData.rolled;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_appliquerExperienceRollData(rollData) { _gererExperience(rollData) {
const callback = this.createCallbackExperience(); const callback = this.createCallbackExperience();
if (callback.condition(rollData)) { if (callback.condition(rollData)) {
callback.action(rollData); callback.action(rollData);
@ -1873,7 +1881,7 @@ export class RdDActor extends RdDBaseActorSang {
diffConditions: 0, diffConditions: 0,
use: { libre: false, conditions: true }, use: { libre: false, conditions: true },
carac: { carac: {
[tacheData.system.carac]: duplicate(this.system.carac[tacheData.system.carac]) [tacheData.system.carac]: foundry.utils.duplicate(this.system.carac[tacheData.system.carac])
} }
}, },
callbackAction: r => this._tacheResult(r, options) callbackAction: r => this._tacheResult(r, options)
@ -1884,7 +1892,7 @@ export class RdDActor extends RdDBaseActorSang {
async _tacheResult(rollData, options) { async _tacheResult(rollData, options) {
// Mise à jour de la tache // Mise à jour de la tache
rollData.appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue"); rollData.appliquerFatigue = ReglesOptionnelles.isUsing("appliquer-fatigue");
rollData.tache = duplicate(rollData.tache); rollData.tache = foundry.utils.duplicate(rollData.tache);
rollData.tache.system.points_de_tache_courant += rollData.rolled.ptTache; rollData.tache.system.points_de_tache_courant += rollData.rolled.ptTache;
if (rollData.rolled.isETotal) { if (rollData.rolled.isETotal) {
rollData.tache.system.difficulte--; rollData.tache.system.difficulte--;
@ -1912,17 +1920,17 @@ export class RdDActor extends RdDBaseActorSang {
{ {
oeuvre: oeuvre, oeuvre: oeuvre,
art: oeuvre.type, art: oeuvre.type,
competence: duplicate(this.getCompetence(artData.compName ?? oeuvre.system.competence ?? artData.art)), competence: foundry.utils.duplicate(this.getCompetence(artData.compName ?? oeuvre.system.competence ?? artData.art)),
diffLibre: - oeuvre.system.niveau, diffLibre: - oeuvre.system.niveau,
diffConditions: 0, diffConditions: 0,
use: { libre: false, conditions: true, surenc: false }, use: { libre: false, conditions: true, surenc: false },
selectedCarac: duplicate(this.system.carac[selected]) selectedCarac: foundry.utils.duplicate(this.system.carac[selected])
}, },
{ overwrite: false }); { overwrite: false });
artData.competence.system.defaut_carac = selected; artData.competence.system.defaut_carac = selected;
if (!artData.forceCarac) { if (!artData.forceCarac) {
artData.forceCarac = {}; artData.forceCarac = {};
artData.forceCarac[selected] = duplicate(this.system.carac[selected]); artData.forceCarac[selected] = foundry.utils.duplicate(this.system.carac[selected]);
} }
await this.openRollDialog({ await this.openRollDialog({
@ -1946,19 +1954,19 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollChant(id) { async rollChant(id) {
const artData = { art: 'chant', verbe: 'Chanter' }; const artData = { art: 'chant', verbe: 'Chanter' };
const oeuvre = duplicate(this.getChant(id)); const oeuvre = foundry.utils.duplicate(this.getChant(id));
await this._rollArt(artData, "ouie", oeuvre); await this._rollArt(artData, "ouie", oeuvre);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollDanse(id) { async rollDanse(id) {
const artData = { art: 'danse', verbe: 'Danser', forceCarac: {} }; const artData = { art: 'danse', verbe: 'Danser', forceCarac: {} };
const oeuvre = duplicate(this.findItemLike(id, artData.art)); const oeuvre = foundry.utils.duplicate(this.findItemLike(id, artData.art));
if (oeuvre.system.agilite) { if (oeuvre.system.agilite) {
artData.forceCarac['agilite'] = duplicate(this.system.carac.agilite); artData.forceCarac['agilite'] = foundry.utils.duplicate(this.system.carac.agilite);
} }
if (oeuvre.system.apparence) { if (oeuvre.system.apparence) {
artData.forceCarac['apparence'] = duplicate(this.system.carac.apparence); artData.forceCarac['apparence'] = foundry.utils.duplicate(this.system.carac.apparence);
} }
const selectedCarac = this._getCaracDanse(oeuvre); const selectedCarac = this._getCaracDanse(oeuvre);
await this._rollArt(artData, selectedCarac, oeuvre); await this._rollArt(artData, selectedCarac, oeuvre);
@ -2061,7 +2069,7 @@ export class RdDActor extends RdDBaseActorSang {
const artData = { const artData = {
art: 'jeu', verbe: 'Jeu', art: 'jeu', verbe: 'Jeu',
use: { libre: true, conditions: true, }, use: { libre: true, conditions: true, },
competence: duplicate(this.getCompetence('jeu')), competence: foundry.utils.duplicate(this.getCompetence('jeu')),
forceCarac: {} forceCarac: {}
}; };
listCarac.forEach(c => artData.forceCarac[c] = this.system.carac[c]); listCarac.forEach(c => artData.forceCarac[c] = this.system.carac[c]);
@ -2072,14 +2080,14 @@ export class RdDActor extends RdDBaseActorSang {
async rollOeuvre(id) { async rollOeuvre(id) {
const artData = { art: 'oeuvre', verbe: 'Interpréter' } const artData = { art: 'oeuvre', verbe: 'Interpréter' }
const oeuvre = duplicate(this.findItemLike(id, artData.art)) const oeuvre = foundry.utils.duplicate(this.findItemLike(id, artData.art))
await this._rollArt(artData, oeuvre.system.default_carac, oeuvre) await this._rollArt(artData, oeuvre.system.default_carac, oeuvre)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollMeditation(id) { async rollMeditation(id) {
const meditation = duplicate(this.getMeditation(id)); const meditation = foundry.utils.duplicate(this.getMeditation(id));
const competence = duplicate(this.getCompetence(meditation.system.competence)); const competence = foundry.utils.duplicate(this.getCompetence(meditation.system.competence));
competence.system.defaut_carac = "intellect"; // Meditation = toujours avec intellect competence.system.defaut_carac = "intellect"; // Meditation = toujours avec intellect
let meditationData = { let meditationData = {
competence: competence, competence: competence,
@ -2145,7 +2153,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
let draconicList = this.getDraconicList() let draconicList = this.getDraconicList()
.map(draconic => { .map(draconic => {
let draconicLecture = duplicate(draconic); let draconicLecture = foundry.utils.duplicate(draconic);
draconicLecture.system.defaut_carac = "intellect"; draconicLecture.system.defaut_carac = "intellect";
return draconicLecture; return draconicLecture;
}); });
@ -2269,7 +2277,7 @@ export class RdDActor extends RdDBaseActorSang {
async _appliquerExperience(rolled, caracName, competence, jetResistance) { async _appliquerExperience(rolled, caracName, competence, jetResistance) {
// Pas d'XP // Pas d'XP
if (!rolled.isPart || rolled.finalLevel >= 0) { if (!rolled.isPart || rolled.finalLevel >= 0) {
return undefined; return []
} }
if (this.checkDesirLancinant()) { if (this.checkDesirLancinant()) {
// Cas de désir lancinant, pas d'expérience sur particulière // Cas de désir lancinant, pas d'expérience sur particulière
@ -2277,7 +2285,7 @@ export class RdDActor extends RdDBaseActorSang {
content: `Vous souffrez au moins d'un Désir Lancinant, vous ne pouvez pas gagner d'expérience sur une Particulière tant que le désir n'est pas assouvi`, content: `Vous souffrez au moins d'un Désir Lancinant, vous ne pouvez pas gagner d'expérience sur une Particulière tant que le désir n'est pas assouvi`,
whisper: ChatMessage.getWhisperRecipients(this.name) whisper: ChatMessage.getWhisperRecipients(this.name)
}); });
return undefined; return []
} }
let xp = Math.abs(rolled.finalLevel); let xp = Math.abs(rolled.finalLevel);
@ -2314,7 +2322,7 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _xpCarac(xpData) { async _xpCarac(xpData) {
if (xpData.xpCarac > 0) { if (xpData.xpCarac > 0) {
const carac = duplicate(this.system.carac) const carac = foundry.utils.duplicate(this.system.carac)
const code = RdDBaseActor._findCaracNode(carac, xpData.caracName) const code = RdDBaseActor._findCaracNode(carac, xpData.caracName)
const selectedCarac = carac[code] const selectedCarac = carac[code]
if (this.isCaracMax(code)) { if (this.isCaracMax(code)) {
@ -2338,7 +2346,7 @@ export class RdDActor extends RdDBaseActorSang {
async _xpCaracDerivee(xpData) { async _xpCaracDerivee(xpData) {
const caracs = RdDActor._getComposantsCaracDerivee(xpData.caracName) const caracs = RdDActor._getComposantsCaracDerivee(xpData.caracName)
.map(c => foundry.utils.mergeObject(this.system.carac[c], { isMax: this.isCaracMax(c) })) .map(c => foundry.utils.mergeObject(this.system.carac[c], { isMax: this.isCaracMax(c) }, { inplace: false }))
switch (caracs.filter(it => !it.isMax).length) { switch (caracs.filter(it => !it.isMax).length) {
case 0: case 0:
xpData.caracRepartitionManuelle = true; xpData.caracRepartitionManuelle = true;
@ -2354,6 +2362,8 @@ export class RdDActor extends RdDBaseActorSang {
static _getComposantsCaracDerivee(caracName) { static _getComposantsCaracDerivee(caracName) {
switch (Grammar.toLowerCaseNoAccent(caracName)) { switch (Grammar.toLowerCaseNoAccent(caracName)) {
case 'reve-actuel': case 'reve actuel': return ['reve']
case 'chance-actuelle': case 'chance actuelle': return ['chance']
case 'vie': return ['constitution'] case 'vie': return ['constitution']
case 'tir': return ['vue', 'dexterite'] case 'tir': return ['vue', 'dexterite']
case 'lancer': return ['force', 'dexterite', 'vue'] case 'lancer': return ['force', 'dexterite', 'vue']
@ -2365,26 +2375,25 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async resetNombresAstraux() { async deleteNombresAstraux() {
const deletions = this.itemTypes['nombreastral'].map(it => it._id); const deletions = this.itemTypes['nombreastral'].map(it => it._id);
await this.deleteEmbeddedDocuments("Item", deletions); await this.deleteEmbeddedDocuments("Item", deletions);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async ajouteNombreAstral(callData) { async ajouteNombreAstral(date, nbAstral, isValid) {
const indexDate = Number.parseInt(callData.date); const indexDate = Number.parseInt(date);
// Ajout du nombre astral // Ajout du nombre astral
const item = { const item = {
name: "Nombre Astral", type: "nombreastral", system: name: "Nombre Astral", type: "nombreastral", system:
{ {
value: callData.nbAstral, value: nbAstral,
istrue: callData.isvalid, istrue: isValid,
jourindex: indexDate, jourindex: indexDate,
jourlabel: RdDTimestamp.formatIndexDate(indexDate) jourlabel: RdDTimestamp.formatIndexDate(indexDate)
} }
}; };
await this.createEmbeddedDocuments("Item", [item]); await this.createEmbeddedDocuments("Item", [item]);
game.system.rdd.calendrier.notifyChangeNombresAstraux();
} }
async supprimerAnciensNombresAstraux() { async supprimerAnciensNombresAstraux() {
@ -2425,22 +2434,29 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async displayTMR(mode = "normal") { async displayTMR(mode = "normal") {
if (this.tmrApp) { if (this.tmrApp) {
ui.notifications.warn("Vous êtes déja dans les TMR...."); ui.notifications.warn("Vous êtes déja dans les TMR....")
this.tmrApp.forceTMRDisplay(); this.tmrApp.forceTMRDisplay()
return return
} }
if (mode != 'visu' && this.getEffect(STATUSES.StatusDemiReve)) { if (mode != 'visu' && this.getEffect(STATUSES.StatusDemiReve)) {
ui.notifications.warn("Le joueur ou le MJ est déja dans les Terres Médianes avec ce personnage ! Visualisation uniquement"); ui.notifications.warn("Les personnage est déjà dans les Terres Médianes, elles s'affichent en visualisation")
mode = "visu"; // bascule le mode en visu automatiquement mode = "visu"; // bascule le mode en visu automatiquement
} }
RdDConfirm.confirmer({ if (mode == 'visu') {
bypass: mode == 'visu', await this._doDisplayTMR(mode)
settingConfirmer: "confirmation-tmr", }
content: `<p>Voulez vous monter dans les TMR en mode ${mode}?</p>`, else {
title: 'Confirmer la montée dans les TMR', const rencontre = this.getRencontreTMREnAttente();
buttonLabel: 'Monter dans les TMR', const settingConfirmer = rencontre ? "confirmation-tmr-rencontre" : "confirmation-tmr";
onAction: async () => await this._doDisplayTMR(mode) const messageRencontre = rencontre ? `<p>Vous devrez combattre ${rencontre.system.genre == 'f' ? 'la' : 'le'} ${rencontre.name} de ${rencontre.system.force} points de Rêve</p>` : '';
}); RdDConfirm.confirmer({
settingConfirmer: settingConfirmer,
content: `<p>Voulez vous monter dans les TMR en mode ${mode}?</p>` + messageRencontre,
title: 'Confirmer la montée dans les TMR',
buttonLabel: 'Monter dans les TMR',
onAction: async () => await this._doDisplayTMR(mode)
})
}
} }
async _doDisplayTMR(mode) { async _doDisplayTMR(mode) {
@ -2612,13 +2628,13 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async resetItemUse() { async resetItemUse() {
await this.unsetFlag(SYSTEM_RDD, 'itemUse');
await this.setFlag(SYSTEM_RDD, 'itemUse', {}); await this.setFlag(SYSTEM_RDD, 'itemUse', {});
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async incDecItemUse(itemId, inc = 1) { async incDecItemUse(itemId, inc = 1) {
let itemUse = duplicate(this.getFlag(SYSTEM_RDD, 'itemUse') ?? {}); const currentItemUse = this.getFlag(SYSTEM_RDD, 'itemUse');
let itemUse = currentItemUse ? foundry.utils.duplicate(currentItemUse) : {};
itemUse[itemId] = (itemUse[itemId] ?? 0) + inc; itemUse[itemId] = (itemUse[itemId] ?? 0) + inc;
await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse); await this.setFlag(SYSTEM_RDD, 'itemUse', itemUse);
console.log("ITEM USE INC", inc, itemUse); console.log("ITEM USE INC", inc, itemUse);
@ -2712,7 +2728,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
async setPointsCoeur(subActorId, coeurs, options = { immediat: false }) { async setPointsCoeur(subActorId, coeurs, options = { immediat: false }) {
const newSuivants = duplicate(this.system.subacteurs.suivants) const newSuivants = foundry.utils.duplicate(this.system.subacteurs.suivants)
const amoureux = newSuivants.find(it => it.id == subActorId); const amoureux = newSuivants.find(it => it.id == subActorId);
if (amoureux) { if (amoureux) {
amoureux[options.immediat ? 'coeur' : 'prochainCoeur'] = coeurs amoureux[options.immediat ? 'coeur' : 'prochainCoeur'] = coeurs
@ -2969,9 +2985,6 @@ export class RdDActor extends RdDBaseActorSang {
} }
} }
/* -------------------------------------------- */
isEffectAllowed(effectId) { return true }
/* -------------------------------------------- */ /* -------------------------------------------- */
async onPreUpdateItem(item, change, options, id) { async onPreUpdateItem(item, change, options, id) {
if (item.isCompetencePersonnage() && item.system.defaut_carac && item.system.xp) { if (item.isCompetencePersonnage() && item.system.defaut_carac && item.system.xp) {
@ -3066,7 +3079,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: 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.rollTotal("1dh", { rollMode: "selfroll", showDice: SHOW_DICE })).key,
age: 18, age: 18,
biographie: '', biographie: '',

View File

@ -180,7 +180,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
isEffectAllowed(effectId) { return true } isEffectAllowed(effectId) { return false }
getEffects(filter = e => true) { getEffects(filter = e => true) {
return this.getEmbeddedCollection("ActiveEffect").filter(filter); return this.getEmbeddedCollection("ActiveEffect").filter(filter);
@ -286,12 +286,12 @@ export class RdDBaseActorReve extends RdDBaseActor {
getCarac() { getCarac() {
// TODO: le niveau d'une entité de cauchemar devrait être exclu... // TODO: le niveau d'une entité de cauchemar devrait être exclu...
const carac = foundry.utils.mergeObject(duplicate(this.system.carac), return foundry.utils.mergeObject(this.system.carac,
{ {
'reve-actuel': this.getCaracReveActuel(), 'reve-actuel': this.getCaracReveActuel(),
'chance-actuelle': this.getCaracChanceActuelle() 'chance-actuelle': this.getCaracChanceActuelle()
}); },
return carac; { inplace: false })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -318,10 +318,10 @@ 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 == TYPES.competencecreature) {
const arme = RdDItemCompetenceCreature.armeCreature(competence) const arme = RdDItemCompetenceCreature.armeCreature(competence)
if (arme && options.tryTarget && Targets.hasTargets()) { if (arme && options.tryTarget && Targets.hasTargets()) {
@ -361,7 +361,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 +375,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
@ -421,36 +421,35 @@ export class RdDBaseActorReve extends RdDBaseActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async encaisser() { await RdDEncaisser.encaisser(this) } async encaisser() { await RdDEncaisser.encaisser(this) }
async encaisserDommagesRemote(rollData, attackerId, show) {
const attacker = game.actors.get(attackerId);
await this.encaisserDommages(rollData, attacker, show)
}
async encaisserDommages(rollData, attacker = undefined, show = undefined) { async encaisserDommages(rollData, attacker = undefined, show = undefined) {
if (attacker && !await attacker.accorder(this, 'avant-encaissement')) { if (attacker && !await attacker.accorder(this, 'avant-encaissement')) {
return; return;
} }
const attackerId = attacker?.id;
if (ReglesOptionnelles.isUsing('validation-encaissement-gr') && !game.user.isGM) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'encaisserDommagesRemote',
args: [rollData, attackerId, show]
});
return;
}
const armure = await this.computeArmure(rollData); const armure = await this.computeArmure(rollData);
if (ReglesOptionnelles.isUsing('validation-encaissement-gr')) { if (ReglesOptionnelles.isUsing('validation-encaissement-gr')){
DialogValidationEncaissement.validerEncaissement(this, rollData, armure, await this.encaisserDommagesValidationGR(rollData, armure, attacker?.id, show);
jet => this.$onEncaissement(jet, show, attacker)); }
}
else { else {
const jet = await RdDUtility.jetEncaissement(rollData, armure, { showDice: SHOW_DICE }); const jet = await RdDUtility.jetEncaissement(rollData, armure, { showDice: SHOW_DICE });
await this.$onEncaissement(jet, show, attacker); await this.$onEncaissement(jet, show, attacker);
} }
} }
async encaisserDommagesValidationGR(rollData, armure, attackerId, show) {
if (!game.user.isGM) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'encaisserDommagesValidationGR',
args: [rollData, armure, attackerId, show]
});
} else {
const attacker = game.actors.get(attackerId);
DialogValidationEncaissement.validerEncaissement(this, rollData, armure,
jet => this.$onEncaissement(jet, show, attacker));
}
}
async $onEncaissement(jet, show, attacker) { async $onEncaissement(jet, show, attacker) {
await this.onAppliquerJetEncaissement(jet, attacker); await this.onAppliquerJetEncaissement(jet, attacker);
await this.$afficherEncaissement(jet, show); await this.$afficherEncaissement(jet, show);
@ -471,7 +470,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
}); });
if (!encaissement.hasPlayerOwner && encaissement.endurance != 0) { if (!encaissement.hasPlayerOwner && encaissement.endurance != 0) {
encaissement = duplicate(encaissement); encaissement = foundry.utils.duplicate(encaissement);
encaissement.isGM = true; encaissement.isGM = true;
ChatMessage.create({ ChatMessage.create({
whisper: ChatMessage.getWhisperRecipients("GM"), whisper: ChatMessage.getWhisperRecipients("GM"),
@ -509,8 +508,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

@ -89,7 +89,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
/* -------------------------------------------- */ /* -------------------------------------------- */
async onAppliquerJetEncaissement(encaissement, attacker) { async onAppliquerJetEncaissement(encaissement, attacker) {
const santeOrig = duplicate(this.system.sante); const santeOrig = foundry.utils.duplicate(this.system.sante);
const blessure = await this.ajouterBlessure(encaissement, attacker); // Will update the result table const blessure = await this.ajouterBlessure(encaissement, attacker); // Will update the result table
const perteVie = await this.santeIncDec("vie", -encaissement.vie); const perteVie = await this.santeIncDec("vie", -encaissement.vie);
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, blessure?.isCritique()); const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, blessure?.isCritique());
@ -108,7 +108,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) { if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
return; return;
} }
const sante = duplicate(this.system.sante) const sante = foundry.utils.duplicate(this.system.sante)
let compteur = sante[name]; let compteur = sante[name];
if (!compteur) { if (!compteur) {
return; return;
@ -269,6 +269,8 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return this.getEffect(STATUSES.StatusStunned); return this.getEffect(STATUSES.StatusStunned);
} }
isEffectAllowed(effectId) { return true }
/* -------------------------------------------- */ /* -------------------------------------------- */
async computeEtatGeneral() { this.system.compteurs.etat.value = this.malusVie() + this.malusFatigue() + this.malusEthylisme() } async computeEtatGeneral() { this.system.compteurs.etat.value = this.malusVie() + this.malusFatigue() + this.malusEthylisme() }
getEtatGeneral(options = { ethylisme: false }) { return this.system.compteurs.etat.value } getEtatGeneral(options = { ethylisme: false }) { return this.system.compteurs.etat.value }

View File

@ -20,7 +20,7 @@ export class RdDBaseActorSheet extends ActorSheet {
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }], tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }], dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
vueDetaillee: false vueDetaillee: false
}); }, { inplace: false })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -37,7 +37,8 @@ export class RdDBaseActorSheet extends ActorSheet {
system: this.actor.system, system: this.actor.system,
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
} }
RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes); RdDBaseActorSheet.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
@ -312,7 +313,7 @@ export class RdDBaseActorSheet extends ActorSheet {
async _onSplitItem(item, split) { async _onSplitItem(item, split) {
if (split >= 1 && split < item.system.quantite) { if (split >= 1 && split < item.system.quantite) {
await item.diminuerQuantite(split); await item.diminuerQuantite(split);
const splitItem = duplicate(item); const splitItem = foundry.utils.duplicate(item);
splitItem.system.quantite = split; splitItem.system.quantite = split;
await this.actor.createEmbeddedDocuments('Item', [splitItem]) await this.actor.createEmbeddedDocuments('Item', [splitItem])
} }

View File

@ -1,3 +1,4 @@
import { ChatVente } from "../achat-vente/chat-vente.js";
import { ChatUtility } from "../chat-utility.js"; 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";
@ -8,7 +9,6 @@ import { RdDAudio } from "../rdd-audio.js";
import { RdDConfirm } from "../rdd-confirm.js"; import { RdDConfirm } from "../rdd-confirm.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 { APP_ASTROLOGIE_REFRESH } from "../sommeil/app-astrologie.js";
export class RdDBaseActor extends Actor { export class RdDBaseActor extends Actor {
@ -16,7 +16,7 @@ export class RdDBaseActor extends Actor {
return Object.entries(carac) return Object.entries(carac)
.filter(it => Grammar.equalsInsensitive(it[1].label, name)) .filter(it => Grammar.equalsInsensitive(it[1].label, name))
.map(it => it[0]) .map(it => it[0])
.find(it => it); .find(it => it)
} }
static $findCaracByName(carac, name) { static $findCaracByName(carac, name) {
const caracList = Object.entries(carac); const caracList = Object.entries(carac);
@ -32,23 +32,16 @@ export class RdDBaseActor extends Actor {
} }
static init() { static init() {
Hooks.on("preUpdateItem", (item, change, options, id) => RdDBaseActor.getParentActor(item)?.onPreUpdateItem(item, change, options, id)); Hooks.on("preUpdateItem", (item, change, options, id) => Misc.documentIfResponsible(item.parent)?.onPreUpdateItem(item, change, options, id))
Hooks.on("createItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onCreateItem(item, options, id)); Hooks.on("createItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onCreateItem(item, options, id))
Hooks.on("deleteItem", (item, options, id) => RdDBaseActor.getParentActor(item)?.onDeleteItem(item, options, id)); Hooks.on("deleteItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onDeleteItem(item, options, id))
Hooks.on("updateActor", (actor, change, options, actorId) => actor.onUpdateActor(change, options, actorId)); Hooks.on("updateActor", (actor, change, options, actorId) => Misc.documentIfResponsible(actor)?.onUpdateActor(change, options, actorId))
} }
static onSocketMessage(sockmsg) { static onSocketMessage(sockmsg) {
switch (sockmsg.msg) { switch (sockmsg.msg) {
case "msg_remote_actor_call": case "msg_remote_actor_call":
return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId); return RdDBaseActor.onRemoteActorCall(sockmsg.data, sockmsg.userId);
case "msg_reset_nombre_astral":
game.user.character.resetNombresAstraux();
game.system.rdd.calendrier.notifyChangeNombresAstraux();
return;
case "msg_refresh_nombre_astral":
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
return;
} }
} }
@ -89,10 +82,6 @@ export class RdDBaseActor extends Actor {
static extractActorMin = (actor) => { return { id: actor?.id, type: actor?.type, name: actor?.name, img: actor?.img }; }; static extractActorMin = (actor) => { return { id: actor?.id, type: actor?.type, name: actor?.name, img: actor?.img }; };
static getParentActor(document) {
return document?.parent instanceof Actor ? document.parent : undefined
}
/** /**
* Cette methode surcharge Actor.create() pour ajouter si besoin des Items par défaut: * Cette methode surcharge Actor.create() pour ajouter si besoin des Items par défaut:
* compétences et monnaies. * compétences et monnaies.
@ -132,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);
} }
@ -242,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)
}
} }
} }
@ -368,16 +360,13 @@ export class RdDBaseActor extends Actor {
ChatUtility.notifyUser(achat.userId, 'warn', `Vous n'avez pas assez d'argent pour payer ${Math.ceil(cout / 100)} sols !`); ChatUtility.notifyUser(achat.userId, 'warn', `Vous n'avez pas assez d'argent pour payer ${Math.ceil(cout / 100)} sols !`);
return; return;
} }
await this.decrementerVente(vendeur, itemVendu, quantite, cout); await vendeur?.vendre(itemVendu, quantite, cout);
if (acheteur) { await acheteur?.acheter(itemVendu, quantite, cout, achat)
await acheteur.depenserSols(cout);
const createdItemId = await acheteur.creerQuantiteItem(itemVendu, quantite);
await acheteur.consommerNourritureAchetee(achat, achat.vente, createdItemId);
}
if (cout > 0) { if (cout > 0) {
RdDAudio.PlayContextAudio("argent"); RdDAudio.PlayContextAudio("argent");
} }
const chatAchatItem = duplicate(achat.vente); const chatAchatItem = foundry.utils.duplicate(achat.vente);
chatAchatItem.quantiteTotal = quantite; chatAchatItem.quantiteTotal = quantite;
ChatMessage.create({ ChatMessage.create({
user: achat.userId, user: achat.userId,
@ -387,24 +376,26 @@ export class RdDBaseActor extends Actor {
}); });
if (!achat.vente.quantiteIllimite) { if (!achat.vente.quantiteIllimite) {
if (achat.vente.quantiteNbLots <= achat.choix.nombreLots) { if (achat.vente.nbLots <= achat.choix.nombreLots) {
ChatUtility.removeChatMessageId(achat.chatMessageIdVente); ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
} }
else if (achat.chatMessageIdVente) { else if (achat.chatMessageIdVente) {
achat.vente.properties = itemVendu.getProprietes(); await ChatVente.diminuerQuantiteAchatVente(achat.chatMessageIdVente, achat.choix.nombreLots)
achat.vente.quantiteNbLots -= achat.choix.nombreLots;
achat.vente.jsondata = JSON.stringify(achat.vente.item);
const messageVente = game.messages.get(achat.chatMessageIdVente);
messageVente.update({ content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', achat.vente) });
messageVente.render(true);
} }
} }
} }
async decrementerVente(vendeur, itemVendu, quantite, cout) { async vendre(item, quantite, cout) {
if (vendeur) { await this.ajouterSols(cout);
await vendeur.ajouterSols(cout); await this.decrementerQuantiteItem(item, quantite);
await vendeur.decrementerQuantiteItem(itemVendu, quantite); }
async acheter(item, quantite, cout, achat) {
await this.depenserSols(cout)
const createdItemId = await this.creerQuantiteItem(item, quantite)
if (achat.choix.consommer && item.type == 'nourritureboisson' && createdItemId != undefined) {
achat.choix.doses = achat.choix.nombreLots;
await this.consommerNourritureboisson(createdItemId, achat.choix, achat.vente.actingUserId);
} }
} }
@ -417,31 +408,28 @@ export class RdDBaseActor extends Actor {
return disponible == undefined || disponible >= quantiteDemande; return disponible == undefined || disponible >= quantiteDemande;
} }
async consommerNourritureAchetee(achat, vente, createdItemId) { async consommerNourritureboisson(itemId, choix, userId) { }
if (achat.choix.consommer && vente.item.type == 'nourritureboisson' && createdItemId != undefined) {
achat.choix.doses = achat.choix.nombreLots;
await this.consommerNourritureboisson(createdItemId, achat.choix, vente.actingUserId);
}
}
async decrementerQuantiteItem(item, quantite, options = { supprimerSiZero: true }) { async decrementerQuantiteItem(item, quantite, options = { supprimerSiZero: true }) {
if (item.isService()) { if (item.isService()) {
return; return;
} }
const itemId = item.id;
let resteQuantite = (item.system.quantite ?? 1) - quantite; let resteQuantite = (item.system.quantite ?? 1) - quantite;
if (resteQuantite <= 0) { if (resteQuantite <= 0) {
if (options.supprimerSiZero) { if (options.supprimerSiZero) {
await this.deleteEmbeddedDocuments("Item", [item.id]); await this.deleteEmbeddedDocuments("Item", [item.id]);
} }
else { else {
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': 0 }]); await this.updateEmbeddedDocuments("Item", [{ _id: itemId, 'system.quantite': 0 }]);
} }
if (resteQuantite < 0) { if (resteQuantite < 0) {
ui.notifications.warn(`La quantité de ${item.name} était insuffisante, l'objet a donc été supprimé`) ui.notifications.warn(`La quantité de ${item.name} était insuffisante, l'objet a donc été supprimé`)
} }
} }
else if (resteQuantite > 0) { else if (resteQuantite > 0) {
const realItem = this.getItem(item.id)
realItem.update({ 'system.quantite': resteQuantite });
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': resteQuantite }]); await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': resteQuantite }]);
} }
} }
@ -453,7 +441,7 @@ export class RdDBaseActor extends Actor {
type: item.type, type: item.type,
img: item.img, img: item.img,
name: item.name, name: item.name,
system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }) system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }, { inplace: false })
}; };
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem); const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
const items = await this.createEmbeddedDocuments("Item", newItems); const items = await this.createEmbeddedDocuments("Item", newItems);
@ -569,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 })
} }
} }
@ -595,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) {
@ -631,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;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -649,7 +648,7 @@ export class RdDBaseActor extends Actor {
sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list sourceActor.buildSubConteneurObjetList(itemId, itemsList); // Get itemId list
const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id)) const itemsDataToCreate = itemsList.map(it => sourceActor.getItem(it.id))
.map(it => duplicate(it)) .map(it => foundry.utils.duplicate(it))
.map(it => { it.system.contenu = []; return it; }); .map(it => { it.system.contenu = []; return it; });
let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate); let newItems = await this.createEmbeddedDocuments('Item', itemsDataToCreate);

View File

@ -1,4 +1,4 @@
import { DialogItemAchat } from "../dialog-item-achat.js"; import { DialogItemAchat } from "../achat-vente/dialog-item-achat.js";
import { RdDItem } from "../item.js"; import { RdDItem } from "../item.js";
import { RdDUtility } from "../rdd-utility.js"; import { RdDUtility } from "../rdd-utility.js";
import { RdDBaseActorSheet } from "./base-actor-sheet.js"; import { RdDBaseActorSheet } from "./base-actor-sheet.js";
@ -15,7 +15,7 @@ export class RdDCommerceSheet extends RdDBaseActorSheet {
template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor/commerce-actor-sheet.html",
width: 600, height: 720, width: 600, height: 720,
tabs: [] tabs: []
}); }, { inplace: false })
} }
get title() { get title() {
if (this.actor.token && this.actor.token != this.actor.prototypeToken) { if (this.actor.token && this.actor.token != this.actor.prototypeToken) {

View File

@ -25,8 +25,7 @@ export class RdDCommerce extends RdDBaseActor {
} }
await super.depenserSols(cout) await super.depenserSols(cout)
} }
async consommerNourritureboisson(itemId, choix, userId) {
async consommerNourritureAchetee(achat, vente, createdItemId) {
// ne pas consommer pour un commerce // ne pas consommer pour un commerce
} }

View File

@ -12,7 +12,7 @@ export class RdDCreatureSheet extends RdDBaseActorSangSheet {
return foundry.utils.mergeObject(RdDBaseActorSangSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorSangSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-creature-sheet.html",
width: 640, height: 720 width: 640, height: 720
}); }, { inplace: false })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -33,31 +33,4 @@ export class RdDCreature extends RdDBaseActorSang {
} }
} }
isEffectAllowed(effectId) {
return [STATUSES.StatusComma].includes(effectId);
}
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 = 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

@ -9,7 +9,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html",
width: 640, height: 720, width: 640, height: 720,
}); }, { inplace: false })
} }
async getData() { async getData() {
@ -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

@ -67,7 +67,7 @@ export class RdDEntite extends RdDBaseActorReve {
if (this.isNonIncarnee()) { if (this.isNonIncarnee()) {
return return
} }
await RdDEncaisser.encaisser(this) await RdDEncaisser.encaisser(this)
} }
isEffectAllowed(effectId) { isEffectAllowed(effectId) {
@ -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 = 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

@ -9,7 +9,7 @@ export class RdDActorVehiculeSheet extends RdDBaseActorSheet {
return foundry.utils.mergeObject(RdDBaseActorSheet.defaultOptions, { return foundry.utils.mergeObject(RdDBaseActorSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html", template: "systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html",
width: 640, height: 720, width: 640, height: 720,
}); }, { inplace: false })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -1,5 +1,6 @@
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js"; import { SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
import { RdDTimestamp } from "./time/rdd-timestamp.js";
/** /**
@ -131,7 +132,7 @@ export class ChatUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static blindMessageToGM(chatOptions) { static blindMessageToGM(chatOptions) {
let chatGM = duplicate(chatOptions); let chatGM = foundry.utils.duplicate(chatOptions);
chatGM.whisper = ChatUtility.getUsers(user => user.isGM); chatGM.whisper = ChatUtility.getUsers(user => user.isGM);
chatGM.content = "Message aveugle de " + game.user.name + "<br>" + chatOptions.content; chatGM.content = "Message aveugle de " + game.user.name + "<br>" + chatOptions.content;
console.log("blindMessageToGM", chatGM); console.log("blindMessageToGM", chatGM);
@ -148,14 +149,13 @@ export class ChatUtility {
} }
static async setMessageData(chatMessage, key, flag) { static async setMessageData(chatMessage, key, flag) {
if (flag) { if (flag && chatMessage.isAuthor) {
await chatMessage.setFlag(SYSTEM_RDD, key, JSON.stringify(flag)); await chatMessage.setFlag(SYSTEM_RDD, key, flag)
} }
} }
static getMessageData(chatMessage, key) { static getMessageData(chatMessage, key) {
const json = chatMessage.getFlag(SYSTEM_RDD, key); return chatMessage.getFlag(SYSTEM_RDD, key);
return json ? JSON.parse(json) : undefined;
} }
static getChatMessage(event) { static getChatMessage(event) {
@ -163,4 +163,19 @@ export class ChatUtility {
return game.messages.get(chatMessageId); return game.messages.get(chatMessageId);
} }
static async onRenderChatMessage(chatMessage, html, data) {
const rddTimestamp = chatMessage.getFlag(SYSTEM_RDD, 'rdd-timestamp')
if (rddTimestamp) {
const timestamp = new RdDTimestamp(rddTimestamp);
const timestampData = timestamp.toCalendrier();
const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData);
html.find('header.message-header .message-sender').after(dateHeure)
}
}
static async onCreateChatMessage(chatMessage, options, id) {
if (chatMessage.isAuthor) {
await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp());
}
}
} }

View File

@ -69,7 +69,7 @@ export class RdDCoeur {
} }
static async applyCoeurChateauDormant(actor, message) { static async applyCoeurChateauDormant(actor, message) {
const newSuivants = duplicate(actor.system.subacteurs.suivants) const newSuivants = foundry.utils.duplicate(actor.system.subacteurs.suivants)
let count = 0 let count = 0
newSuivants.forEach(async link => { newSuivants.forEach(async link => {
const suivant = game.actors.get(link.id) const suivant = game.actors.get(link.id)
@ -117,8 +117,8 @@ export class RdDCoeur {
} }
ChatUtility.removeChatMessageId(infoCoeur.chatMessageId) ChatUtility.removeChatMessageId(infoCoeur.chatMessageId)
infoCoeur.target.jetTendre = (await (new Roll('1d6').evaluate({ async: true }))).total infoCoeur.target.jetTendre = (await (new Roll('1d6').evaluate())).total
infoCoeur.source.jetTendre = (await (new Roll('1d6').evaluate({ async: true }))).total infoCoeur.source.jetTendre = (await (new Roll('1d6').evaluate())).total
const diff = Math.abs(infoCoeur.source.jetTendre - infoCoeur.target.jetTendre) const diff = Math.abs(infoCoeur.source.jetTendre - infoCoeur.target.jetTendre)
for (let amoureux of [infoCoeur.source, infoCoeur.target]) { for (let amoureux of [infoCoeur.source, infoCoeur.target]) {
const actorAmoureux = game.actors.get(amoureux.actor.id); const actorAmoureux = game.actors.get(amoureux.actor.id);

View File

@ -8,3 +8,46 @@ export const SHOW_DICE = 'show';
export const ENTITE_INCARNE = 'incarne'; export const ENTITE_INCARNE = 'incarne';
export const ENTITE_NONINCARNE = 'nonincarne'; export const ENTITE_NONINCARNE = 'nonincarne';
export const ENTITE_BLURETTE = 'blurette'; export const ENTITE_BLURETTE = 'blurette';
export const RDD_CONFIG = {
niveauEthylisme : [
{value: "1", label: "Aucun"},
{value: "0", label: "Eméché (0)"},
{value: "-1", label: "Gris (-1)"},
{value: "-2", label: "Pinté (-2)"},
{value: "-3", label: "Pas Frais (-3)"},
{value: "-4", label: "Ivre (-4)"},
{value: "-5", label: "Bu (-5)"},
{value: "-6", label: "Complètement fait (-6)"},
{value: "-7", label: "Ivre mort (-7)"}
],
categorieEntite: {
"cauchemar": "Cauchemar",
"reve": "Rêve"
},
typeEntite: {
"incarne": "Incarnée",
"nonincarne": "Non Incarnée",
"blurette": "Blurette"
},
heuresRdD : [
{value : "vaisseau", label: "Vaisseau", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd01.webp"},
{value : "sirene", label: "Sirène", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd02.webp"},
{value : "faucon", label: "Faucon", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd03.webp"},
{value : "couronne", label: "Couronne", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd04.webp"},
{value : "dragon", label: "Dragon", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd05.webp"},
{value : "epees", label: "Epées", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd06.webp"},
{value : "lyre", label: "Lyre", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd07.webp"},
{value : "serpent", label: "Serpent", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd08.webp"},
{value : "poissonacrobate", label: "Poisson Acrobate", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd09.webp"},
{value : "araignee", label: "Araignée", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd10.webp"},
{value : "roseau", label: "Roseau", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd11.webp"},
{value : "chateaudormant", label: "Chateau Dormant", img: "modules/foundryvtt-reve-de-dragon/icons/heures/hd12.webp"}
],
raretes: [
{value: "Commune", label: "Commune"},
{value: "Frequente", label: "Fréquente"},
{value: "Rare", label: "Rare"},
{value: "Rarissime", label: "Rarissime"}
]
}

View File

@ -21,7 +21,7 @@ export class DialogFabriquerPotion extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
static prepareData(actor, item) { static prepareData(actor, item) {
let potionData = duplicate(item) let potionData = foundry.utils.duplicate(item)
potionData.nbBrinsSelect = RdDUtility.buildListOptions( potionData.nbBrinsSelect = RdDUtility.buildListOptions(
DialogFabriquerPotion.nombreBrinsMinimum(item), DialogFabriquerPotion.nombreBrinsMinimum(item),
DialogFabriquerPotion.nombreBrinsOptimal(item)); DialogFabriquerPotion.nombreBrinsOptimal(item));

View File

@ -47,7 +47,7 @@ export class DialogConsommer extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
static prepareData(actor, item) { static prepareData(actor, item) {
let consommerData = { let consommerData = {
item: duplicate(item), item: foundry.utils.duplicate(item),
cuisine: actor.getCompetence('cuisine'), cuisine: actor.getCompetence('cuisine'),
choix: { choix: {
doses: 1, doses: 1,

View File

@ -139,7 +139,7 @@ export class RdDItemArme extends Item {
const uneOuDeuxMains = armeData.system.unemain && armeData.system.deuxmains; const uneOuDeuxMains = armeData.system.unemain && armeData.system.deuxmains;
const containsSlash = !Number.isInteger(armeData.system.dommages) && armeData.system.dommages.includes("/"); const containsSlash = !Number.isInteger(armeData.system.dommages) && armeData.system.dommages.includes("/");
if (containsSlash) { // Sanity check if (containsSlash) { // Sanity check
armeData = duplicate(armeData); armeData = foundry.utils.duplicate(armeData);
const tableauDegats = armeData.system.dommages.split("/"); const tableauDegats = armeData.system.dommages.split("/");
if (aUneMain) if (aUneMain)

View File

@ -199,7 +199,7 @@ export class RdDItemCompetence extends Item {
if (idOrName == undefined || idOrName == "") { if (idOrName == undefined || idOrName == "") {
return RdDItemCompetence.sansCompetence(); return RdDItemCompetence.sansCompetence();
} }
options = foundry.utils.mergeObject(options, { preFilter: it => it.isCompetence(), description: 'compétence' }, { overwrite: false }); options = foundry.utils.mergeObject(options, { preFilter: it => it.isCompetence(), description: 'compétence' }, { overwrite: false, inplace: false });
return RdDItemCompetence.findFirstItem(list, idOrName, options); return RdDItemCompetence.findFirstItem(list, idOrName, options);
} }
@ -257,7 +257,7 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeResumeArchetype(competences) { static computeResumeArchetype(competences) {
const computed = duplicate(limitesArchetypes); const computed = foundry.utils.duplicate(limitesArchetypes);
computed.forEach(it => { it.nombre = 0; it.reste = it.nombreMax; }); computed.forEach(it => { it.nombre = 0; it.reste = it.nombreMax; });
competences.map(it => Math.max(0, it.system.niveau_archetype)) competences.map(it => Math.max(0, it.system.niveau_archetype))

View File

@ -33,8 +33,7 @@ export class RdDItemCompetenceCreature extends Item {
if (categorieAttaque != undefined) { if (categorieAttaque != undefined) {
// si c'est un Item compétence: cloner pour ne pas modifier la compétence // si c'est un Item compétence: cloner pour ne pas modifier la compétence
let arme = item.clone(); let arme = item.clone();
foundry.utils.mergeObject(arme, return foundry.utils.mergeObject(arme, {
{
action: item.isCompetencePossession() ? 'possession' : 'attaque', action: item.isCompetencePossession() ? 'possession' : 'attaque',
system: { system: {
competence: arme.name, competence: arme.name,
@ -48,8 +47,7 @@ export class RdDItemCompetenceCreature extends Item {
force: 0, force: 0,
rapide: true, rapide: true,
} }
}); }, { inplace: false });
return arme;
} }
return undefined; return undefined;
} }

View File

@ -57,7 +57,7 @@ export class Monnaie {
} }
static creerDeniers(fortune) { static creerDeniers(fortune) {
const deniers = duplicate(MONNAIE_ETAIN); const deniers = foundry.utils.duplicate(MONNAIE_ETAIN);
deniers.system.quantite = fortune; deniers.system.quantite = fortune;
return deniers; return deniers;
} }

View File

@ -44,7 +44,7 @@ export class RdDItemSheet extends ItemSheet {
template: RdDItemSheet.defaultTemplate(RdDItemSheet.ITEM_TYPE), template: RdDItemSheet.defaultTemplate(RdDItemSheet.ITEM_TYPE),
width: 550, width: 550,
height: 550 height: 550
}); }, { inplace: false });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -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,7 +99,7 @@ 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 == TYPES.competencecreature) {
formData.isparade = RdDItemCompetenceCreature.isParade(this.item) formData.isparade = RdDItemCompetenceCreature.isParade(this.item)
@ -108,8 +109,8 @@ export class RdDItemSheet extends ItemSheet {
const competences = await SystemCompendiums.getCompetences('personnage'); const competences = await SystemCompendiums.getCompetences('personnage');
formData.categories = this.item.getCategories() formData.categories = this.item.getCategories()
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 = duplicate(game.system.model.Actor.personnage.carac) formData.caracList = foundry.utils.duplicate(game.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = duplicate(game.system.model.Actor.personnage.reve.reve) formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.model.Actor.personnage.reve.reve)
formData.competences = competences; formData.competences = competences;
} }
if (this.item.type == 'arme') { if (this.item.type == 'arme') {
@ -228,7 +229,7 @@ export class RdDItemSheet extends ItemSheet {
}); });
} }
const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: duplicate(timestamp) }) const updateItemTimestamp = (path, timestamp) => this.item.update({ [path]: foundry.utils.duplicate(timestamp) })
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.debut', updateItemTimestamp); RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.debut', updateItemTimestamp);
RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp); RdDTimestamp.handleTimestampEditor(this.html, 'system.temporel.fin', updateItemTimestamp);

View File

@ -1,4 +1,4 @@
import { DialogItemVente } from "./dialog-item-vente.js"; import { DialogItemVente } from "./achat-vente/dialog-item-vente.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDHerbes } from "./rdd-herbes.js"; import { RdDHerbes } from "./rdd-herbes.js";
@ -177,7 +177,7 @@ export class RdDItem extends Item {
constructor(docData, context = {}) { constructor(docData, context = {}) {
if (!context.rdd?.ready) { if (!context.rdd?.ready) {
mergeObject(context, { rdd: { ready: true } }); foundry.utils.mergeObject(context, { rdd: { ready: true } });
const ItemConstructor = game.system.rdd.itemClasses[docData.type]; const ItemConstructor = game.system.rdd.itemClasses[docData.type];
if (ItemConstructor) { if (ItemConstructor) {
if (!docData.img) { if (!docData.img) {
@ -189,6 +189,7 @@ 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);
} }
@ -233,7 +234,7 @@ export class RdDItem extends Item {
} }
isCompetenceArme() { isCompetenceArme() {
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 TYPES.competencecreature == this.type && this.system.categorie == "possession" }
@ -317,8 +318,8 @@ export class RdDItem extends Item {
const timestampFin = await this.calculerFinPeriodeTemporel(timestampDebut); const timestampFin = await this.calculerFinPeriodeTemporel(timestampDebut);
await actor.updateEmbeddedDocuments('Item', [{ await actor.updateEmbeddedDocuments('Item', [{
_id: this.id, _id: this.id,
'system.temporel.debut': duplicate(timestampDebut), 'system.temporel.debut': foundry.utils.duplicate(timestampDebut),
'system.temporel.fin': duplicate(timestampFin), 'system.temporel.fin': foundry.utils.duplicate(timestampFin),
}]) }])
} }
} }
@ -538,7 +539,7 @@ export class RdDItem extends Item {
_id: this.id, _id: this.id,
'system.quantite': this.system.quantite * sust, 'system.quantite': this.system.quantite * sust,
'system.encombrement': Misc.keepDecimals(this.system.encombrement / sust, 2), 'system.encombrement': Misc.keepDecimals(this.system.encombrement / sust, 2),
'system.cout': Misc.keepDecimals(this.system.cout / sust, 2), 'system.cout': Math.max(0, Misc.keepDecimals(this.system.cout / sust, 2)),
'system.sust': 1 'system.sust': 1
}]) }])
} }
@ -621,23 +622,7 @@ export class RdDItem extends Item {
ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`); ui.notifications.warn(`Votre ${this.name} n'est pas vide, pas possible de le proposer`);
return; return;
} }
await DialogItemVente.display({ await DialogItemVente.display({ item: this, quantiteMax })
item: this,
quantiteMax,
callback: async (vente) => {
vente["properties"] = this.getProprietes();
if (vente.isOwned) {
if (vente.quantiteNbLots * vente.tailleLot > vente.quantiteMax) {
ui.notifications.warn(`Vous avez ${vente.quantiteMax} ${vente.item.name}, ce n'est pas suffisant pour vendre ${vente.quantiteNbLots} de ${vente.tailleLot}`)
return;
}
}
vente.jsondata = JSON.stringify(vente.item);
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', vente);
ChatMessage.create(RdDUtility.chatDataSetup(html));
}
});
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -39,7 +39,7 @@ export class RdDItemBlessure extends RdDItem {
ui.notifications.warn(`Pas de tâche de soins pour une blessure ${gravite}`) ui.notifications.warn(`Pas de tâche de soins pour une blessure ${gravite}`)
return undefined; return undefined;
} }
return foundry.utils.mergeObject(duplicate(BASE_TACHE_SOIN_BLESSURE), tache) return foundry.utils.mergeObject(BASE_TACHE_SOIN_BLESSURE, tache, { inplace: false })
} }
static async applyFullBlessure(actor, gravite) { static async applyFullBlessure(actor, gravite) {
@ -48,7 +48,7 @@ export class RdDItemBlessure extends RdDItem {
let lostEndurance = 0 let lostEndurance = 0
let lostVie = 0 let lostVie = 0
if (definition.endurance) { if (definition.endurance) {
lostEndurance = new Roll(definition.endurance).roll({async: false}).total; lostEndurance = await new Roll(definition.endurance).roll().total;
actor.santeIncDec("endurance", -Number(lostEndurance)); actor.santeIncDec("endurance", -Number(lostEndurance));
} }
if (definition.vie) { if (definition.vie) {
@ -106,12 +106,12 @@ export class RdDItemBlessure extends RdDItem {
} }
async setSoinsBlessure(systemUpdate = {}) { async setSoinsBlessure(systemUpdate = {}) {
systemUpdate = foundry.utils.mergeObject(systemUpdate, this.system, { overwrite: false }), systemUpdate = foundry.utils.mergeObject(systemUpdate, this.system, { overwrite: false })
systemUpdate.soinscomplets.done = systemUpdate.premierssoins.done && systemUpdate.soinscomplets.done systemUpdate.soinscomplets.done = systemUpdate.premierssoins.done && systemUpdate.soinscomplets.done
await this.update({ await this.update({
img: this.getImgSoins(systemUpdate.gravite, systemUpdate.soinscomplets.done), img: this.getImgSoins(systemUpdate.gravite, systemUpdate.soinscomplets.done),
system: systemUpdate system: systemUpdate
}); })
} }
async recuperationBlessure({ actor, timestamp, message, isMaladeEmpoisonne, blessures }) { async recuperationBlessure({ actor, timestamp, message, isMaladeEmpoisonne, blessures }) {

View File

@ -38,7 +38,7 @@ export class RdDItemMaladie extends RdDItem {
await mal.actor.updateEmbeddedDocuments('Item', [{ await mal.actor.updateEmbeddedDocuments('Item', [{
_id: mal.id, _id: mal.id,
'system.temporel.fin': duplicate(timestampFin), 'system.temporel.fin': foundry.utils.duplicate(timestampFin),
}]) }])
} }
} }

View File

@ -10,7 +10,7 @@ export class RdDItemInventaireSheet extends RdDItemSheet {
static get defaultOptions() { static get defaultOptions() {
return foundry.utils.mergeObject(RdDItemSheet.defaultOptions, { return foundry.utils.mergeObject(RdDItemSheet.defaultOptions, {
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }] tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "informations" }]
}); }, { inplace: false })
} }
setPosition(options = {}) { setPosition(options = {}) {
@ -23,9 +23,10 @@ export class RdDItemInventaireSheet extends RdDItemSheet {
async getData() { async getData() {
const formData = await super.getData(); const formData = await super.getData();
return foundry.utils.mergeObject(formData, { foundry.utils.mergeObject(formData, {
milieux: await game.system.rdd.environnement.autresMilieux(this.item) milieux: await game.system.rdd.environnement.autresMilieux(this.item)
}); })
return formData
} }
activateListeners(html) { activateListeners(html) {

View File

@ -8,7 +8,7 @@ export class RdDRencontreItemSheet extends RdDItemSheet {
static get defaultOptions() { static get defaultOptions() {
return foundry.utils.mergeObject(super.defaultOptions, { return foundry.utils.mergeObject(super.defaultOptions, {
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }] tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }]
}); }, { inplace: false })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -35,7 +35,7 @@ export class RdDRencontreItemSheet extends RdDItemSheet {
select: RdDRencontre.mapEffets(this.item.system.echec.effets) select: RdDRencontre.mapEffets(this.item.system.echec.effets)
} }
} }
}); })
return formData; return formData;
} }

View File

@ -5,6 +5,7 @@ import { Monnaie } from "./item-monnaie.js";
import { RdDItem, TYPES } from "./item.js"; import { RdDItem, 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";
class Migration { class Migration {
get code() { return "sample"; } get code() { return "sample"; }
@ -70,17 +71,17 @@ class _10_0_16_MigrationSortsReserve extends Migration {
get version() { return "10.0.16"; } get version() { return "10.0.16"; }
async migrate() { async migrate() {
await game.actors const actors = game.actors.filter((actor) => actor.type == "personnage" && (actor.system.reve?.reserve?.list?.length ?? 0 > 0))
.filter((actor) => actor.type == "personnage") Promise.all(actors.map(async it => await this.convertirSortsReserveActeur(it)))
.filter((actor) => actor.system.reve?.reserve?.list?.length ?? 0 > 0) }
.forEach(async (actor) => {
const sortsReserve = actor.system.reve.reserve.list.map(this.conversionSortReserve); async convertirSortsReserveActeur(actor) {
console.log(`${LOG_HEAD} Migration des sorts en réserve de ${actor.name}`, sortsReserve); const sortsReserve = actor.system.reve.reserve.list.map(this.conversionSortReserve);
await actor.createEmbeddedDocuments("Item", sortsReserve, { console.log(`${LOG_HEAD} Migration des sorts en réserve de ${actor.name}`, sortsReserve);
renderSheet: false, await actor.createEmbeddedDocuments("Item", sortsReserve, {
}); renderSheet: false,
await actor.update({ 'system.reve.reserve': undefined }) });
}); await actor.update({ 'system.reve.reserve': undefined });
} }
conversionSortReserve(it) { conversionSortReserve(it) {
@ -507,13 +508,28 @@ class _10_7_19_PossessionsEntiteVictime extends Migration {
} }
migratePossession(it) { migratePossession(it) {
return { _id: it.id, return {
_id: it.id,
'system.entite.actorid': it.system.possesseurid, 'system.entite.actorid': it.system.possesseurid,
'system.victime.actorid': it.system.possedeid 'system.victime.actorid': it.system.possedeid
} }
} }
} }
class _11_2_20_MigrationAstrologie extends Migration {
get code() { return "migration-astrologie" }
get version() { return "11.2.20" }
async migrate() {
const nombresAstraux = game.system.rdd.calendrier.getNombresAstraux()
nombresAstraux.forEach(na => {
na.lectures = na.valeursFausses
na.valeursFausses = undefined
})
await game.system.rdd.calendrier.setNombresAstraux(nombresAstraux)
}
}
export class Migrations { export class Migrations {
static getMigrations() { static getMigrations() {
return [ return [
@ -532,6 +548,7 @@ export class Migrations {
new _10_7_0_MigrationBlessures(), new _10_7_0_MigrationBlessures(),
new _10_7_19_CategorieCompetenceCreature(), new _10_7_19_CategorieCompetenceCreature(),
new _10_7_19_PossessionsEntiteVictime(), new _10_7_19_PossessionsEntiteVictime(),
new _11_2_20_MigrationAstrologie(),
]; ];
} }
@ -546,15 +563,18 @@ export class Migrations {
} }
migrate() { migrate() {
const currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion"); let currentVersion = game.settings.get(SYSTEM_RDD, "systemMigrationVersion")
if (isNewerVersion(game.system.version, currentVersion)) { if (currentVersion.startsWith("v")) {
currentVersion = currentVersion.substring(1)
}
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) => {
ui.notifications.info( ui.notifications.info(
`Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}` `${LOG_HEAD} Executing migration ${m.code}: version ${currentVersion} is lower than ${m.version}`
); );
await m.migrate(); await m.migrate();
}); });
@ -562,9 +582,7 @@ export class Migrations {
`Migrations done, version will change to ${game.system.version}` `Migrations done, version will change to ${game.system.version}`
); );
} else { } else {
console.log( console.log(`${LOG_HEAD} No migration needeed, version will change to ${game.system.version}`
LOG_HEAD +
`No migration needeed, version will change to ${game.system.version}`
); );
} }
@ -574,7 +592,7 @@ export class Migrations {
game.system.version game.system.version
); );
} else { } else {
console.log(LOG_HEAD + `No system version changed`); console.log(`${LOG_HEAD} No system version changed`);
} }
} }

View File

@ -166,15 +166,47 @@ export class Misc {
} }
static firstConnectedGM() { static firstConnectedGM() {
return game.users.filter(u => u.isGM && u.active).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 isOwnerPlayer(actor, user = undefined) { static connectedGMs() {
return actor.testUserPermission(user ?? game.user, CONST.DOCUMENT_PERMISSION_LEVELS.OWNER) return game.users.filter(u => u.isGM && u.active);
} }
static isOwnerPlayerOrUniqueConnectedGM(actor, user = undefined) { /**
return Misc.isOwnerPlayer(actor, user) ?? Misc.isUniqueConnectedGM(); * This helper method allows to get the docuument, for a single user (either first connected GM, or the owner
* if there is no connected GMs), or else return undefined.
*
* This allows for example update hooks that should apply modifications to actors to be called only for one
* user (preventing the "User ... lacks permission to update Item" that was occuring on hooks when Item updates
* were triggering other changes)
*
* @param {*} document the Document with is potentially an Actor
* @returns the actor if either the game.user is the first connected GM, or if the game.user is the owner
* and there is no connected GM
*/
static documentIfResponsible(document) {
if (foundry.utils.isNewerVersion(game.release.version, '12.0')) {
if (game.users.activeGM || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document)))
{
return document
}
}
else if (Misc.isUniqueConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isOwnerPlayer(document))) {
return document
}
return undefined
}
static isOwnerPlayer(document) {
return document.testUserPermission && document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
}
static isOwnerPlayerOrUniqueConnectedGM(actor) {
return Misc.isOwnerPlayer(actor) ?? Misc.isUniqueConnectedGM();
} }
/** /**

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

@ -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`);
} }
@ -119,7 +128,7 @@ export class RdDCombatManager extends Combat {
//console.log("Combatat", c); //console.log("Combatat", c);
const roll = combatant.getInitiativeRoll(rollFormula); const roll = combatant.getInitiativeRoll(rollFormula);
if (!roll.total) { if (!roll.total) {
roll.evaluate({ async: false }); await roll.evaluate();
} }
const total = Math.max(roll.total, 0.00); const total = Math.max(roll.total, 0.00);
console.log("Compute init for", rollFormula, roll, total, combatant); console.log("Compute init for", rollFormula, roll, total, combatant);
@ -128,21 +137,17 @@ export class RdDCombatManager extends Combat {
// Send a chat message // Send a chat message
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode"); let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
let messageData = foundry.utils.mergeObject( let messageData = foundry.utils.mergeObject({
{ speaker: {
speaker: { scene: canvas.scene._id,
scene: canvas.scene._id, actor: combatant.actor?._id,
actor: combatant.actor?._id, token: combatant.token._id,
token: combatant.token._id, alias: combatant.token.name,
alias: combatant.token.name, sound: CONFIG.sounds.dice,
sound: CONFIG.sounds.dice,
},
flavor: `${combatant.token.name} a fait son jet d'Initiative (${messageOptions.initInfo})
<br>
`,
}, },
messageOptions flavor: `${combatant.token.name} a fait son jet d'Initiative (${messageOptions.initInfo})<br>`,
); },
messageOptions);
roll.toMessage(messageData, { rollMode, create: true }); roll.toMessage(messageData, { rollMode, create: true });
RdDCombatManager.processPremierRoundInit(); RdDCombatManager.processPremierRoundInit();
@ -218,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 = 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;
} }
@ -339,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;
@ -374,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 });
@ -791,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),
@ -890,7 +897,7 @@ export class RdDCombat {
// # utilisation esquive // # utilisation esquive
const corpsACorps = this.defender.getCompetenceCorpsACorps({ onMessage: it => console.info(it, this.defender) }); const corpsACorps = this.defender.getCompetenceCorpsACorps({ onMessage: it => console.info(it, this.defender) });
const esquives = duplicate(this.defender.getCompetencesEsquive()) const esquives = foundry.utils.duplicate(this.defender.getCompetencesEsquive())
esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0); esquives.forEach(e => e.system.nbUsage = e?._id ? this.defender.getItemUse(e._id) : 0);
const paramChatDefense = { const paramChatDefense = {

View File

@ -1,32 +1,28 @@
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) {
options.bypass = options.bypass || !(options.settingConfirmer == undefined || ReglesOptionnelles.isUsing(options.settingConfirmer)); if (options.settingConfirmer && !ReglesOptionnelles.isSet(options.settingConfirmer)) {
if (options.bypass) { return options.onAction()
options.onAction();
} }
else { let buttons = {
let buttons = { "action": RdDConfirm._createButtonAction(options),
"action": RdDConfirm._createButtonAction(options), "cancel": RdDConfirm._createButtonCancel()
"cancel": RdDConfirm._createButtonCancel() };
}; if (options.settingConfirmer) {
if (options.settingConfirmer) { buttons = foundry.utils.mergeObject(RdDConfirm._createButtonActionSave(options), buttons);
buttons = foundry.utils.mergeObject(RdDConfirm._createButtonActionSave(options), buttons);
}
if (autresActions) {
buttons = foundry.utils.mergeObject(autresActions, buttons);
}
const dialogDetails = {
title: options.title,
content: options.content,
default: "cancel",
buttons: buttons
};
new Dialog(dialogDetails, { width: 150 * Object.keys(buttons).length }).render(true);
} }
if (autresActions) {
buttons = foundry.utils.mergeObject(autresActions, buttons, { inplace: false });
}
const dialogDetails = {
title: options.title,
content: options.content,
default: "cancel",
buttons: buttons
};
new Dialog(dialogDetails, { width: 150 * Object.keys(buttons).length }).render(true);
} }
static _createButtonCancel() { static _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;
} }
@ -138,7 +138,7 @@ export class RdDDice {
static async roll(formula, options = { showDice: SHOW_DICE, rollMode: undefined }) { static async roll(formula, options = { showDice: SHOW_DICE, rollMode: undefined }) {
const roll = new Roll(RdDDice._formulaOrFake(formula, options)); const roll = new Roll(RdDDice._formulaOrFake(formula, options));
await roll.evaluate({ async: true }); await roll.evaluate();
await this.showDiceSoNice(roll, options); await this.showDiceSoNice(roll, options);
return roll; return roll;
} }
@ -216,7 +216,7 @@ export class RdDDice {
static async fakeD10(faces) { static async fakeD10(faces) {
let roll = new Roll(`1d${faces}`); let roll = new Roll(`1d${faces}`);
await roll.evaluate({ async: true }); await roll.evaluate();
return roll.total; return roll.total;
} }

View File

@ -98,7 +98,7 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static getEmpoignadeById(actor, id) { static getEmpoignadeById(actor, id) {
let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id) let emp = actor.itemTypes[TYPES.empoignade].find(it => it.system.empoignadeid == id)
return emp && duplicate(emp) || undefined; return emp && foundry.utils.duplicate(emp) || undefined;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -108,7 +108,7 @@ export class RdDEmpoignade {
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id) (it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
) )
if (emp) { if (emp) {
return duplicate(emp); return foundry.utils.duplicate(emp);
} }
return undefined; return undefined;
} }
@ -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);
} }
@ -267,7 +267,7 @@ export class RdDEmpoignade {
return return
} }
empoignade = duplicate(empoignade) empoignade = foundry.utils.duplicate(empoignade)
let defenderRoll = { let defenderRoll = {
mode, attacker, defender, empoignade, attackerRoll, mode, attacker, defender, empoignade, attackerRoll,
diffLibre: attackerRoll.diffLibre, diffLibre: attackerRoll.diffLibre,
@ -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

@ -1,4 +1,4 @@
import { SYSTEM_RDD, SYSTEM_SOCKET_ID } 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";
@ -71,15 +71,16 @@ import { RdDTMRDialog } from "./rdd-tmr-dialog.js";
* Software License: GNU GPLv3 * Software License: GNU GPLv3
*/ */
export class SystemReveDeDragon { export class SystemReveDeDragon {
static start() { static start() {
const system = new SystemReveDeDragon() const system = new SystemReveDeDragon()
Hooks.once('init', async () => await system.onInit()) Hooks.once('init', async () => await system.onInit())
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d)) Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d))
Hooks.once('ready', () => system.onReady()) Hooks.once('ready', () => system.onReady())
} }
constructor() { constructor() {
this.config = RDD_CONFIG;
this.RdDUtility = RdDUtility; this.RdDUtility = RdDUtility;
this.RdDHotbar = RdDHotbar; this.RdDHotbar = RdDHotbar;
this.itemClasses = { this.itemClasses = {
@ -108,7 +109,7 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */ /* -------------------------------------------- */
async onInit() { async onInit() {
game.system.rdd = this; game.system.rdd = this;
this.AppAstrologie = AppAstrologie; this.AppAstrologie = AppAstrologie;
console.log(`Initializing Reve de Dragon System`); console.log(`Initializing Reve de Dragon System`);

View File

@ -56,7 +56,7 @@ const temperatures = [
export class RdDMeteo { export class RdDMeteo {
static async getForce() { static async getForce() {
const roll = new Roll(`1dr`); const roll = new Roll(`1dr`);
await roll.evaluate({ async: true }); await roll.evaluate();
return roll.total; return roll.total;
} }
@ -67,14 +67,14 @@ export class RdDMeteo {
static async getTemperature() { static async getTemperature() {
const degre = await RdDMeteo.getForce(); const degre = await RdDMeteo.getForce();
const rollChaudFroid = new Roll('1d2'); const rollChaudFroid = new Roll('1d2');
await rollChaudFroid.evaluate({ async: true }); await rollChaudFroid.evaluate();
const chaudFroid = rollChaudFroid.total == 1; const chaudFroid = rollChaudFroid.total == 1;
return chaudFroid.total ? degre : -degre; return chaudFroid.total ? degre : -degre;
} }
static async getDirection(direction) { static async getDirection(direction) {
const roll = new Roll(`1d16`); const roll = new Roll(`1d16`);
await roll.evaluate({ async: true }); await roll.evaluate();
switch (roll.total % 16) { switch (roll.total % 16) {
case 0: return 'Nord'; case 0: return 'Nord';
case 1: return 'Nord Nord Est'; case 1: return 'Nord Nord Est';

View File

@ -24,7 +24,7 @@ export class RdDPossession {
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 == TYPES.possession && poss.system.victime.actorid == defender.id);
} }
return poss && duplicate(poss) || undefined; return poss && foundry.utils.duplicate(poss) || undefined;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -52,7 +52,7 @@ export class RdDPossession {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async onConjurerPossession(attacker, possession) { static async onConjurerPossession(attacker, possession) {
possession = duplicate(possession); possession = foundry.utils.duplicate(possession);
RdDPossession.$updateEtatPossession(possession) RdDPossession.$updateEtatPossession(possession)
const defender = game.actors.get(possession.system.entite.actorid); const defender = game.actors.get(possession.system.entite.actorid);
@ -80,7 +80,7 @@ export class RdDPossession {
ui.notifications.warn("Une erreur s'est produite : Aucune possession trouvée !!") ui.notifications.warn("Une erreur s'est produite : Aucune possession trouvée !!")
return return
} }
possession = duplicate(possession) possession = foundry.utils.duplicate(possession)
// Update for draconic roll // Update for draconic roll
let rollData = { let rollData = {
mode: "defense", mode: "defense",
@ -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;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -114,7 +114,7 @@ export class RdDResolutionTable {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async roll(caracValue, finalLevel, rollData = {}) { static async roll(caracValue, finalLevel, rollData = {}) {
let chances = duplicate(this.computeChances(caracValue, finalLevel)); let chances = foundry.utils.duplicate(this.computeChances(caracValue, finalLevel));
this._updateChancesWithBonus(chances, rollData.bonus, finalLevel); this._updateChancesWithBonus(chances, rollData.bonus, finalLevel);
this._updateChancesFactor(chances, rollData.diviseurSignificative); this._updateChancesFactor(chances, rollData.diviseurSignificative);
chances.showDice = rollData.showDice; chances.showDice = rollData.showDice;

View File

@ -76,7 +76,7 @@ export class RdDSheetUtility {
static async _onSplitItem(item, split, actor) { static async _onSplitItem(item, split, actor) {
if (split >= 1 && split < item.system.quantite) { if (split >= 1 && split < item.system.quantite) {
await item.diminuerQuantite(split); await item.diminuerQuantite(split);
const splitItem = duplicate(item); const splitItem = foundry.utils.duplicate(item);
// todo: ajouter dans le même conteneur? // todo: ajouter dans le même conteneur?
splitItem.system.quantite = split; splitItem.system.quantite = split;
await actor.createEmbeddedDocuments('Item', [splitItem]) await actor.createEmbeddedDocuments('Item', [splitItem])

View File

@ -70,7 +70,7 @@ export class RdDTMRDialog extends Dialog {
'z-index': 40 'z-index': 40
} }
super(dialogConf, dialogOptions); super(dialogConf, dialogOptions);
this.tmrdata = duplicate(tmrData); this.tmrdata = foundry.utils.duplicate(tmrData);
this.actor = actor; this.actor = actor;
this.actor.tmrApp = this; // reference this app in the actor structure this.actor.tmrApp = this; // reference this app in the actor structure
this.viewOnly = tmrData.mode == "visu" this.viewOnly = tmrData.mode == "visu"
@ -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;
} }
@ -212,7 +221,7 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
loadRencontres() { loadRencontres() {
this.rencontresExistantes = this.actor.getTMRRencontres(); this.rencontresExistantes = this.actor.getRencontresTMR();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -302,7 +311,7 @@ export class RdDTMRDialog extends Dialog {
} }
const coord = this._getCoordActor(); const coord = this._getCoordActor();
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord)); HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
let ptsreve = document.getElementById("tmr-pointsreve-value"); let ptsreve = document.getElementById("tmr-pointsreve-value");
ptsreve.innerHTML = this.actor.system.reve.reve.value; ptsreve.innerHTML = this.actor.system.reve.reve.value;
@ -382,7 +391,7 @@ export class RdDTMRDialog extends Dialog {
async refouler() { async refouler() {
console.log("-> refouler", this.currentRencontre); console.log("-> refouler", this.currentRencontre);
await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`); await this.actor.ajouterRefoulement(this.currentRencontre.system.refoulement, `${this.currentRencontre.system.genre == 'f' ? 'une' : 'un'} ${this.currentRencontre.name}`);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary await this.actor.deleteRencontreTMRAtPosition()
this.updateTokens(); this.updateTokens();
this.updateValuesDisplay(); this.updateValuesDisplay();
this.nettoyerRencontre(); this.nettoyerRencontre();
@ -392,7 +401,7 @@ export class RdDTMRDialog extends Dialog {
async ignorerRencontre() { async ignorerRencontre() {
console.log("-> ignorer", this.currentRencontre); console.log("-> ignorer", this.currentRencontre);
this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name); this._tellToGM(this.actor.name + " a ignoré: " + this.currentRencontre.name);
await this.actor.deleteTMRRencontreAtPosition(); // Remove the stored rencontre if necessary await this.actor.deleteRencontreTMRAtPosition()
this.updateTokens(); this.updateTokens();
this.updateValuesDisplay(); this.updateValuesDisplay();
this.nettoyerRencontre(); this.nettoyerRencontre();
@ -407,7 +416,7 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
$marquerCasesTMR(listCoordTMR) { $marquerCasesTMR(listCoordTMR) {
this.currentRencontre.locList = duplicate(listCoordTMR); // And track of allowed location this.currentRencontre.locList = foundry.utils.duplicate(listCoordTMR); // And track of allowed location
this.currentRencontre.graphics = listCoordTMR.map(coordTMR => this.pixiTMR.addMarkTMR(coordTMR)) this.currentRencontre.graphics = listCoordTMR.map(coordTMR => this.pixiTMR.addMarkTMR(coordTMR))
} }
@ -446,7 +455,7 @@ export class RdDTMRDialog extends Dialog {
async maitriserRencontre() { async maitriserRencontre() {
console.log("-> maitriser", this.currentRencontre); console.log("-> maitriser", this.currentRencontre);
await this.actor.deleteTMRRencontreAtPosition(); await this.actor.deleteRencontreTMRAtPosition()
this.updateTokens(); this.updateTokens();
let rencontreData = { let rencontreData = {
@ -679,7 +688,7 @@ export class RdDTMRDialog extends Dialog {
if (this.isCaseHumide(tmr)) { if (this.isCaseHumide(tmr)) {
let rollData = { let rollData = {
actor: this.actor, actor: this.actor,
competence: duplicate(this.actor.getBestDraconic()), competence: foundry.utils.duplicate(this.actor.getBestDraconic()),
tmr: tmr, tmr: tmr,
canClose: false, canClose: false,
diffLibre: -7, diffLibre: -7,
@ -804,7 +813,7 @@ export class RdDTMRDialog extends Dialog {
async _conquerir(tmr, options) { async _conquerir(tmr, options) {
let rollData = { let rollData = {
actor: this.actor, actor: this.actor,
competence: duplicate(this.actor.getBestDraconic()), competence: foundry.utils.duplicate(this.actor.getBestDraconic()),
tmr: tmr, tmr: tmr,
canClose: options.canClose ?? false, canClose: options.canClose ?? false,
diffLibre: options.difficulte ?? -7, diffLibre: options.difficulte ?? -7,

View File

@ -4,7 +4,7 @@ import { RdDCombat } from "./rdd-combat.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
import { DialogItemAchat } from "./dialog-item-achat.js"; import { DialogItemAchat } from "./achat-vente/dialog-item-achat.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { RdDDice } from "./rdd-dice.js"; import { RdDDice } from "./rdd-dice.js";
import { RdDItem } from "./item.js"; import { RdDItem } from "./item.js";
@ -18,6 +18,8 @@ import { RdDRaretes } from "./item/raretes.js";
import { RdDEmpoignade } from "./rdd-empoignade.js"; 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 { RDD_CONFIG } from "./constants.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
// This table starts at 0 -> niveau -10 // This table starts at 0 -> niveau -10
@ -31,7 +33,7 @@ function _buildAllSegmentsFatigue(max) {
const cycle = [5, 2, 4, 1, 3, 0]; const cycle = [5, 2, 4, 1, 3, 0];
const fatigue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]]; const fatigue = [[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]];
for (let i = 0; i <= max; i++) { for (let i = 0; i <= max; i++) {
const ligneFatigue = duplicate(fatigue[i]); const ligneFatigue = foundry.utils.duplicate(fatigue[i]);
const caseIncrementee = cycle[i % 6]; const caseIncrementee = cycle[i % 6];
ligneFatigue[caseIncrementee]++; ligneFatigue[caseIncrementee]++;
ligneFatigue[caseIncrementee + 6]++; ligneFatigue[caseIncrementee + 6]++;
@ -45,7 +47,7 @@ function _buildAllSegmentsFatigue(max) {
function _cumulSegmentsFatigue(matrix) { function _cumulSegmentsFatigue(matrix) {
let cumulMatrix = []; let cumulMatrix = [];
for (let line of matrix) { for (let line of matrix) {
let cumul = duplicate(line); let cumul = foundry.utils.duplicate(line);
for (let i = 1; i < 12; i++) { for (let i = 1; i < 12; i++) {
cumul[i] += cumul[i - 1]; cumul[i] += cumul[i - 1];
@ -98,8 +100,9 @@ export class RdDUtility {
static afficheContenu = {} static afficheContenu = {}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async init() { static async init() {
Hooks.on("renderChatMessage", async (app, html, msg) => RdDUtility.onRenderChatMessage(app, html, msg)); Hooks.on("renderChatMessage", async (app, html, msg) => await ChatUtility.onRenderChatMessage(app, html, msg))
Hooks.on('renderChatLog', (log, html, chatLog) => RdDUtility.chatListeners(html)); Hooks.on("createChatMessage", async (chatMessage, options, id) => await ChatUtility.onCreateChatMessage(chatMessage, options, id))
Hooks.on('renderChatLog', (log, html, chatLog) => RdDUtility.chatListeners(html))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -205,6 +208,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/voyage/fatigue-actor.hbs', 'systems/foundryvtt-reve-de-dragon/templates/voyage/fatigue-actor.hbs',
'systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs', 'systems/foundryvtt-reve-de-dragon/templates/voyage/option-vitesse-fatigue.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs', 'systems/foundryvtt-reve-de-dragon/templates/common/timestamp.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs', 'systems/foundryvtt-reve-de-dragon/templates/common/periodicite.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs', 'systems/foundryvtt-reve-de-dragon/templates/common/enum-duree.hbs',
'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs', 'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs',
@ -259,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() ?? '');
@ -269,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)); });
@ -297,6 +303,14 @@ export class RdDUtility {
Handlebars.registerHelper('plusMoins', diff => (diff > 0 ? '+' : '') + Math.round(diff)) Handlebars.registerHelper('plusMoins', diff => (diff > 0 ? '+' : '') + Math.round(diff))
Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic)); Handlebars.registerHelper('experienceLog-topic', topic => ExperienceLog.labelTopic(topic));
// Handle v12 removal of this helper
Handlebars.registerHelper('select', function (selected, options) {
const escapedValue = RegExp.escape(Handlebars.escapeExpression(selected));
const rgx = new RegExp(' value=[\"\']' + escapedValue + '[\"\']');
const html = options.fn(this);
return html.replace(rgx, "$& selected");
});
return loadTemplates(templatePaths); return loadTemplates(templatePaths);
} }
@ -344,13 +358,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);
}
} }
} }
} }
@ -549,49 +565,54 @@ export class RdDUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async jetEncaissement(rollData, armure, options = { showDice: HIDE_DICE }) { static async jetEncaissement(rollData, armure, options = { showDice: HIDE_DICE }) {
let formula = "2d10"; const diff = Math.abs(rollData.diffLibre);
let formula = RdDUtility.formuleEncaissement(diff, options)
const roll = await RdDDice.roll(formula, options);
// Chaque dé fait au minmum la difficulté libre RdDUtility.remplaceDeMinParDifficulte(roll, diff, options);
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre')) {
if (rollData.diffLibre < 0) {
let valeurMin = Math.abs(rollData.diffLibre);
formula += "min" + valeurMin;
}
}
// Chaque dé fait au minmum la difficulté libre
if (ReglesOptionnelles.isUsing('degat-ajout-malus-libre')) {
if (rollData.diffLibre < 0) {
let valeurMin = Math.abs(rollData.diffLibre);
formula += "+" + valeurMin;
}
}
let roll = await RdDDice.roll(formula, options);
// 1 dé fait au minmum la difficulté libre
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre-simple')) {
if (rollData.diffLibre < 0) {
let valeurMin = Math.abs(rollData.diffLibre);
if (roll.terms[0].results[0].result < valeurMin) {
roll.terms[0].results[0].result = valeurMin;
} else if (roll.terms[0].results[1].result < valeurMin) {
roll.terms[0].results[1].result = valeurMin;
}
roll._total = roll.terms[0].results[0].result + roll.terms[0].results[1].result;
}
}
return await RdDUtility.prepareEncaissement(rollData, roll, armure); return await RdDUtility.prepareEncaissement(rollData, roll, armure);
} }
static remplaceDeMinParDifficulte(roll, diff, options) {
if (!ReglesOptionnelles.isUsing('degat-minimum-malus-libre-simple')) {
return
}
// 1 dé fait au minmum la difficulté libre
const total = options.forceDiceResult?.total;
if (total) {
const reste = Math.max(total - diff, 1)
roll.terms[0].number = reste + diff
}
else {
if (roll.terms[0].results[0].result < diff) {
roll.terms[0].results[0].result = diff;
} else if (roll.terms[0].results[1].result < diff) {
roll.terms[0].results[1].result = diff;
}
roll._total = roll.terms[0].results[0].result + roll.terms[0].results[1].result;
}
}
static formuleEncaissement(diff, options) {
// Chaque dé fait au minimum la difficulté libre
if (ReglesOptionnelles.isUsing('degat-minimum-malus-libre')) {
return `2d10min${diff}`
}
return '2d10'
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async prepareEncaissement(rollData, roll, armure) { static async prepareEncaissement(rollData, roll, armure) {
const jetTotal = roll.total + rollData.dmg.total - armure; // La difficulté d'ataque s'ajoute aux dégâts
let encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite); const bonusDegatsDiffLibre = ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(rollData.diffLibre ?? 0) : 0
let over20 = Math.max(jetTotal - 20, 0); const jetTotal = roll.total + rollData.dmg.total - armure + bonusDegatsDiffLibre
const encaissement = RdDUtility._selectEncaissement(jetTotal, rollData.dmg.mortalite);
const over20 = Math.max(jetTotal - 20, 0);
encaissement.dmg = rollData.dmg; encaissement.dmg = rollData.dmg;
encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(this.type); encaissement.dmg.loc = rollData.dmg.loc ?? await RdDUtility.getLocalisation(this.type);
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;'; encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;';
encaissement.dmg.bonusDegatsDiffLibre = bonusDegatsDiffLibre
encaissement.roll = roll; encaissement.roll = roll;
encaissement.armure = armure; encaissement.armure = armure;
encaissement.penetration = rollData.arme?.system.penetration ?? 0; encaissement.penetration = rollData.arme?.system.penetration ?? 0;
@ -607,34 +628,28 @@ export class RdDUtility {
for (let encaissement of table) { for (let encaissement of table) {
if ((encaissement.minimum === undefined || encaissement.minimum <= degats) if ((encaissement.minimum === undefined || encaissement.minimum <= degats)
&& (encaissement.maximum === undefined || degats <= encaissement.maximum)) { && (encaissement.maximum === undefined || degats <= encaissement.maximum)) {
return duplicate(encaissement); return foundry.utils.duplicate(encaissement);
} }
} }
return duplicate(table[0]); return foundry.utils.duplicate(table[0]);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async _evaluatePerte(formula, over20) { static async _evaluatePerte(formula, over20) {
let perte = new Roll(formula, { over20: over20 }); let perte = new Roll(formula, { over20: over20 });
await perte.evaluate({ async: true }); await perte.evaluate();
return perte.total; return perte.total;
} }
/* -------------------------------------------- */
static async responseNombreAstral(callData) {
let actor = game.actors.get(callData.id);
actor.ajouteNombreAstral(callData);
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static onSocketMessage(sockmsg) { static onSocketMessage(sockmsg) {
switch (sockmsg.msg) { switch (sockmsg.msg) {
case "msg_gm_chat_message": case "msg_gm_chat_message":
return ChatUtility.handleGMChatMessage(sockmsg.data); return ChatUtility.handleGMChatMessage(sockmsg.data);
case "msg_app_astrologie_refresh":
return Hooks.callAll(APP_ASTROLOGIE_REFRESH);
case "msg_request_nombre_astral": case "msg_request_nombre_astral":
return game.system.rdd.calendrier.requestNombreAstral(sockmsg.data); return game.system.rdd.calendrier.requestNombreAstral(sockmsg.data);
case "msg_response_nombre_astral":
return RdDUtility.responseNombreAstral(sockmsg.data);
case "msg_tmr_move": case "msg_tmr_move":
let actor = game.actors.get(sockmsg.data.actorId); let actor = game.actors.get(sockmsg.data.actorId);
if (actor.isOwner || game.user.isGM) { if (actor.isOwner || game.user.isGM) {
@ -754,7 +769,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,
@ -890,10 +905,4 @@ export class RdDUtility {
} }
} }
/*-------------------------------------------- */
static async onRenderChatMessage(app, html, msg) {
// TODO
//console.log(app, html, msg);
}
} }

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

@ -26,6 +26,7 @@ const listeReglesOptionnelles = [
{ group: 'Confirmations', name: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"}, { group: 'Confirmations', name: 'confirmer-combat-sans-cible', descr: "Confirmer avant une attaque sans cible", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"}, { group: 'Confirmations', name: 'confirmation-tmr', descr: "Confirmer pour monter dans les TMR", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-tmr-rencontre', descr: "Confirmer pour monter dans les TMR avec rencontre en attente", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-refouler', descr: "Confirmer avant de refouler", scope: "client"}, { group: 'Confirmations', name: 'confirmation-refouler', descr: "Confirmer avant de refouler", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"}, { group: 'Confirmations', name: 'confirmation-vider', descr: "Confirmer pour vider l'équipement", scope: "client"},
{ group: 'Confirmations', name: 'confirmation-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"}, { group: 'Confirmations', name: 'confirmation-supprimer-lien-acteur', descr: "Confirmer pour détacher un animal/suivant/véhicule", scope: "client"},
@ -70,8 +71,7 @@ export class ReglesOptionnelles extends FormApplication {
} }
static get defaultOptions() { static get defaultOptions() {
const options = super.defaultOptions; return foundry.utils.mergeObject(super.defaultOptions, {
foundry.utils.mergeObject(options, {
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.html",
height: 650, height: 650,
@ -79,14 +79,13 @@ export class ReglesOptionnelles extends FormApplication {
minimizable: false, minimizable: false,
closeOnSubmit: true, closeOnSubmit: true,
title: "Règles optionnelles" title: "Règles optionnelles"
}); }, { inplace: false })
return options;
} }
getData() { getData() {
let formData = super.getData(); let formData = super.getData();
const regles = listeReglesOptionnelles.filter(it => game.user.isGM || it.scope == "client").map(it => { const regles = listeReglesOptionnelles.filter(it => game.user.isGM || it.scope == "client").map(it => {
it = duplicate(it); it = foundry.utils.duplicate(it);
it.id = ReglesOptionnelles._getIdRegle(it.name); it.id = ReglesOptionnelles._getIdRegle(it.name);
it.active = ReglesOptionnelles.isSet(it.name); it.active = ReglesOptionnelles.isSet(it.name);
return it; return it;

View File

@ -18,8 +18,8 @@ const rddStatusEffects = [
{ rdd: true, id: STATUSES.StatusStunned, label: 'EFFECT.StatusStunned', icon: 'icons/svg/stoned.svg', "duration.rounds": 1 }, { rdd: true, id: STATUSES.StatusStunned, label: 'EFFECT.StatusStunned', icon: 'icons/svg/stoned.svg', "duration.rounds": 1 },
{ rdd: true, id: STATUSES.StatusBleeding, label: 'EFFECT.StatusBleeding', icon: 'icons/svg/blood.svg' }, { rdd: true, id: STATUSES.StatusBleeding, label: 'EFFECT.StatusBleeding', icon: 'icons/svg/blood.svg' },
{ rdd: true, id: STATUSES.StatusProne, label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg' }, { rdd: true, id: STATUSES.StatusProne, label: 'EFFECT.StatusProne', icon: 'icons/svg/falling.svg' },
{ rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.svg' }, { rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', label: 'EFFECT.StatusGrappling', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.webp' },
{ rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.svg' }, { rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', label: 'EFFECT.StatusGrappled', icon: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.webp' },
{ rdd: true, id: STATUSES.StatusRestrained, label: 'EFFECT.StatusRestrained', icon: 'icons/svg/net.svg' }, { rdd: true, id: STATUSES.StatusRestrained, label: 'EFFECT.StatusRestrained', icon: 'icons/svg/net.svg' },
{ rdd: true, id: STATUSES.StatusUnconscious, label: 'EFFECT.StatusUnconscious', icon: 'icons/svg/unconscious.svg' }, { rdd: true, id: STATUSES.StatusUnconscious, label: 'EFFECT.StatusUnconscious', icon: 'icons/svg/unconscious.svg' },
{ rdd: true, id: STATUSES.StatusBlind, label: 'EFFECT.StatusBlind', icon: 'icons/svg/blind.svg' }, { rdd: true, id: STATUSES.StatusBlind, label: 'EFFECT.StatusBlind', icon: 'icons/svg/blind.svg' },
@ -65,7 +65,7 @@ export class StatusEffects extends FormApplication {
static valeurSurprise(effect, isCombat) { static valeurSurprise(effect, isCombat) {
if (statusSurpriseTotale.intersects(effect.statuses)) { if (statusSurpriseTotale.intersects(effect.statuses)) {
return 2; return 2
} }
if (statusDemiSurprise.intersects(effect.statuses)) { if (statusDemiSurprise.intersects(effect.statuses)) {
return 1 return 1
@ -94,7 +94,7 @@ export class StatusEffects extends FormApplication {
static prepareActiveEffect(effectId) { static prepareActiveEffect(effectId) {
let status = rddStatusEffects.find(it => it.id == effectId) let status = rddStatusEffects.find(it => it.id == effectId)
if (status) { if (status) {
status = duplicate(status) status = foundry.utils.duplicate(status)
status.statuses = [effectId] status.statuses = [effectId]
} }
return status; return status;
@ -110,7 +110,7 @@ export class StatusEffects extends FormApplication {
static get defaultOptions() { static get defaultOptions() {
const options = super.defaultOptions; const options = super.defaultOptions;
mergeObject(options, { foundry.utils.mergeObject(options, {
id: "status-effects", id: "status-effects",
template: "systems/foundryvtt-reve-de-dragon/templates/settings/status-effects.html", template: "systems/foundryvtt-reve-de-dragon/templates/settings/status-effects.html",
height: 800, height: 800,
@ -125,7 +125,7 @@ export class StatusEffects extends FormApplication {
getData() { getData() {
const used = StatusEffects._getUseStatusEffects(); const used = StatusEffects._getUseStatusEffects();
let formData = super.getData(); let formData = super.getData();
formData.effects = duplicate(CONFIG.RDD.allEffects); formData.effects = foundry.utils.duplicate(CONFIG.RDD.allEffects);
formData.effects.forEach(it => it.active = used.includes(it.id)) formData.effects.forEach(it => it.active = used.includes(it.id))
return formData; return formData;
} }

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";
@ -152,7 +153,7 @@ export class SystemCompendiums extends FormApplication {
getData() { getData() {
const systemCompendiums = Object.values(CONFIGURABLE_COMPENDIUMS) const systemCompendiums = Object.values(CONFIGURABLE_COMPENDIUMS)
.map(it => foundry.utils.mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) })); .map(it => foundry.utils.mergeObject(it, { value: SystemCompendiums.getCompendium(it.compendium) }, { inplace: false }))
const availableCompendiums = game.packs.map(pack => { const availableCompendiums = game.packs.map(pack => {
return { return {
name: pack.collection, name: pack.collection,
@ -163,7 +164,7 @@ export class SystemCompendiums extends FormApplication {
return foundry.utils.mergeObject(super.getData(), { return foundry.utils.mergeObject(super.getData(), {
systemCompendiums: systemCompendiums, systemCompendiums: systemCompendiums,
availableCompendiums: availableCompendiums availableCompendiums: availableCompendiums
}); }, { inplace: false })
} }
activateListeners(html) { activateListeners(html) {
@ -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

@ -25,13 +25,12 @@ export class AppAstrologie extends Application {
classes: ['calendar-astrologie'], classes: ['calendar-astrologie'],
popOut: true, popOut: true,
resizable: false resizable: false
}); }, { inplace: false })
} }
constructor(actor, options = {}) { constructor(actor, options = {}) {
super(options); super(options);
this.actor = actor; this.actor = actor;
this.hookReference = Hooks.on(APP_ASTROLOGIE_REFRESH, () => this.refreshAstrologie());
} }
getData(options) { getData(options) {
@ -50,7 +49,7 @@ export class AppAstrologie extends Application {
signeNaissance: RdDTimestamp.definition(0) signeNaissance: RdDTimestamp.definition(0)
} }
}) })
return this.appData; return this.appData
} }
getActorAstrologie() { getActorAstrologie() {
@ -85,9 +84,10 @@ export class AppAstrologie extends Application {
const nbAstral = calendrier.getNombreAstral() const nbAstral = calendrier.getNombreAstral()
const heures = RdDTimestamp.heures(); const heures = RdDTimestamp.heures();
return { return {
ajustementsActors:game.actors.filter(actor => actor.isPersonnageJoueur()) ajustementsActors: game.actors.filter(actor => actor.isPersonnageJoueur())
.map(actor => this.getAjustementActor(actor, nbAstral, heures)), .map(actor => this.getAjustementActor(actor, nbAstral, heures)),
nombresAstraux: calendrier.getNombresAstraux().map(na => this.getDetailNombreAstral(na)) nombresAstraux: game.system.rdd.calendrier.getNombresAstraux()
.map(na => this.getDetailNombreAstral(na))
} }
} }
return {} return {}
@ -104,15 +104,18 @@ export class AppAstrologie extends Application {
} }
getDetailNombreAstral(nombreAstral) { getDetailNombreAstral(nombreAstral) {
const detail = duplicate(nombreAstral); const detail = foundry.utils.duplicate(nombreAstral);
const timestamp = new RdDTimestamp({ indexDate: nombreAstral.index }); const timestamp = new RdDTimestamp({ indexDate: nombreAstral.index });
detail.date = { mois: timestamp.mois, jour: timestamp.jour + 1 }; detail.date = { mois: timestamp.mois, jour: timestamp.jour + 1 };
detail.valeursFausses.forEach(fausse => fausse.actorName = game.actors.get(fausse.actorId).name ?? "Inconnu"); detail.lectures.forEach(lecture => lecture.actorName = game.actors.get(lecture.actorId).name ?? "Inconnu");
return detail; return detail;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
activateListeners(html) { activateListeners(html) {
if (!this.hookReference){
this.hookReference = Hooks.on(APP_ASTROLOGIE_REFRESH, () => this.refreshAstrologie());
}
super.activateListeners(html); super.activateListeners(html);
this.html = html; this.html = html;
this.html.find('select[name="signe-astral"]').change(event => { this.html.find('select[name="signe-astral"]').change(event => {
@ -145,8 +148,7 @@ export class AppAstrologie extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
async onRebuild() { async onRebuild() {
game.system.rdd.calendrier.resetNombresAstraux(); await game.system.rdd.calendrier.resetNombresAstraux();
await game.system.rdd.calendrier.rebuildNombresAstraux(); await game.system.rdd.calendrier.rebuildNombresAstraux();
} }
@ -195,6 +197,8 @@ export class AppAstrologie extends Application {
} }
refreshAstrologie() { refreshAstrologie() {
this.count = (this.count ?? 0)+1
console.log(`Refreshing ${this.count}`);
this.render(true) this.render(true)
} }

View File

@ -17,7 +17,7 @@ export class AutoAdjustDarkness {
static async adjust(darkness) { static async adjust(darkness) {
if (AutoAdjustDarkness.isAuto()) { if (AutoAdjustDarkness.isAuto()) {
const scene = game.scenes.viewed; const scene = game.scenes.viewed;
if (scene?.globalLight && scene?.tokenVision) { if (scene?.environment?.globalLight?.enabled && scene?.tokenVision) {
await scene.update({ darkness }); await scene.update({ darkness });
} }
} }

View File

@ -61,7 +61,7 @@ export class RdDCalendrierEditor extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
updateData(calendrierData) { updateData(calendrierData) {
this.calendrierData = duplicate(calendrierData); this.calendrierData = foundry.utils.duplicate(calendrierData);
} }
} }

View File

@ -43,7 +43,7 @@ export class RdDCalendrier extends Application {
resizable: false, resizable: false,
width: 'fit-content', width: 'fit-content',
height: 'fit-content', height: 'fit-content',
}); }, { inplace: false })
} }
constructor() { constructor() {
@ -51,7 +51,6 @@ export class RdDCalendrier extends Application {
this.timestamp = RdDTimestamp.getWorldTime(); this.timestamp = RdDTimestamp.getWorldTime();
if (Misc.isUniqueConnectedGM()) { // Uniquement si GM if (Misc.isUniqueConnectedGM()) { // Uniquement si GM
RdDTimestamp.setWorldTime(this.timestamp); RdDTimestamp.setWorldTime(this.timestamp);
this.nombresAstraux = this.getNombresAstraux();
this.rebuildNombresAstraux(); // Ensure always up-to-date this.rebuildNombresAstraux(); // Ensure always up-to-date
} }
Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id)); Hooks.on('updateSetting', async (setting, update, options, id) => this.onUpdateSetting(setting, update, options, id));
@ -108,7 +107,10 @@ export class RdDCalendrier extends Application {
this.timestamp = RdDTimestamp.getWorldTime(); this.timestamp = RdDTimestamp.getWorldTime();
this.positionAiguilles() this.positionAiguilles()
this.render(false); this.render(false);
Hooks.callAll(APP_ASTROLOGIE_REFRESH); Hooks.callAll(APP_ASTROLOGIE_REFRESH)
}
if (setting.key == SYSTEM_RDD + '.' + "liste-nombre-astral") {
Hooks.callAll(APP_ASTROLOGIE_REFRESH)
} }
} }
@ -121,9 +123,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;
} }
@ -167,7 +169,11 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
getNombresAstraux() { getNombresAstraux() {
return game.settings.get(SYSTEM_RDD, "liste-nombre-astral") ?? []; return game.settings.get(SYSTEM_RDD, "liste-nombre-astral") ?? []
}
async setNombresAstraux(nombresAstraux) {
await game.settings.set(SYSTEM_RDD, "liste-nombre-astral", nombresAstraux)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -225,20 +231,15 @@ export class RdDCalendrier extends Application {
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: HIDE_DICE, rollMode: "selfroll" }); const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: HIDE_DICE, rollMode: "selfroll" });
return { return {
nombreAstral: nombreAstral, nombreAstral: nombreAstral,
valeursFausses: [], lectures: [],
index: indexDate index: indexDate
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
resetNombresAstraux() { async resetNombresAstraux() {
this.nombresAstraux = []; await Promise.all(game.actors.filter(it => it.type == "personnage").map(async it => await it.deleteNombresAstraux()))
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", []); await this.setNombresAstraux([])
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_reset_nombre_astral",
data: {}
});
} }
/** /**
@ -251,39 +252,30 @@ export class RdDCalendrier extends Application {
if (indexDate == undefined) { if (indexDate == undefined) {
indexDate = this.timestamp.indexDate; indexDate = this.timestamp.indexDate;
} }
this.nombresAstraux = this.getNombresAstraux(); const nombresAstraux = this.getNombresAstraux()
let astralData = this.nombresAstraux.find((nombreAstral, i) => nombreAstral.index == indexDate); let astralData = nombresAstraux.find(it => it.index == indexDate);
return astralData?.nombreAstral ?? 0; return astralData?.nombreAstral ?? 0;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rebuildNombresAstraux() { async rebuildNombresAstraux() {
if (Misc.isUniqueConnectedGM()) { if (Misc.isUniqueConnectedGM()) {
let newList = []; const nombresAstraux = this.getNombresAstraux()
let newNombresAstraux = [];
for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) { for (let i = 0; i < MAX_NOMBRE_ASTRAL; i++) {
let dayIndex = this.timestamp.indexDate + i; let dayIndex = this.timestamp.indexDate + i;
let na = this.nombresAstraux.find(n => n.index == dayIndex); let na = nombresAstraux.find(it => it.index == dayIndex);
if (na) { if (na) {
newList[i] = na; newNombresAstraux[i] = na;
} else { } else {
newList[i] = await this.ajouterNombreAstral(dayIndex); newNombresAstraux[i] = await this.ajouterNombreAstral(dayIndex);
} }
} }
this.nombresAstraux = newList;
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", newList);
game.actors.filter(it => it.isPersonnage()).forEach(actor => actor.supprimerAnciensNombresAstraux()); game.actors.filter(it => it.isPersonnage()).forEach(actor => actor.supprimerAnciensNombresAstraux());
this.notifyChangeNombresAstraux(); await this.setNombresAstraux(newNombresAstraux);
} }
} }
notifyChangeNombresAstraux() {
Hooks.callAll(APP_ASTROLOGIE_REFRESH);
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_refresh_nombre_astral",
data: {}
});
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async setNewTimestamp(newTimestamp) { async setNewTimestamp(newTimestamp) {
const oldTimestamp = this.timestamp; const oldTimestamp = this.timestamp;
@ -373,25 +365,22 @@ export class RdDCalendrier extends Application {
request.nbAstral = await RdDDice.rollTotal("1dhr" + request.nbAstral, { request.nbAstral = await RdDDice.rollTotal("1dhr" + request.nbAstral, {
rollMode: "selfroll", showDice: HIDE_DICE rollMode: "selfroll", showDice: HIDE_DICE
}); });
// Mise à jour des nombres astraux du joueur
this.addNbAstralIncorect(request.id, request.date, request.nbAstral);
}
if (Misc.getActiveUser(request.userId)?.isGM) {
RdDUtility.responseNombreAstral(request);
} else {
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_response_nombre_astral",
data: request
});
} }
// Mise à jour des nombres astraux du joueur
await this.addNbAstralJoueur(actor, request.date, request.nbAstral, request.isValid)
Hooks.callAll(APP_ASTROLOGIE_REFRESH)
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_app_astrologie_refresh", data: {} })
} }
} }
addNbAstralIncorect(actorId, date, nbAstral) { async addNbAstralJoueur(actor, date, nbAstral, isValid) {
const astralData = this.nombresAstraux.find((nombreAstral, i) => nombreAstral.index == date); const nombresAstraux = this.getNombresAstraux()
astralData.valeursFausses.push({ actorId: actorId, nombreAstral: nbAstral }); const astralData = nombresAstraux.find(it => it.index == date)
game.settings.set(SYSTEM_RDD, "liste-nombre-astral", this.nombresAstraux); if (astralData) {
astralData.lectures.push({ actorId: actor.id, nombreAstral: nbAstral });
await this.setNombresAstraux(nombresAstraux);
await actor.ajouteNombreAstral(date, nbAstral, isValid);
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -202,7 +202,7 @@ export class RdDTimestamp {
} }
static setWorldTime(timestamp) { static setWorldTime(timestamp) {
game.settings.set(SYSTEM_RDD, WORLD_TIMESTAMP_SETTING, duplicate(timestamp)); game.settings.set(SYSTEM_RDD, WORLD_TIMESTAMP_SETTING, foundry.utils.duplicate(timestamp));
} }
/** construit un RdDTimestamp à partir de l'année/mois/jour/heure?/minute? */ /** construit un RdDTimestamp à partir de l'année/mois/jour/heure?/minute? */
@ -231,6 +231,7 @@ export class RdDTimestamp {
get annee() { return Math.floor(this.indexDate / RDD_JOURS_PAR_AN) } get annee() { return Math.floor(this.indexDate / RDD_JOURS_PAR_AN) }
get mois() { return Math.floor(Misc.modulo(this.indexDate, RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) } get mois() { return Math.floor(Misc.modulo(this.indexDate, RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) }
get nomMois() { return Math.floor(Misc.modulo(this.indexDate, RDD_JOURS_PAR_AN) / RDD_JOURS_PAR_MOIS) }
get jour() { return Misc.modulo(Misc.modulo(this.indexDate, RDD_JOURS_PAR_AN), RDD_JOURS_PAR_MOIS) } get jour() { return Misc.modulo(Misc.modulo(this.indexDate, RDD_JOURS_PAR_AN), RDD_JOURS_PAR_MOIS) }
get heure() { return Math.floor(this.indexMinute / RDD_MINUTES_PAR_HEURES) } get heure() { return Math.floor(this.indexMinute / RDD_MINUTES_PAR_HEURES) }
get minute() { return Misc.modulo(this.indexMinute, RDD_MINUTES_PAR_HEURES) } get minute() { return Misc.modulo(this.indexMinute, RDD_MINUTES_PAR_HEURES) }

View File

@ -125,7 +125,7 @@ export class FenetreRechercheTirage extends Application {
popOut: true, popOut: true,
dragDrop: [{ dragSelector: "a.content-link" }], dragDrop: [{ dragSelector: "a.content-link" }],
resizable: true resizable: true
}); }, { inplace: false })
} }
static async create() { static async create() {
@ -133,7 +133,7 @@ export class FenetreRechercheTirage extends Application {
const parameters = { const parameters = {
milieux: milieux, milieux: milieux,
filterMilieux: $filterMilieux(milieux), filterMilieux: $filterMilieux(milieux),
filterGroups: duplicate(FILTER_GROUPS).filter(it => it.group), filterGroups: foundry.utils.duplicate(FILTER_GROUPS).filter(it => it.group),
} }
const options = {} const options = {}
$loadFilters(parameters); $loadFilters(parameters);

View File

@ -16,7 +16,7 @@ export class Rencontre extends Draconique {
return pixiTMR.sprite(this.code(), { return pixiTMR.sprite(this.code(), {
zIndex: tmrTokenZIndex.rencontre, zIndex: tmrTokenZIndex.rencontre,
decallage: pixiTMR.sizes.decallage(0, 0), decallage: pixiTMR.sizes.decallage(0, 0),
taille: () => pixiTMR.sizes.twoThird, taille: () => pixiTMR.sizes.full,
}) })
} }
} }

View File

@ -1,6 +1,7 @@
import { TYPES } from "../item.js" import { 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[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,44 +154,61 @@ 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)
) .forEach(async it => {
actors.filter(it => it.selected)
.forEach(async it => {
const perteFatigue = fatigueBase + it.ajustement const perteFatigue = fatigueBase + it.ajustement
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(it.actor.name), whisper: ChatUtility.getWhisperRecipientsAndGMs(it.actor.name),
content: await renderTemplate( content: await renderTemplate(
'systems/foundryvtt-reve-de-dragon/templates/voyage/chat-fatigue_voyage.hbs', foundry.utils.mergeObject(it, 'systems/foundryvtt-reve-de-dragon/templates/voyage/chat-fatigue_voyage.hbs',
foundry.utils.mergeObject(it,
{ {
parameters: this.parameters, parameters: this.parameters,
fatigueBase: fatigueBase, fatigueBase: fatigueBase,
perteFatigue: perteFatigue, perteFatigue: perteFatigue,
isVoyage: fatigueBase == this.parameters.nombreHeures * this.parameters.fatigueHoraire isVoyage: fatigueBase == this.parameters.nombreHeures * this.parameters.fatigueHoraire
}) }, { inplace: false })
), ),
}) })
await it.actor.santeIncDec("fatigue", perteFatigue) await it.actor.santeIncDec("fatigue", perteFatigue)
}) })
} }
$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() {

View File

@ -92,6 +92,8 @@
--background-custom-button-hover: linear-gradient(to bottom, rgb(128, 0, 0) 5%, rgb(62, 1, 1) 100%); --background-custom-button-hover: linear-gradient(to bottom, rgb(128, 0, 0) 5%, rgb(62, 1, 1) 100%);
--background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%); --background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%);
--background-tooltip: hsla(60, 12%, 85%, 0.95); --background-tooltip: hsla(60, 12%, 85%, 0.95);
--color-tooltip:hsla(282, 47%, 33%, 0.9);
--color-tooltip-faint:hsla(282, 47%, 66%, 0.5);
--background-error:hsla(16, 100%, 50%, 0.8); --background-error:hsla(16, 100%, 50%, 0.8);
--color-profile-border: hsla(0, 0%, 80%, 0.05); --color-profile-border: hsla(0, 0%, 80%, 0.05);
} }
@ -1372,7 +1374,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;
@ -1525,6 +1527,11 @@ div.control-icon.token-hud-icon {
font-size: 1rem; font-size: 1rem;
} }
.chat-message header.message-header .heure-rdd {
font-size: 0.7rem;
flex-grow: 3;
}
.chat-message.whisper { .chat-message.whisper {
background: rgba(220,220,210,0.75); background: rgba(220,220,210,0.75);
border: 2px solid #545469; border: 2px solid #545469;
@ -1943,7 +1950,7 @@ div.calendar-timestamp-edit select.calendar-signe-heure {
padding: 3px; padding: 3px;
} }
aside#tooltip{ aside#tooltip {
background: var(--background-tooltip); background: var(--background-tooltip);
color: var(--color-text-dark-primary); color: var(--color-text-dark-primary);
font-size: 1rem; font-size: 1rem;
@ -1951,6 +1958,15 @@ aside#tooltip{
padding: 0.4rem; padding: 0.4rem;
} }
aside#tooltip span.reference {
color: var(--color-tooltip);
border: 1px solid var(--color-tooltip-faint);
}
aside#tooltip .toolclip p.faint {
color: var(--color-tooltip-faint);
}
.tooltip :is(.ttt-xp,.ttt-levelup) { .tooltip :is(.ttt-xp,.ttt-levelup) {
width: 250px; width: 250px;
background: var(--background-tooltip) !important; background: var(--background-tooltip) !important;

View File

@ -1,13 +1,13 @@
{ {
"id": "foundryvtt-reve-de-dragon", "id": "foundryvtt-reve-de-dragon",
"title": "Rêve de Dragon", "title": "Rêve de Dragon",
"version": "11.2.19", "version": "12.0.8",
"download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-11.2.19.zip", "download": "https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/archive/foundryvtt-reve-de-dragon-12.0.8.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": {
"minimum": "11", "minimum": "11",
"verified": "11" "verified": "12"
}, },
"description": "Rêve de Dragon RPG for FoundryVTT", "description": "Rêve de Dragon RPG for FoundryVTT",
"authors": [ "authors": [

View File

@ -55,9 +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">
{{#select system.compteurs.ethylisme.value}} {{selectOptions (RDD_CONFIG 'niveauEthylisme') selected=system.compteurs.ethylisme.value valueAttr="value" nameAttr="value" labelAttr="label"}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-niveau-ethylisme.html"}}
{{/select}}
</select> </select>
</li> </li>

View File

@ -2,20 +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}}>
{{#select system.definition.categorieentite}} {{selectOptions (RDD_CONFIG 'categorieEntite') selected=system.definition.categorieentite}}
<option value="cauchemar">Cauchemar</option>
<option value="reve">Rêve</option>
{{/select}}
</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}}>
{{#select system.definition.typeentite}} {{selectOptions (RDD_CONFIG 'typeEntite') selected=system.definition.typeentite}}
<option value="incarne">Incarnée</option>
<option value="nonincarne">Non Incarnée</option>
<option value="blurette">Blurette</option>
{{/select}}
</select> </select>
</li> </li>
{{#each system.attributs as |attr key|}} {{#each system.attributs as |attr key|}}

View File

@ -25,7 +25,7 @@
<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|}}

View File

@ -2,7 +2,7 @@
{{#if effects}} {{#if effects}}
{{#each effects as |effect key|}} {{#each effects as |effect key|}}
<span class="active-effect" data-effect="{{effect.id}}"> <span class="active-effect" data-effect="{{effect.id}}">
<img class="button-effect-img {{#if @root.options.isGM}}delete-active-effect{{/if}}" src="{{effect.icon}}" data-tooltip="{{localize effect.name}}" width="24" height="24" /> <img class="button-effect-img {{#if @root.options.isGM}}delete-active-effect{{/if}}" src="{{effect.img}}" data-tooltip="{{localize effect.name}}" width="24" height="24" />
</span> </span>
{{/each}} {{/each}}
{{#if calc.surprise}}<span>{{calc.surprise}}!</span>{{/if}} {{#if calc.surprise}}<span>{{calc.surprise}}!</span>{{/if}}

View File

@ -1,3 +1,4 @@
{{log 'chat-vente-item' this}}
<div class="post-item" data-transfer="{{transfer}}"> <div class="post-item" data-transfer="{{transfer}}">
<h3>{{#if alias}}{{alias}} propose: {{else}}Acheter {{/if}}{{item.name}}</h3> <h3>{{#if alias}}{{alias}} propose: {{else}}Acheter {{/if}}{{item.name}}</h3>
{{#if item.img}} {{#if item.img}}
@ -12,7 +13,7 @@
<hr> <hr>
<p> <p>
{{#unless quantiteIllimite}} {{#unless quantiteIllimite}}
<span>Lots disponibles: <span class="quantiteNbLots">{{quantiteNbLots}}</span></span><br> <span>Lots disponibles: {{nbLots}}</span><br>
{{/unless}} {{/unless}}
{{#if (gt tailleLot 1)}} {{#if (gt tailleLot 1)}}
<span>Lots de: <span class="tailleLot">{{tailleLot}}</span></span><br> <span>Lots de: <span class="tailleLot">{{tailleLot}}</span></span><br>
@ -22,15 +23,9 @@
<span class="prixLot">{{numberFormat prixLot decimals=2 sign=false}}</span> Sols</strong></span><br> <span class="prixLot">{{numberFormat prixLot decimals=2 sign=false}}</span> Sols</strong></span><br>
{{/if}} {{/if}}
</p> </p>
{{#if (or (gt quantiteNbLots 0) quantiteIllimite)}} {{#if (or (gt nbLots 0) quantiteIllimite)}}
<span class="chat-card-button-area"> <span class="chat-card-button-area">
<a class="button-acheter chat-card-button" <a class="button-acheter chat-card-button">
data-jsondata='{{jsondata}}'
{{#if vendeurId}}data-vendeurId='{{vendeurId}}'{{/if}}
data-tailleLot="{{tailleLot}}"
data-quantiteNbLots="{{quantiteNbLots}}"
data-quantiteIllimite="{{#if quantiteIllimite}}true{{else}}false{{/if}}"
data-prixLot="{{prixLot}}">
{{#if (eq prixLot 0)}}Prendre{{else}}Acheter{{/if}}</a> {{#if (eq prixLot 0)}}Prendre{{else}}Acheter{{/if}}</a>
</span> </span>
{{/if}} {{/if}}

View File

@ -1,22 +1,20 @@
<span draggable="true"> <span draggable="true">
{{#if pack}} <a class="{{#if pack}}content-link{{else}}rdd-world-content-link{{/if}}"
{{!-- draggable="true" --}} data-id="{{id}}"
<a class="content-link" data-link=""
{{#if doctype}}
data-doctype="{{doctype}}"
data-type="{{doctype}}"
{{/if}}
{{#if pack}}
data-pack="{{pack}}"
data-uuid="Compendium.{{pack}}.{{id}}" data-uuid="Compendium.{{pack}}.{{id}}"
data-pack="{{pack}}" {{/if}} >
{{#if doctype}}data-doctype="{{doctype}}"{{/if}} {{#if img}}
data-id="{{id}}" <img class="in-text-img" src="{{img}}" data-tooltip="{{name}}" />
> {{else}}
{{else}} <i class="fas fa-suitcase"></i>
<a class="rdd-world-content-link" {{/if}}
{{#if doctype}}data-doctype="{{doctype}}"{{/if}} {{name}}
data-id="{{id}}" </a>
>
{{/if}}
{{#if img}}
<img class="in-text-img" src="{{img}}" data-tooltip="{{name}}" />
{{else}}
<i class="fas fa-suitcase"></i>
{{/if}}
{{name}}</a>
</span> </span>

View File

@ -0,0 +1,3 @@
<span class="message-metadata heure-rdd">
{{this.jourDuMois}} {{this.mois.label}} - {{timestamp-imgSigne this.heure}}
</span>

View File

@ -2,8 +2,6 @@
<div class="flexrow"> <div class="flexrow">
<input type="number" name="{{path}}.nombre" value="{{nombre}}" data-dtype="Number"/> <input type="number" name="{{path}}.nombre" value="{{nombre}}" data-dtype="Number"/>
<select name="{{path}}.unite" data-dtype="String" > <select name="{{path}}.unite" data-dtype="String" >
{{#select unite}} {{selectOptions (timestamp-formulesPeriode) selected=unite labelAttr="label" nameAttr="code" valueAttr="code"}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-periode.html"}}
{{/select}}
</select> </select>
</div> </div>

View File

@ -6,9 +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 mois.key}} {{selectOptions (RDD_CONFIG 'heuresRdD') selected=mois.key labelAttr="label" nameAttr="value" valueAttr="value"}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-heures.html"}}
{{/select}}
</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"/>
@ -17,9 +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 heure.key}} {{selectOptions (RDD_CONFIG 'heuresRdD') selected=heure.key labelAttr="label" nameAttr="value" valueAttr="value"}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-heures.html"}}
{{/select}}
</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

@ -31,7 +31,7 @@
<label>{{#if quantiteIllimite}} <label>{{#if quantiteIllimite}}
pas de limite pas de limite
{{else}} {{else}}
{{quantiteNbLots}} {{nbLots}}
{{/if}}</label> {{/if}}</label>
</div> </div>
<div class="flexrow flex-group-left"> <div class="flexrow flex-group-left">
@ -41,7 +41,7 @@
</label> </label>
<div class="flexrow"> <div class="flexrow">
<input name="nombreLots" class="nombreLots flex-shrink number-x2" type="number" min="1" <input name="nombreLots" class="nombreLots flex-shrink number-x2" type="number" min="1"
{{#unless quantiteIllimite}} max="{{quantiteNbLots}}" {{/unless}} {{#unless quantiteIllimite}} max="{{nbLots}}" {{/unless}}
value="{{choix.nombreLots}}" value="{{choix.nombreLots}}"
data-dtype="Number" /> data-dtype="Number" />
</div> </div>

View File

@ -18,8 +18,8 @@
quantiteIllimite}}checked{{/if}} /> quantiteIllimite}}checked{{/if}} />
<label class="label-quantiteIllimite flex-shrink">disponibles</label> <label class="label-quantiteIllimite flex-shrink">disponibles</label>
{{/unless}} {{/unless}}
<input name="quantiteNbLots" class="quantiteNbLots flex-shrink number-x2" type="number" min="1" <input name="nbLots" class="nbLots flex-shrink number-x2" type="number" min="1"
max="{{quantiteMaxLots}}" value="{{quantiteNbLots}}" data-dtype="Number" /> max="{{maxLots}}" value="{{nbLots}}" data-dtype="Number" />
</div> </div>
</div> </div>
<div class="flexrow flex-group-left"> <div class="flexrow flex-group-left">

View File

@ -15,33 +15,36 @@
<label class="encaissement-total">{{encaissement.total}}</label> <label class="encaissement-total">{{encaissement.total}}</label>
<div class="tooltiptext ttt-ajustements"> <div class="tooltiptext ttt-ajustements">
<div>Armure: {{encaissement.armure}}</div> <div>Armure: {{encaissement.armure}}</div>
{{#if rollData.dmg.penetration}} {{#if encaissement.dmg.penetration}}
<div>Pénétration: -{{rollData.dmg.penetration}}</div> <div>Pénétration: -{{encaissement.dmg.penetration}}</div>
{{/if}} {{/if}}
<hr> <hr>
{{#if encaissement.dmg.total}} {{#if encaissement.dmg.total}}
<div>+dom encaissement: {{plusMoins rollData.dmg.total}}</div> <div>+dom encaissement: {{plusMoins encaissement.dmg.total}}</div>
{{/if}} {{/if}}
{{#if rollData.dmg.dmgArme}} {{#if encaissement.dmg.dmgArme}}
<div>+dom arme: {{plusMoins rollData.dmg.dmgArme}}</div> <div>+dom arme: {{plusMoins encaissement.dmg.dmgArme}}</div>
{{/if}} {{/if}}
{{#if rollData.dmg.dmgActor}} {{#if encaissement.dmg.dmgActor}}
<div>+dom attaquant: {{plusMoins rollData.dmg.dmgActor}}</div> <div>+dom attaquant: {{plusMoins encaissement.dmg.dmgActor}}</div>
{{/if}} {{/if}}
{{#if rollData.dmg.dmgParticuliere}} {{#if encaissement.dmg.dmgParticuliere}}
<div>+dom particulière: {{plusMoins rollData.dmg.dmgParticuliere}}</div> <div>+dom particulière: {{plusMoins encaissement.dmg.dmgParticuliere}}</div>
{{/if}} {{/if}}
{{#if rollData.dmg.dmgTactique}} {{#if encaissement.dmg.dmgTactique}}
<div>+dom tactique: {{plusMoins rollData.dmg.dmgTactique}}</div> <div>+dom tactique: {{plusMoins encaissement.dmg.dmgTactique}}</div>
{{/if}} {{/if}}
{{#if rollData.dmg.dmgSurprise}} {{#if encaissement.dmg.dmgSurprise}}
<div>+dom surprise: {{plusMoins rollData.dmg.dmgSurprise}}</div> <div>+dom surprise: {{plusMoins encaissement.dmg.dmgSurprise}}</div>
{{/if}}
{{#if encaissement.dmg.bonusDegatsDiffLibre}}
<div>+dom attaque: {{plusMoins encaissement.dmg.bonusDegatsDiffLibre}}</div>
{{/if}} {{/if}}
</div> </div>
</span> </span>
</li> </li>
<li class="flexrow flex-group-left"> <li class="flexrow flex-group-left">
<label>Blessure ({{rollData.dmg.mortalite}})</label> <label>Blessure ({{encaissement.dmg.mortalite}})</label>
<label class="encaissement-blessure">{{encaissement.blessures}}</label> <label class="encaissement-blessure">{{encaissement.blessures}}</label>
</li> </li>
</ul> </ul>

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,9 +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">
{{#select env.rarete}} {{selectOptions (RDD_CONFIG 'raretes') selected=env.rarete labelAttr="label" valueAttr="value" nameAttr="value"}}
{{>"systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html"}}
{{/select}}
</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

@ -7,7 +7,7 @@
{{else}} {{else}}
<input class="resource-content select-effect" type="checkbox" name="{{effect.id}}" {{#if effect.active}}checked{{/if}}/> <input class="resource-content select-effect" type="checkbox" name="{{effect.id}}" {{#if effect.active}}checked{{/if}}/>
{{/if}} {{/if}}
<img class="button-effect-img" height="16" width="16" src="{{effect.icon}}" data-tooltip="{{localize effect.name}}" /> <img class="button-effect-img" height="16" width="16" src="{{effect.img}}" data-tooltip="{{localize effect.name}}" />
<label>{{localize effect.name}}</label> <label>{{localize effect.name}}</label>
</li> </li>
{{/each}} {{/each}}

View File

@ -3,7 +3,7 @@
{{#each systemCompendiums as |definition key|}} {{#each systemCompendiums as |definition key|}}
<li class="flexrow"> <li class="flexrow">
<label>{{definition.label}}</label> <label>{{definition.label}}</label>
<select data-dtype="String" class="system-compendium-setting flex-grow-2" data-compendium="{{definition.compendium}}" > <select data-dtype="String" class="system-compendium-setting flex-grow-2" data-compendium="{{definition.compendium}}" >
{{#select definition.value}} {{#select definition.value}}
{{#each @root.availableCompendiums as |available key|}} {{#each @root.availableCompendiums as |available key|}}
{{#if (eq available.type definition.type)}} {{#if (eq available.type definition.type)}}

View File

@ -15,8 +15,8 @@
<td class="nombre-astral" data-nombre-astral="{{nba.nombreAstral}}"> <td class="nombre-astral" data-nombre-astral="{{nba.nombreAstral}}">
<ol> <ol>
<b>{{nba.nombreAstral}}</b> <b>{{nba.nombreAstral}}</b>
{{#each nba.valeursFausses as |fausse|}} {{#each nba.lectures as |lecture|}}
<li>{{fausse.actorName}} - {{fausse.nombreAstral}}</li> <li>{{lecture.actorName}} - {{lecture.nombreAstral}}</li>
{{/each}} {{/each}}
</ol> </ol>
</td> </td>

View File

@ -1,19 +1,11 @@
<div> <div>
<label>Conditions</label> <label>Conditions</label>
<select name="diffConditions" data-dtype="Number"> <select name="diffConditions" data-dtype="Number">
{{#select '0'}} {{selectOptions actorAstrologie.ajustements selected='0'}}
{{#each actorAstrologie.ajustements as |ajustement|}}
<option value={{ajustement}}>{{ajustement}}</option>
{{/each}}
{{/select}}
</select> </select>
<label>&nbsp;&nbsp;Jours</label> <label>&nbsp;&nbsp;Jours</label>
<select name="joursAstrologie" data-dtype="Number"> <select name="joursAstrologie" data-dtype="Number">
{{#select ''}} {{selectOptions dates selected='' labelAttr='label' valueAttr='index' nameAttr='index'}}
{{#each dates as |date|}}
<option value={{date.index}}>{{date.label}}</option>
{{/each}}
{{/select}}
</select> </select>
<label> <label>
&nbsp;&nbsp;Etat Général: {{actorAstrologie.etat}} &nbsp;&nbsp;Etat Général: {{actorAstrologie.etat}}

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>