Compare commits

...

62 Commits

Author SHA1 Message Date
93b74574ad pas de stress/sommeil pour personnage non lié
All checks were successful
Release Creation / build (release) Successful in 1m32s
2026-05-29 01:53:35 +02:00
1765cb2ef9 Mode de visibilité des jets 2026-05-29 01:53:35 +02:00
0cbd7a6deb Merge pull request '13.0.39 - La défense d'Illisys' (#806) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 1m1s
Reviewed-on: https, #806
2026-05-10 15:06:35 +02:00
aec4364889 Type de jet: Jet de résistance 2026-05-09 23:14:28 +02:00
f17996b1c8 Difficultés attaque/défense sur appel à la chance 2026-05-09 22:41:47 +02:00
14a4b34bbd Correction jets de compétence des invocations 2026-05-09 22:41:02 +02:00
1777eced30 Correction des catégories de parades 2026-05-09 21:42:09 +02:00
9bdda32d54 Merge pull request 'Set version changelog 13.0.38' (#805) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 2m29s
Reviewed-on: https, #805
2026-05-05 23:55:45 +02:00
3fe53d7ff0 Set version changelog 13.0.38 2026-05-05 23:55:16 +02:00
c839d4633d Merge pull request '## 13.0.37 - L'urgence d'Illisys' (#804) from feature/v13-corrections into v13
Reviewed-on: https, #804
2026-05-05 23:54:19 +02:00
24753bfc29 Appel chance RollDialogV2 2026-05-05 23:51:04 +02:00
e7acb0c4f2 Fix v14 Dés dice-so-nice 2026-05-05 21:51:01 +02:00
7535e5f340 Fix v14: /roll dans le tchat 2026-05-05 21:48:24 +02:00
d2326e5a25 Fix: liste des actions disponibles
- ajout du haut-rêve
- possibilité de ne lister que les armes équipées
2026-05-05 02:12:48 +02:00
e2afc24601 Message en cas d'erreur de migration 2026-05-02 16:46:25 +02:00
f220e3a394 Merge pull request 'Version 13.0.37' (#803) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 1m28s
Reviewed-on: https, #803
2026-05-02 16:37:40 +02:00
1d9348b701 Version 13.0.37 2026-05-02 16:36:51 +02:00
d96dff988e Merge pull request 'isNewerVersion' (#802) from feature/v13-corrections into v13
Reviewed-on: https, #802
2026-05-02 16:35:21 +02:00
9966a33524 Correction Migration avec Foundry14
Accès à méthode isNewerVersion à travers foundry.utils
2026-05-02 16:32:19 +02:00
7fb0ee1659 await ChatMessage.create
ChatMessage.create est async, il faut donc de préférence
l'appeler avec un await.

Des effets secondaires avaient lieu (ordre de messages, updates
ultérieurs parfois pas pris en compte)
2026-05-02 00:42:45 +02:00
d15d0989a3 Remise à zéro du refoulement après souffle 2026-05-01 23:56:17 +02:00
704c99e418 Correction: modification de coeurs 2026-05-01 23:38:05 +02:00
9ccc068333 Amélioration du moral
Les bon moments sont affichés en tooltips sur le moral

Simplification moralIncDec: Utilisation d'un seul update
2026-05-01 23:20:58 +02:00
6b0a6a268e Merge pull request '13.0.36 - Les rêveries d'Illisys' (#801) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 1m45s
Reviewed-on: https, #801
2026-04-30 18:25:47 +02:00
c7da930556 Boutons dans les listes d'équipement
Affichage amélioré en évitant les retours à la ligne
Meilleur affichage des -/+
2026-04-30 00:05:31 +02:00
e9e2eba9b5 Support v14: commandes dans chatMessage en html 2026-04-29 22:53:23 +02:00
423dcaf53e Cuisiner depuis l'équipement 2026-04-29 22:53:23 +02:00
a01086ff28 Amélioration champs input
- ajout de min et max quand utile
- ordre et regroupement des attributs:
   - préférence pour name en premier
   - regroupement de class/type/data-dtype
   - regroupement value/min/max
2026-04-29 22:53:22 +02:00
76e651cf19 Corrections mineures 2026-04-28 19:21:00 +02:00
eaee50511a Fix v14: attaque à distance 2026-04-28 19:10:38 +02:00
d1832917bc Message de dommage sur entité
Plutôt que de dire "ne subit aucun dommage", une gravité de blessure
indicative est donnée
2026-04-28 19:09:08 +02:00
277799088f Affichage des jeux 2026-04-28 19:07:24 +02:00
0398fbdbd1 Fix: Pas d'affichage de feuille sur encaissement 2026-04-28 19:07:00 +02:00
4faa9b6b54 Merge pull request 'Quelques corrections mineures' (#800) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 1m40s
Reviewed-on: https, #800
2026-04-26 22:38:40 +02:00
43a09f3a99 Compatibilité v14 2026-04-26 22:37:49 +02:00
ec8fc795f4 Affichage état & blessures
Les icônes d'effets sont affichées en premier.

Affichage des contusions. Les blessures sont affichées en
dernier, par gravité décroissante
2026-04-26 22:37:49 +02:00
8b46ea3681 Ajout de tokens de créatures 2026-04-26 22:37:49 +02:00
3ce33eeea3 simplification pre-update checkCompetence 2026-04-26 22:37:48 +02:00
5c4292882f Correction des updates multiples
Utilisation d'un render sur timer pour forcer le réaffichage
2026-04-26 22:37:48 +02:00
fb150753e0 Suppression image de fond "players"
Adaptation theme Foundry v13
2026-04-26 22:37:48 +02:00
fa54865369 Amélioration des tirages
- option pour ne pas afficher la table source
- les tirages de rencontres sont entre joueur et MJ
2026-04-26 22:37:48 +02:00
200e35b7b7 Filtrage des actions des items des commerces 2026-04-26 22:37:48 +02:00
76fb385c69 Visibilité des tirages dans le compendium
Les tirages de queues, têtes, ... ne concernent plus tout le monde,
mais le joueur et le MJ
2026-04-26 22:37:48 +02:00
ef30e76449 Fix: recul contre entité de cauchemar 2026-04-26 22:37:47 +02:00
10aba8bd58 Fix: sortie d'objet de conteneur 2026-04-26 22:37:47 +02:00
0aedff9d4b Merge pull request 'v13.0.34 - La saumuche d'Illysis' (#799) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 2m2s
Reviewed-on: https, #799
2026-04-07 19:23:26 +02:00
6062d0428c Fix: difficulté d'annulation de magie 2026-04-03 22:16:50 +02:00
eebca509bd Fix: affichage appel moral sur sorts 2026-04-03 22:16:50 +02:00
9934fe9191 Le pluriel de jeu est jeux 2026-04-03 22:16:50 +02:00
e6c4f7990a Correction: qualité des improvisations de cuisine 2026-04-03 22:16:50 +02:00
956fecdd82 Demi-rêve masqué, masquer les rencontres
Pour éviter de trahir l'emplacement du demi-rêve...
2026-04-03 22:16:50 +02:00
afcd200913 Merge pull request 'v13.0.33 - L'ébriété d'Illysis' (#798) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 1m31s
Reviewed-on: https, #798
2026-03-26 23:11:26 +01:00
f3e7cc38a7 Message de Vaisseau 2026-03-24 20:45:54 +01:00
bcc1ec6a37 Pas de perte d'endurance quand éméché 2026-03-24 20:45:54 +01:00
4141eeaa4a Cleanup: gererExperience=>ajoutExperience 2026-03-24 20:45:54 +01:00
d80efba092 Corrections relecture IA 2026-03-24 20:45:54 +01:00
a768419029 Merge pull request '## 13.0.32 - Le surpoids d'Illysis' (#797) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 2m42s
Reviewed-on: https, #797
2026-03-09 09:47:19 +01:00
dfc73fb96d Fix: affichage blessures et pertes
Les pertes et la récupération sont correctement gérées (en ne
faisant qu'un seul render pour le personnage)
2026-03-07 20:38:28 +01:00
9bb9a3b0eb Icône "sonné" inline dans le tchat 2026-03-07 20:38:28 +01:00
3f014faf02 Pas de perte endurance blessures graves soignées 2026-03-07 20:38:12 +01:00
6f30913a8f Visibilité ajustement conditions 2026-03-07 20:38:11 +01:00
b326484797 Fix: malus encombrement 2026-03-07 20:38:11 +01:00
239 changed files with 2093 additions and 1669 deletions

View File

@@ -1,5 +1,74 @@
# 13.0 # 13.0
## 13.0.40 - Le miroir d'Illisys
- les mode de visibilité des jets sont bien pris en compte
- pas de stress ou de sommeil pour les personnage non liés
## 13.0.39 - La défense d'Illisys
- mise à jour de version foundry-cli
- correction des catégories de parades des compendiums
- des ne pouvaient pas parer (exemple: le bouclier du guerrier sorde)
- les difficultés des jets d'attaque/défense après appel à la chance sont conservées
- L'absence des compétences cuisine/jeu ne bloque plus l'accès à la fenêtre de jets (cas des invocations)
## 13.0.38 - L'urgence d'Illisys
- Corrections v14
- on peut utiliser les commandes foundry dans le tchat (par exemple, /roll 1d6)
- les dés customisés Dice-So-Nice (heure, rencontres, dé draconique) fonctionnent
- Le Haut-rêve est de nouveau proposé dans les options d'initiative
- Nouvelle règle optionnelle: choisir si seules les armes équipées sont proposées en combat
- L'appel à la chance utilise la nouvelle fenêtre de jet de dés
## 13.0.37 - Le bonheur des zyglutes d'Illisys
- Corrections v14
- correction du problème liè à Foundry 14 qui peut empêcher d'utiliser les fenêtres de jets à cause de migrations mal effectuées
- Les bon moments sont affichés en tooltip sur le moral
- Les modifications de coeurs fonctionnent de nouveau
- Le refoulement est remis à zéro après avoir refoulé et reçu un souffle
## 13.0.36 - Les rêveries d'Illisys
- Corrections v14
- les attaques à distance n'empèchent plus la fenêtre d'attaque de s'ouvrir
- les commandes (/help, ...) fonctionnent en v14
- Les feuilles d'acteurs ne s'ouvrent plus lors d'un changement (par exemple en cas d'encaissement)
- Les jeux sont correctement affichés
- Ajout d'une gravité de blessure sur les encaissement d'entités
- Amélioration de champs numériques: ajout de min et max quand c'est utile
- correction pour cuisiner depuis l'équipement
- les boutons dans les listes d'équipement sont mieux affichés sans retour à la ligne
## 13.0.35 - Les travaux d'Illisys
- Correction du recul contre une entité de cauchemar (qui utilise le rêve comme force)
- Correction erreur lors de la suppression d'un objet d'un conteneur
- Meilleure gestion des messages publics/GM, en particulier pour les tirage dans les compendiums
- Filtrage des boutons pour les acteurs non personnages (pour éviter de faire manger l'auberge...)
## 13.0.34 - La saumuche d'Illysis
- la qualité des "improvisations du moment" se base sur le niveau du cuisinier
- l'appel au moral n'est pas affiché à l'ouverture d'une fenêtre de jets de sorts (ou de tâche intellectuelle)
- la difficulté variable de l'annulation de magie est bien prise en compte
- correction erreur lors de la suppression d'un objet d'un conteneur
## 13.0.33 - L'ébriété d'Illysis
- le stade éméché ne cause plus de perte d'endurance
## 13.0.32 - Le surpoids d'Illysis
- Le malus d'encombrement sur jet d'Agilité avec Natation ou Acrobatie peuvent être changés, et sont correctement arrondis
- L'ajustement de condition est plus visible sur les résultats de jets de dés
- Les blessures graves soignées ne font pas perdre d'endurance par round
- Les blessures et pertes correspondantes (vie, endurance, effets sonné, ...) s'affichent correctement
- la remise à neuf ne provoque pas d'erreur pour certains effets déjà supprimés
## 13.0.31 - Les choix multiples d'Illysis ## 13.0.31 - Les choix multiples d'Illysis
- les défauts de caractéristique/difficulté des compétences ne sont pris que si aucun autre choix n'est fait - les défauts de caractéristique/difficulté des compétences ne sont pris que si aucun autre choix n'est fait

View File

@@ -1120,49 +1120,27 @@ body {
text-align: left; text-align: left;
} }
.system-foundryvtt-reve-de-dragon .equipement-nom { .system-foundryvtt-reve-de-dragon .equipement-nom {
flex-grow: 3; flex-grow: 4;
flex-shrink: 2;
margin: 0; margin: 0;
justify-content: center;
text-align: left; text-align: left;
display: ruby; display: ruby;
} }
.system-foundryvtt-reve-de-dragon .equipement-valeur { .system-foundryvtt-reve-de-dragon .equipement-valeur {
margin: 0; margin: 0;
flex-grow: 1.5; flex-grow: 1;
flex-shrink: 1;
text-align: center; text-align: center;
} }
.system-foundryvtt-reve-de-dragon .equipement-detail { .system-foundryvtt-reve-de-dragon .equipement-detail {
margin: 0; margin: 0;
flex-grow: 1; flex-grow: 1;
align-items: center; flex-shrink: 1;
justify-content: center;
text-align: center;
}
.system-foundryvtt-reve-de-dragon span.equipement-detail-buttons {
margin: 0;
flex-grow: 1.5;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
text-align: center; text-align: center;
display: flex; display: flex;
flex-direction: row; min-width: max-content;
}
.system-foundryvtt-reve-de-dragon .equipement-button {
margin: 0;
flex-grow: 0.5;
align-items: center;
justify-content: center;
text-align: center;
}
.system-foundryvtt-reve-de-dragon :is(.item-actions-controls, .equipement-actions) {
margin: 0;
flex-grow: 1.2;
align-items: end;
justify-content: flex-end;
text-align: right;
}
.system-foundryvtt-reve-de-dragon .liste-equipement :is(.equipement-actions, .item-actions-controls) {
flex-grow: 2;
} }
.system-foundryvtt-reve-de-dragon .blessure-control { .system-foundryvtt-reve-de-dragon .blessure-control {
flex-grow: 1; flex-grow: 1;
@@ -1526,9 +1504,20 @@ body {
.system-foundryvtt-reve-de-dragon .competence-list .item-controls.hidden-controls { .system-foundryvtt-reve-de-dragon .competence-list .item-controls.hidden-controls {
display: none !important; display: none !important;
} }
.system-foundryvtt-reve-de-dragon .competence-header .item-actions-controls {
flex-shrink: 2;
flex-grow: 2;
}
.system-foundryvtt-reve-de-dragon .item-actions-controls, .system-foundryvtt-reve-de-dragon .item-actions-controls,
.system-foundryvtt-reve-de-dragon .item-controls { .system-foundryvtt-reve-de-dragon .item-controls {
vertical-align: super; margin: 0;
flex-grow: 1;
flex-shrink: 1;
align-items: end;
text-align: right;
min-width: max-content;
flex-basis: fit-content;
vertical-align: baseline;
} }
.system-foundryvtt-reve-de-dragon .item-actions-controls img, .system-foundryvtt-reve-de-dragon .item-actions-controls img,
.system-foundryvtt-reve-de-dragon .item-controls img { .system-foundryvtt-reve-de-dragon .item-controls img {
@@ -2379,8 +2368,9 @@ body {
} }
.system-foundryvtt-reve-de-dragon .chat-inline-icon { .system-foundryvtt-reve-de-dragon .chat-inline-icon {
border: 0; border: 0;
padding: 1px; padding: 0 0.2rem;
vertical-align: text-top; vertical-align: text-top;
display: inline;
} }
.system-foundryvtt-reve-de-dragon .actor-img-small { .system-foundryvtt-reve-de-dragon .actor-img-small {
max-width: 1.5rem; max-width: 1.5rem;
@@ -2498,12 +2488,6 @@ body {
background: #1e1914; background: #1e1914;
border: 1px solid #482e1c; border: 1px solid #482e1c;
} }
.system-foundryvtt-reve-de-dragon #players {
border-image: url(../assets/ui/footer-button.webp) 10 repeat;
border-image-width: 4px;
border-image-outset: 0px;
background: #1e1914;
}
.system-foundryvtt-reve-de-dragon #navigation #scene-list .scene.nav-item.active { .system-foundryvtt-reve-de-dragon #navigation #scene-list .scene.nav-item.active {
background: #482e1c; background: #482e1c;
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 136 KiB

BIN
icons/creatures/glou_t.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 177 KiB

View File

@@ -1,5 +1,6 @@
<h3>Joyeuses fêtes</h3> <h3>L'oeuf de Dragon</h3>
<p> <p>
VincentVK, LeRatierBretonnien et toute l'équipe de Scriptrarium vous On raconte que si le premier Vaisseau, on trouve un oeuf couvé par
souhaitent de joyeuses et oniriques fêtes ! un lapin, il faut bien s'occuper dudit lapin, car quatre mois plus tard
pourrait bien éclore un dragon!
</p> </p>

View File

@@ -393,49 +393,27 @@
text-align: left; text-align: left;
} }
.equipement-nom { .equipement-nom {
flex-grow: 3; flex-grow: 4;
flex-shrink: 2;
margin: 0; margin: 0;
justify-content: center;
text-align: left; text-align: left;
display: ruby; display: ruby;
} }
.equipement-valeur { .equipement-valeur {
margin: 0; margin: 0;
flex-grow: 1.5; flex-grow: 1;
flex-shrink: 1;
text-align: center; text-align: center;
} }
.equipement-detail { .equipement-detail {
margin: 0; margin: 0;
flex-grow: 1; flex-grow: 1;
align-items: center; flex-shrink: 1;
justify-content: center;
text-align: center;
}
span.equipement-detail-buttons {
margin: 0;
flex-grow: 1.5;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
text-align: center; text-align: center;
display: flex; display: flex;
flex-direction: row; min-width: max-content;
}
.equipement-button {
margin: 0;
flex-grow: 0.5;
align-items: center;
justify-content: center;
text-align: center;
}
:is(.item-actions-controls, .equipement-actions) {
margin: 0;
flex-grow: 1.2;
align-items: end;
justify-content: flex-end;
text-align: right;
}
.liste-equipement :is(.equipement-actions, .item-actions-controls) {
flex-grow: 2;
} }
.blessure-control { .blessure-control {
@@ -848,12 +826,20 @@
.competence-list .item-controls.hidden-controls { .competence-list .item-controls.hidden-controls {
display: none !important; display: none !important;
} }
.competence-header .item-actions-controls{
flex-shrink: 2;
flex-grow: 2;
}
.item-actions-controls, .item-actions-controls,
.item-controls { .item-controls {
vertical-align: super; margin: 0;
// a { flex-grow: 1;
// } flex-shrink: 1;
align-items: end;
text-align: right;
min-width: max-content;
flex-basis: fit-content;
vertical-align: baseline;
img { img {
vertical-align: text-bottom; vertical-align: text-bottom;
display: inline; display: inline;
@@ -1776,8 +1762,9 @@
} }
.chat-inline-icon { .chat-inline-icon {
border: 0; border: 0;
padding: 1px; padding: 0 0.2rem;
vertical-align: text-top; vertical-align: text-top;
display: inline;
} }
.actor-img-small { .actor-img-small {
@@ -1911,13 +1898,6 @@
border: 1px solid rgba(72, 46, 28, 1); border: 1px solid rgba(72, 46, 28, 1);
} }
#players {
border-image: url(../assets/ui/footer-button.webp) 10 repeat;
border-image-width: 4px;
border-image-outset: 0px;
background: rgba(30, 25, 20, 1);
}
#navigation #scene-list .scene.nav-item.active { #navigation #scene-list .scene.nav-item.active {
background: rgba(72, 46, 28, 1); background: rgba(72, 46, 28, 1);
} }

View File

@@ -51,7 +51,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
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)).label, surprise: RdDBonus.find(this.actor.getSurprise(false)).label,
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures), blessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute), caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
caracTotalXp: RdDCarac.computeTotalXp(this.actor.system.carac, this.actor.system.beaute), caracTotalXp: RdDCarac.computeTotalXp(this.actor.system.carac, this.actor.system.beaute),
surEncombrementMessage: this.actor.isSurenc() ? "Sur-Encombrement!" : "", surEncombrementMessage: this.actor.isSurenc() ? "Sur-Encombrement!" : "",
@@ -216,7 +216,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
// Points de reve actuel // Points de reve actuel
this.html.find('.roll-reve-actuel').click(async event => await this.actor.rollReveActuel({ resistance: false })) this.html.find('.roll-reve-actuel').click(async event => await this.actor.rollReveActuel({ resistance: false }))
this.html.find('.button-reve-resistance').click(async event => await this.actor.rollReveActuel({ diff: -8, resistance: true })) this.html.find('.button-reve-resistance').click(async event => await this.actor.rollReveResistance())
this.html.find('.action-empoignade').click(async event => await RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor))) this.html.find('.action-empoignade').click(async event => await RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor)))
this.html.find('.roll-arme').click(async event => { this.html.find('.roll-arme').click(async event => {
@@ -279,7 +279,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
// On pts de reve change // On pts de reve change
this.html.find('.pointsreve-value').change(async event => await this.actor.update({ "system.reve.reve.value": event.currentTarget.value })) this.html.find('.pointsreve-value').change(async event => await this.actor.update({ "system.reve.reve.value": event.currentTarget.value }))
this.html.find('.seuil-reve-value').change(async event => await this.actor.setPointsDeSeuil(event.currentTarget.value)) this.html.find('.seuil-reve-value').change(async event => await this.actor.update({ "system.reve.seuil.value": event.currentTarget.value }))
this.html.find('.stress-test').click(async event => await this.actor.transformerStress()) this.html.find('.stress-test').click(async event => await this.actor.transformerStress())
this.html.find('.moral-malheureux').click(async event => await this.actor.jetDeMoral(MORAL.MALHEUREUX)) this.html.find('.moral-malheureux').click(async event => await this.actor.jetDeMoral(MORAL.MALHEUREUX))

File diff suppressed because it is too large Load Diff

View File

@@ -26,9 +26,8 @@ import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES_CREATURES } fr
import { RollDataAjustements } from "../rolldata-ajustements-v1.js"; import { RollDataAjustements } from "../rolldata-ajustements-v1.js";
import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs"; import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs";
import RollDialog from "../roll/roll-dialog.mjs"; import RollDialog from "../roll/roll-dialog.mjs";
import { ATTAQUE_ROLL_TYPES, DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE } from "../roll/roll-constants.mjs"; import { DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP, ROLL_TYPE_REVE_RESISTANCE } from "../roll/roll-constants.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js"; import { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js";
import { PART_COMP } from "../roll/roll-part-comp.mjs";
import { RdDInitiative } from "../initiative.mjs"; import { RdDInitiative } from "../initiative.mjs";
import { RdDItemCompetenceCreature } from "../item-competencecreature.js"; import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs"; import { RdDPossessionV2 } from "../rdd-possession-v2.mjs";
@@ -145,7 +144,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
} }
listActions({ isAttaque = false, isEquipe = false }) { listActions() {
return this.itemTypes[ITEM_TYPES.competencecreature] return this.itemTypes[ITEM_TYPES.competencecreature]
.filter(it => it.isAttaque()) .filter(it => it.isAttaque())
.map(it => it.attaqueCreature()) .map(it => it.attaqueCreature())
@@ -154,11 +153,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
async computeArmure(dmg) { return this.getProtectionNaturelle() } async computeArmure(dmg) { return this.getProtectionNaturelle() }
async remiseANeuf() { } async remiseANeuf() { }
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { } async ajoutExperience(rollData, hideChatMessage = 'show') { }
computeResumeBlessure() { } computeResumeBlessure() { return [] }
countBlessures(filter = it => !it.isContusion()) { return 0 } countBlessures(filter = it => !it.isContusion()) { return 0 }
async santeIncDec(name, inc, isCritique = false) { } async santeIncDec(name, inc, isCritique) { }
async finDeRound(options = { terminer: false }) { async finDeRound(options = { terminer: false }) {
await this.finDeRoundSuppressionEffetsTermines(options) await this.finDeRoundSuppressionEffetsTermines(options)
@@ -169,10 +168,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
async finDeRoundSuppressionEffetsTermines(options) { async finDeRoundSuppressionEffetsTermines(options) {
for (let effect of this.getEffects()) { const effects = this.getEffects();
for (let effect of effects) {
if (effect.duration.type !== 'none' && (effect.duration.remaining <= 0 || options.terminer)) { if (effect.duration.type !== 'none' && (effect.duration.remaining <= 0 || options.terminer)) {
await effect.delete(); await effect.delete()
ChatMessage.create({ content: `${this.getAlias()} n'est plus ${Misc.lowerFirst(game.i18n.localize(effect.system.label))} !` }); await ChatMessage.create({ content: `${this.getAlias()} n'est plus ${Misc.lowerFirst(game.i18n.localize(effect.system.label))} !` })
} }
} }
} }
@@ -255,15 +255,15 @@ export class RdDBaseActorReve extends RdDBaseActor {
if (competence) { if (competence) {
function getFieldPath(fieldName) { function getFieldPath(fieldName) {
switch (fieldName) { switch (fieldName) {
case "niveau": return 'system.niveau'; case "niveau": return 'system.niveau'
case "dommages": return 'system.dommages'; case "dommages": return 'system.dommages'
case "carac_value": return 'system.carac_value'; case "carac_value": return 'system.carac_value'
} }
return undefined return undefined
} }
const path = getFieldPath(fieldName); const path = getFieldPath(fieldName)
if (path) { if (path) {
await competence.update({ [path]: value }); await competence.update({ [path]: value })
} }
} }
} }
@@ -295,7 +295,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
createCallbackExperience() { createCallbackExperience() {
return { action: r => this.appliquerAjoutExperience(r) } return { action: r => this.ajoutExperience(r) }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -304,7 +304,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
return { action: r => this.appliquerAppelMoral(r) } return { action: r => this.appliquerAppelMoral(r) }
} }
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { } async ajoutExperience(rollData, hideChatMessage = 'show') { }
async appliquerAppelMoral(rollData) { } async appliquerAppelMoral(rollData) { }
async _onCloseRollDialog(html) { } async _onCloseRollDialog(html) { }
@@ -316,7 +316,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
const competence = this.getCompetence(compName); const competence = this.getCompetence(compName);
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { allowed: DEFAULT_ROLL_TYPES, current: PART_COMP }, type: { allowed: DEFAULT_ROLL_TYPES, current: ROLL_TYPE_COMP },
selected: { selected: {
carac: { key: caracName }, carac: { key: caracName },
comp: { key: competence.name }, comp: { key: competence.name },
@@ -371,13 +371,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
RollDataAjustements.calcul(rollData, this); RollDataAjustements.calcul(rollData, this);
await RdDResolutionTable.rollData(rollData); await RdDResolutionTable.rollData(rollData);
this.gererExperience(rollData); this.ajoutExperience(rollData);
await RdDResolutionTable.displayRollData(rollData, this) await RdDResolutionTable.displayRollData(rollData, this)
return rollData.rolled; return rollData.rolled;
} }
gererExperience(rollData) { }
/* -------------------------------------------- */ /* -------------------------------------------- */
async roll() { async roll() {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
@@ -385,7 +383,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { type: {
allowed: DEFAULT_ROLL_TYPES, allowed: DEFAULT_ROLL_TYPES,
current: PART_COMP, current: ROLL_TYPE_COMP,
}, },
selected: { selected: {
diff: { type: DIFF.DEFAUT } diff: { type: DIFF.DEFAUT }
@@ -413,13 +411,33 @@ export class RdDBaseActorReve extends RdDBaseActor {
}) })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollReveResistance(diff = -8) {
return await RollDialog.create(
{
ids: { actorId: this.id },
type: {
allowed: [ROLL_TYPE_REVE_RESISTANCE],
current: ROLL_TYPE_REVE_RESISTANCE,
resistance: true
},
selected: {
carac: { key: CARACS.REVE_ACTUEL, forced: true },
comp: { key: undefined, forced: true },
diff: { type: DIFF.DEFAUT, value: diff }
}
},
{
onRollDone: (dialog, roll) => RollDialog.onRollDoneClose(dialog, roll)
})
}
async rollReveActuel({ diff = 0, resistance = false }) { async rollReveActuel({ diff = 0, resistance = false }) {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { type: {
allowed: [PART_COMP], allowed: [ROLL_TYPE_REVE_RESISTANCE],
current: PART_COMP, current: ROLL_TYPE_REVE_RESISTANCE,
resistance: resistance resistance: resistance
}, },
selected: { selected: {
@@ -441,8 +459,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { type: {
allowed: options.resistance ? [PART_COMP] : DEFAULT_ROLL_TYPES, allowed: options.resistance ? [ROLL_TYPE_COMP] : DEFAULT_ROLL_TYPES,
current: PART_COMP, current: options.resistance ? ROLL_TYPE_COMP : ROLL_TYPE_COMP,
resistance: options.resistance resistance: options.resistance
}, },
selected: { selected: {
@@ -617,7 +635,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
RdDPossessionV2.rollAttaquePossession(this) RdDPossessionV2.rollAttaquePossession(this)
} }
verifierForceMin(item) { } async verifierForceMin(item) { }
/* -------------------------------------------- */ /* -------------------------------------------- */
async encaisser() { await RdDEncaisser.encaisser(this) } async encaisser() { await RdDEncaisser.encaisser(this) }
@@ -656,36 +674,31 @@ export class RdDBaseActorReve extends RdDBaseActor {
jet => this.$onEncaissement(jet, show, attackerToken, defenderToken)); jet => this.$onEncaissement(jet, show, attackerToken, defenderToken));
} }
} }
async $onEncaissement(jet, show, attackerToken, defenderToken) {
await this.onAppliquerJetEncaissement(jet, attackerToken);
await this.$afficherEncaissement(jet, show, defenderToken);
}
async onAppliquerJetEncaissement(encaissement, attackerToken) { } async onAppliquerJetEncaissement(encaissement, attackerToken) { }
async $afficherEncaissement(encaissement, show, defenderToken) { async $onEncaissement(encaissement, show, attackerToken, defenderToken) {
await this.onAppliquerJetEncaissement(encaissement, attackerToken);
foundry.utils.mergeObject(encaissement, { foundry.utils.mergeObject(encaissement, {
alias: defenderToken?.name ?? this.getAlias(), alias: defenderToken?.name ?? this.getAlias(),
hasPlayerOwner: this.hasPlayerOwner, hasPlayerOwner: this.hasPlayerOwner,
show: show ?? {} show: show ?? {}
}, { overwrite: false }); }, { overwrite: false });
await ChatUtility.createChatWithRollMode( await ChatMessage.create(ChatUtility.adaptVisibility(
{ {
roll: encaissement.roll, roll: encaissement.roll,
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.hbs', encaissement) content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.hbs', encaissement)
}, },
this { actor: this }))
)
if (!encaissement.hasPlayerOwner && encaissement.endurance != 0) { if (!encaissement.hasPlayerOwner && encaissement.endurance != 0) {
encaissement = foundry.utils.duplicate(encaissement) encaissement = foundry.utils.duplicate(encaissement)
encaissement.isGM = true encaissement.isGM = true
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getGMs(), whisper: ChatUtility.getGMs(),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.hbs', encaissement) content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.hbs', encaissement)
}); })
} }
} }
@@ -732,7 +745,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-accorder-cauchemar.hbs') await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-accorder-cauchemar.hbs')
await this.appliquerAjoutExperience(rollData, true) await this.ajoutExperience(rollData, true)
return rolled.isSuccess; return rolled.isSuccess;
} }

View File

@@ -36,7 +36,7 @@ export class RdDBaseActorSangSheet extends RdDBaseActorReveSheet {
async jetEndurance() { async jetEndurance() {
const endurance = this.actor.getEnduranceActuelle() const endurance = this.actor.getEnduranceActuelle()
const result = await this.actor.jetEndurance(endurance); const result = await this.actor.jetEndurance(endurance);
ChatMessage.create({ await ChatMessage.create({
content: `Jet d'Endurance : ${result.jetEndurance} / ${endurance} content: `Jet d'Endurance : ${result.jetEndurance} / ${endurance}
<br>${this.actor.name} a ${result.sonne ? 'échoué' : 'réussi'} son Jet d'Endurance ${result.sonne ? 'et devient Sonné' : ''}`, <br>${this.actor.name} a ${result.sonne ? 'échoué' : 'réussi'} son Jet d'Endurance ${result.sonne ? 'et devient Sonné' : ''}`,
whisper: ChatUtility.getOwners(this.actor) whisper: ChatUtility.getOwners(this.actor)

View File

@@ -17,6 +17,14 @@ import { CARACS } from "../rdd-carac.js";
*/ */
export class RdDBaseActorSang extends RdDBaseActorReve { export class RdDBaseActorSang extends RdDBaseActorReve {
async _preUpdate(changed, options, user) {
const updatedEndurance = changed?.system?.sante?.endurance
if (updatedEndurance && options.diff) {
await this.setEffect(STATUSES.StatusUnconscious, updatedEndurance.value == 0)
}
}
prepareActorData() { prepareActorData() {
this.system.sante.vie.max = Math.ceil((this.getTaille() + this.getConstitution()) / 2) this.system.sante.vie.max = Math.ceil((this.getTaille() + this.getConstitution()) / 2)
this.system.sante.vie.value = Math.min(this.system.sante.vie.value, this.system.sante.vie.max) this.system.sante.vie.value = Math.min(this.system.sante.vie.value, this.system.sante.vie.max)
@@ -71,51 +79,64 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return Math.min(0, Math.floor(this.getEncombrementMax() - this.encTotal)); return Math.min(0, Math.floor(this.getEncombrementMax() - this.encTotal));
} }
countBlessures(filter) { return this.itemTypes[ITEM_TYPES.blessure].filter(filter).length }
isDead() { return this.system.sante.vie.value < -this.getSConst() } isDead() { return this.system.sante.vie.value < -this.getSConst() }
nbBlessuresLegeres() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isLegere()).length }
nbBlessuresGraves() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isGrave()).length }
nbBlessuresCritiques() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isCritique()).length }
/* -------------------------------------------- */ /* -------------------------------------------- */
computeResumeBlessure() { computeResumeBlessure() {
const nbLegeres = this.nbBlessuresLegeres() function descBlessure(count, name) {
const nbGraves = this.nbBlessuresGraves() return count > 0 ? [`${count} ${name}${count > 1 ? "s" : ""}`] : []
const nbCritiques = this.nbBlessuresCritiques() }
if (nbLegeres + nbGraves + nbCritiques == 0) { const nbContusions = this.countBlessures(it => it.isContusion())
return "Aucune blessure"; const nbLegeres = this.countBlessures(it => it.isLegere())
} const nbGraves = this.countBlessures(it => it.isGrave())
let resume = "Blessures:"; const nbCritiques = this.countBlessures(it => it.isCritique())
if (nbLegeres > 0) { return [
resume += " " + nbLegeres + " légère" + (nbLegeres > 1 ? "s" : ""); ... (nbCritiques > 0 ? ['une CRITIQUE !'] : []),
} ...descBlessure(nbGraves, 'grave'),
if (nbGraves > 0) { ...descBlessure(nbLegeres, 'légère'),
if (nbLegeres > 0) ...descBlessure(nbContusions, 'contusion'),
resume += ","; ]
resume += " " + nbGraves + " grave" + (nbGraves > 1 ? "s" : "");
}
if (nbCritiques > 0) {
if (nbGraves > 0 || nbLegeres > 0)
resume += ",";
resume += " une CRITIQUE !";
}
return resume;
} }
blessuresASoigner() { return [] } blessuresASoigner() { return [] }
async computeArmure(attackerRoll) { return this.getProtectionNaturelle() } async computeArmure(attackerRoll) { return this.getProtectionNaturelle() }
async remiseANeuf() { } async remiseANeuf() { }
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { } async ajoutExperience(rollData, hideChatMessage = 'show') { }
/* -------------------------------------------- */ /* -------------------------------------------- */
async onAppliquerJetEncaissement(encaissement, attackerToken) { async onAppliquerJetEncaissement(encaissement, attackerToken) {
const santeOrig = foundry.utils.duplicate(this.system.sante); const santeOrig = foundry.utils.duplicate(this.system.sante);
const blessure = await this.ajouterBlessure(encaissement, attackerToken); // Will update the result table const blessure = this.nouvelleBlessure(encaissement.gravite, {
const perteVie = await this.santeIncDec("vie", -encaissement.vie); localisation: encaissement.dmg?.loc.label ?? '',
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, blessure?.isCritique()); origine: attackerToken?.name ?? ''
})
if (blessure.system.gravite == encaissement.gravite) {
blessure.system.vie = encaissement.vie
blessure.system.endurance = encaissement.endurance
}
else { // aggravation du fait du nombre de blessures
blessure.system.vie = blessure.system.vie
const rollPerteEndurance = new Roll(blessure.system.endurance)
await rollPerteEndurance.evaluate()
blessure.system.endurance = rollPerteEndurance.total
}
const isCritique = blessure.system.gravite >= 6;
if (isCritique) {
blessure.system.endurance = this.getEnduranceActuelle()
}
// Will update the result table
if (blessure.system.gravite > 6) {
this.setEffect(STATUSES.StatusComma, true)
encaissement.mort = "à seconde blessure critique"
}
const perteVie = await this.santeIncDec("vie", -encaissement.vie)
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, isCritique)
await this.createEmbeddedDocuments('Item', [blessure])
foundry.utils.mergeObject(encaissement, { foundry.utils.mergeObject(encaissement, {
resteEndurance: perteEndurance.newValue, resteEndurance: perteEndurance.newValue,
@@ -124,7 +145,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
endurance: perteEndurance.perte, endurance: perteEndurance.perte,
vie: santeOrig.vie.value - perteVie.newValue, vie: santeOrig.vie.value - perteVie.newValue,
blessure: blessure blessure: blessure
}); })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -142,12 +163,13 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
let minValue = name == "vie" ? -this.getSConst() - 1 : 0; let minValue = name == "vie" ? -this.getSConst() - 1 : 0;
result.newValue = Math.max(minValue, Math.min(compteur.value + inc, compteur.max)); result.newValue = Math.max(minValue, Math.min(compteur.value + inc, compteur.max));
//console.log("New value ", inc, minValue, result.newValue);
let fatigue = 0; let fatigue = 0;
if (name == "endurance") { if (name == "endurance") {
if (result.newValue == 0 && inc < 0 && !isCritique) { // perte endurance et endurance devient 0 (sauf critique) -> -1 vie if (result.newValue == 0 && inc < 0 && !isCritique) {
sante.vie.value--; // perte endurance et endurance devient 0 (sauf critique) -> -1 vie
result.perteVie = true; sante.vie.value--
result.perteVie = true
} }
result.newValue = Math.max(0, result.newValue); result.newValue = Math.max(0, result.newValue);
if (inc > 0) { // le max d'endurance s'applique seulement à la récupération if (inc > 0) { // le max d'endurance s'applique seulement à la récupération
@@ -164,17 +186,17 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && sante.fatigue && fatigue > 0) { if (ReglesOptionnelles.isUsing("appliquer-fatigue") && sante.fatigue && fatigue > 0) {
sante.fatigue.value = Math.max(sante.fatigue.value + fatigue, this.getFatigueMin()); sante.fatigue.value = Math.max(sante.fatigue.value + fatigue, this.getFatigueMin());
} }
await this.update({ "system.sante": sante }, { render: true }) await this.update({ "system.sante": sante })
if (perteEndurance > 1) { if (perteEndurance > 1) {
// Peut-être sonné si 2 points d'endurance perdus d'un coup // Peut-être sonné si 2 points d'endurance perdus d'un coup
foundry.utils.mergeObject(result, await this.jetEndurance(result.newValue)); foundry.utils.mergeObject(result, await this.jetEndurance(result.newValue));
} else if (name == "endurance" && inc > 0) { } else if (name == "endurance" && inc > 0) {
await this.setSonne(false); await this.setSonne(false)
} }
if (this.isDead()) { if (this.isDead()) {
await this.setEffect(STATUSES.StatusComma, true); await this.setEffect(STATUSES.StatusComma, true)
} }
return result return result
} }
@@ -256,14 +278,6 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return Math.max(0, Math.min(maxEndVie, maxEndGraves, maxEndCritiques)); return Math.max(0, Math.min(maxEndVie, maxEndGraves, maxEndCritiques));
} }
async onUpdateActor(update, options, actorId) {
const updatedEndurance = update?.system?.sante?.endurance
if (updatedEndurance && options.diff) {
await this.setEffect(STATUSES.StatusUnconscious, updatedEndurance.value == 0)
}
await super.onUpdateActor(update, options, actorId)
}
async onCreateItem(item, options, id) { async onCreateItem(item, options, id) {
await this.changeItemEffects(item) await this.changeItemEffects(item)
await super.onCreateItem(item, options, id) await super.onCreateItem(item, options, id)
@@ -282,12 +296,12 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
async changeItemEffects(item) { async changeItemEffects(item) {
switch (item.type) { switch (item.type) {
case ITEM_TYPES.blessure: case ITEM_TYPES.blessure:
await this.changeStateBleeding(); await this.changeStateBleeding()
break; break;
case ITEM_TYPES.maladie: case ITEM_TYPES.maladie:
case ITEM_TYPES.poison: case ITEM_TYPES.poison:
await this.changeStateMalade(); await this.changeStateMalade()
break; break
} }
} }
@@ -306,32 +320,15 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async ajouterBlessure(encaissement, attackerToken = undefined) { nouvelleBlessure(gravite, options = { origine: undefined, localisation: '' }) {
if (encaissement.gravite < 0) return; if (gravite < 0) return
if (encaissement.gravite > 0) { if (gravite > 0) {
while (this.countBlessures(it => it.system.gravite == encaissement.gravite) >= RdDItemBlessure.maxBlessures(encaissement.gravite) && encaissement.gravite <= 6) { while (this.countBlessures(it => it.system.gravite == gravite) >= RdDItemBlessure.maxBlessures(gravite) && gravite <= 6) {
// Aggravation // Aggravation
encaissement.gravite += 2 gravite += 2
if (encaissement.gravite > 2) {
encaissement.vie += 2;
} }
} }
} return RdDItemBlessure.prepareBlessure(gravite, options);
const endActuelle = this.getEnduranceActuelle();
const blessure = await RdDItemBlessure.createBlessure(this, encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken);
if (blessure.isCritique()) {
encaissement.endurance = endActuelle
}
if (blessure.isMort()) {
this.setEffect(STATUSES.StatusComma, true);
encaissement.mort = true;
ChatMessage.create({
content: `<img class="chat-icon" src="icons/svg/skull.svg" data-tooltip="charge" />
<strong>${this.getAlias()} vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !</strong>`
});
}
return blessure;
} }
async supprimerBlessure({ gravite }) { async supprimerBlessure({ gravite }) {
@@ -343,8 +340,8 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
async supprimerBlessures(filterToDelete) { async supprimerBlessures(filterToDelete) {
const toDelete = this.filterItems(filterToDelete, ITEM_TYPES.blessure) const toDelete = this.filterItems(filterToDelete, ITEM_TYPES.blessure)
.map(it => it.id); .map(it => it.id)
await this.deleteEmbeddedDocuments('Item', toDelete); await this.deleteEmbeddedDocuments('Item', toDelete)
} }
countBlessures(filter = it => !it.isContusion()) { countBlessures(filter = it => !it.isContusion()) {
@@ -354,19 +351,17 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
/* -------------------------------------------- */ /* -------------------------------------------- */
async jetDeVie() { async jetDeVie() {
if (this.isDead()) { if (this.isDead()) {
ChatMessage.create({ return await ChatMessage.create({
content: `Jet de Vie: ${this.getAlias()} est déjà mort, ce n'est pas la peine d'en rajouter !!!!!`, content: `Jet de Vie: ${this.getAlias()} est déjà mort, ce n'est pas la peine d'en rajouter !!!!!`,
whisper: ChatUtility.getOwners(this) whisper: ChatUtility.getOwners(this)
}) })
return
} }
const jetDeVie = await RdDDice.roll("1d20"); const jetDeVie = await RdDDice.roll("1d20");
const sConst = this.getSConst(); const sConst = this.getSConst();
const vie = this.system.sante.vie.value; const vie = this.system.sante.vie.value;
const isCritique = this.nbBlessuresCritiques() > 0; const isCritique = this.countBlessures(it => it.isCritique()) > 0
const isGrave = this.nbBlessuresGraves(); const isGrave = this.countBlessures(it => it.isGrave())
const isEchecTotal = jetDeVie.total == 20; const isEchecTotal = jetDeVie.total == 20
const isSuccess = jetDeVie.total == 1 || jetDeVie.total <= vie; const isSuccess = jetDeVie.total == 1 || jetDeVie.total <= vie;
const perte = isSuccess ? 0 : 1 + (isEchecTotal ? vie + sConst : 0) const perte = isSuccess ? 0 : 1 + (isEchecTotal ? vie + sConst : 0)
const prochainJet = (jetDeVie.total == 1 && vie > 0 ? 20 : 1) * (isCritique ? 1 : isGrave > 0 ? sConst : 0) const prochainJet = (jetDeVie.total == 1 && vie > 0 ? 20 : 1) * (isCritique ? 1 : isGrave > 0 ? sConst : 0)
@@ -384,10 +379,10 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
else if (prochainJet > 0) { else if (prochainJet > 0) {
msgText += `<br>Prochain jet de vie dans ${prochainJet} ${isCritique ? 'round' : 'minute'}${prochainJet > 1 ? 's' : ''} ${isCritique ? '(état critique)' : '(état grave)'}` msgText += `<br>Prochain jet de vie dans ${prochainJet} ${isCritique ? 'round' : 'minute'}${prochainJet > 1 ? 's' : ''} ${isCritique ? '(état critique)' : '(état grave)'}`
} }
ChatMessage.create({ return await ChatMessage.create({
content: msgText, content: msgText,
whisper: ChatUtility.getOwners(this) whisper: ChatUtility.getOwners(this)
}); })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -395,13 +390,14 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
const jetEndurance = (await RdDDice.roll("1d20")).total; const jetEndurance = (await RdDDice.roll("1d20")).total;
const sonne = jetEndurance == 20 || jetEndurance > (resteEndurance ?? this.system.sante.endurance.value) const sonne = jetEndurance == 20 || jetEndurance > (resteEndurance ?? this.system.sante.endurance.value)
if (sonne) { if (sonne) {
await this.setSonne(); await this.setSonne(true)
} }
return { jetEndurance, sonne } return { jetEndurance, sonne }
} }
async finDeRoundBlessures() { async finDeRoundBlessures() {
const nbGraves = this.filterItems(it => it.isGrave(), 'blessure').length; const nbGraves = this.itemTypes[ITEM_TYPES.blessure]
.filter(it => it.isGrave() && !it.system.premierssoins.done).length;
if (nbGraves > 0) { if (nbGraves > 0) {
// Gestion blessure graves : -1 pt endurance par blessure grave // Gestion blessure graves : -1 pt endurance par blessure grave
await this.santeIncDec("endurance", -nbGraves); await this.santeIncDec("endurance", -nbGraves);
@@ -410,8 +406,9 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
async setSonne(sonne = true) { async setSonne(sonne = true) {
if (!game.combat && sonne) { if (!game.combat && sonne) {
// TODO: vérifier si comportement toujours valable
ui.notifications.info(`${this.getAlias()} est hors combat, il ne reste donc pas sonné`); ui.notifications.info(`${this.getAlias()} est hors combat, il ne reste donc pas sonné`);
return; return
} }
await this.setEffect(STATUSES.StatusStunned, sonne) await this.setEffect(STATUSES.StatusStunned, sonne)
} }

View File

@@ -49,11 +49,9 @@ export class RdDBaseActor extends Actor {
static init() { static init() {
Handlebars.registerHelper('actor-isFeminin', actor => actor.isFeminin()) Handlebars.registerHelper('actor-isFeminin', actor => actor.isFeminin())
Hooks.on("preUpdateItem", (item, change, options, id) => Misc.documentIfResponsible(item.parent)?.onPreUpdateItem(item, change, options, id))
Hooks.on("createItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onCreateItem(item, options, id)) Hooks.on("createItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onCreateItem(item, options, id))
Hooks.on("updateItem", (item, updates, options, id) => Misc.documentIfResponsible(item.parent)?.onUpdateItem(item, updates, options, id)) Hooks.on("updateItem", (item, updates, options, id) => Misc.documentIfResponsible(item.parent)?.onUpdateItem(item, updates, options, id))
Hooks.on("deleteItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.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) => Misc.documentIfResponsible(actor)?.onUpdateActor(change, options, actorId))
} }
static onSocketMessage(sockmsg) { static onSocketMessage(sockmsg) {
@@ -93,25 +91,11 @@ export class RdDBaseActor extends Actor {
} }
static getRealActor(actorId, tokenId) { static getRealActor(actorId, tokenId) {
if (tokenId) { const actor = tokenId ? canvas.tokens.get(tokenId)?.actor : undefined
let token = canvas.tokens.get(tokenId) return actor ?? game.actors.get(actorId)
if (token) {
return token.actor
}
}
return game.actors.get(actorId)
} }
getAlias() { static extractActorMin(actor) { return { id: actor?.id, type: actor?.type, name: actor?.name, img: actor?.img } }
if (this.token?.name != null && this.token != this.prototypeToken) {
return this.token.name
}
return this.name
}
isPersonnageJoueur() { return false }
static extractActorMin = (actor) => { return { id: actor?.id, type: actor?.type, name: actor?.name, img: actor?.img }; };
/** /**
* 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:
@@ -156,6 +140,15 @@ export class RdDBaseActor extends Actor {
super(docData, context); super(docData, context);
} }
getAlias() {
if (this.token?.name != null && this.token != this.prototypeToken) {
return this.token.name
}
return this.name
}
isPersonnageJoueur() { return false }
getCarac() { getCarac() {
return foundry.utils.duplicate(this.system.carac) return foundry.utils.duplicate(this.system.carac)
} }
@@ -221,6 +214,41 @@ export class RdDBaseActor extends Actor {
} }
} }
async _preUpdate(changed, options, user) {
const updatedCarac = changed?.system?.carac
if (updatedCarac && (updatedCarac.force || updatedCarac.reve || updatedCarac.taille)) {
await this.setEffect(STATUSES.StatusSurEnc, this.isSurenc())
}
await this.delayedRenderSheet('_preUpdate', changed, options)
return super._preUpdate(changed, options, user)
}
_onUpdate(changed, options, userId) {
super._onUpdate(changed, options, userId)
if (userId == game.user.id){
this.delayedRenderSheet('_onUpdate', changed, options)
}
}
async delayedRenderSheet(caller, data, options) {
this.refreshDelayCounter = (this.refreshDelayCounter ?? 0)+1
if (this.refreshDelayCounter == 1) {
this.renderAfterDelay(this.refreshDelayCounter)
}
}
renderAfterDelay(currentCounter) {
setTimeout(async () => {
if (currentCounter == this.refreshDelayCounter) {
this.sheet?.render()
this.refreshDelayCounter = 0
}
else {
this.renderAfterDelay(this.refreshDelayCounter)
}
}, 30)
}
/* -------------------------------------------- */ /* -------------------------------------------- */
prepareData() { prepareData() {
super.prepareData() super.prepareData()
@@ -233,6 +261,7 @@ export class RdDBaseActor extends Actor {
prepareActorData() { } prepareActorData() { }
async computeEtatGeneral() { } async computeEtatGeneral() { }
/* -------------------------------------------- */ /* -------------------------------------------- */
findPlayer() { findPlayer() {
return game.users.players.find(player => player.active && player.character?.id == this.id); return game.users.players.find(player => player.active && player.character?.id == this.id);
@@ -285,14 +314,14 @@ export class RdDBaseActor extends Actor {
return this.getEffects().filter(it => it.statuses.has(effectId)) return this.getEffects().filter(it => it.statuses.has(effectId))
} }
async setEffect(effectId, status) { async setEffect(effectId, status, options = { render: true }) {
if (this.isEffectAllowed(effectId)) { if (this.isEffectAllowed(effectId)) {
const effects = this.getEffectsByStatus(effectId) const effects = this.getEffectsByStatus(effectId)
if (!status && effects.length > 0) { if (!status && effects.length > 0) {
await this.deleteEmbeddedDocuments('ActiveEffect', effects.map(it => it.id), { render: true }) await this.deleteEmbeddedDocuments('ActiveEffect', effects.map(it => it.id), options)
} }
if (status && effects.length == 0) { if (status && effects.length == 0) {
await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.prepareActiveEffect(effectId)], { render: true }) await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.prepareActiveEffect(effectId)], options)
} }
} }
} }
@@ -301,13 +330,13 @@ export class RdDBaseActor extends Actor {
this.removeEffects(it => it.id == id) this.removeEffects(it => it.id == id)
} }
async removeEffects(filter = e => true) { async removeEffects(filter = e => true, options = { render: true }) {
if (game.user.isGM) { if (game.user.isGM) {
const ids = this.getEffects(filter) const ids = this.getEffects(filter)
.filter(it => this.canRemoveEffects(it)) .filter(it => this.canRemoveEffects(it))
.map(it => it.id) .map(it => it.id)
if (ids.length > 0) { if (ids.length > 0) {
await this.deleteEmbeddedDocuments('ActiveEffect', ids) await this.deleteEmbeddedDocuments('ActiveEffect', ids, options)
} }
} }
@@ -326,16 +355,8 @@ export class RdDBaseActor extends Actor {
async updateCarac(caracName, to) { async updateCarac(caracName, to) {
} }
async onUpdateActor(change, options, actorId) {
const updatedCarac = change?.system?.carac
if (updatedCarac && (updatedCarac.force || updatedCarac.reve || updatedCarac.taille)) {
console.log(' onUpdateActor', change, options, actorId)
await this.setEffect(STATUSES.StatusSurEnc, this.isSurenc())
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async onPreUpdateItem(item, change, options, id) { }
async onCreateItem(item, options, id) { async onCreateItem(item, options, id) {
} }
@@ -352,15 +373,15 @@ export class RdDBaseActor extends Actor {
} }
async _removeItemFromConteneur(item) { async _removeItemFromConteneur(item) {
const updates = this.findConteneur(item) const conteneur = this.findConteneur(item);
.map(conteneur => { if (conteneur) {
const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id) const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id)
return { _id: conteneur.id, 'system.contenu': nouveauContenu } const updates = { _id: conteneur.id, 'system.contenu': nouveauContenu }
})
if (updates.length > 0) { if (updates.length > 0) {
await this.updateEmbeddedDocuments('Item', updates) await this.updateEmbeddedDocuments('Item', updates)
} }
} }
}
async onTimeChanging(oldTimestamp, newTimestamp) { async onTimeChanging(oldTimestamp, newTimestamp) {
this.items.filter(it => it.isFinPeriode(oldTimestamp, newTimestamp)) this.items.filter(it => it.isFinPeriode(oldTimestamp, newTimestamp))
@@ -429,7 +450,7 @@ export class RdDBaseActor extends Actor {
msg = "Vous n'avez pas assez d'argent pour payer cette somme !"; msg = "Vous n'avez pas assez d'argent pour payer cette somme !";
} }
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(this), whisper: ChatUtility.getOwners(this),
content: msg content: msg
}) })
@@ -473,7 +494,7 @@ export class RdDBaseActor extends Actor {
await Monnaie.optimiserFortune(this, sols + this.getFortune()); await Monnaie.optimiserFortune(this, sols + this.getFortune());
RdDAudio.PlayContextAudio("argent"); // Petit son RdDAudio.PlayContextAudio("argent"); // Petit son
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(this), whisper: ChatUtility.getOwners(this),
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.` content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
}) })
@@ -527,7 +548,7 @@ export class RdDBaseActor extends Actor {
} }
const chatAchatItem = foundry.utils.duplicate(achat.vente); const chatAchatItem = foundry.utils.duplicate(achat.vente);
chatAchatItem.quantiteTotal = quantite; chatAchatItem.quantiteTotal = quantite;
ChatMessage.create({ await ChatMessage.create({
user: achat.userId, user: achat.userId,
speaker: { alias: (acheteur ?? vendeur).getAlias() }, speaker: { alias: (acheteur ?? vendeur).getAlias() },
whisper: ChatUtility.getOwners(this), whisper: ChatUtility.getOwners(this),
@@ -872,13 +893,14 @@ export class RdDBaseActor extends Actor {
system: { description: this.system.description } system: { description: this.system.description }
} }
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.hbs', chatData) renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.hbs', chatData)
.then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride))); .then(async html => await ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
} }
actionImpossible(action) { actionImpossible(action) {
ui.notifications.info(`${this.getAlias()} ne peut pas faire cette action: ${action}`) ui.notifications.info(`${this.getAlias()} ne peut pas faire cette action: ${action}`)
} }
ajoutExperience(rollData) { }
isAlcoolise() { return false } isAlcoolise() { return false }
async jetEthylisme() { this.actionImpossible("jet d'éthylisme") } async jetEthylisme() { this.actionImpossible("jet d'éthylisme") }
async rollAppelChance() { this.actionImpossible("appel à la chance") } async rollAppelChance() { this.actionImpossible("appel à la chance") }
@@ -892,11 +914,7 @@ export class RdDBaseActor extends Actor {
isActorCombat() { return false } isActorCombat() { return false }
getCaracInit(competence) { return 0 } getCaracInit(competence) { return 0 }
listAttaques() { listActions() { return [] }
return this.listActions({ isAttaque: true, isEquipe: false })
}
listActions({ isAttaque = false, isEquipe = false }) { return [] }
listActionsPossessions() { listActionsPossessions() {
return this.itemTypes[ITEM_TYPES.possession] return this.itemTypes[ITEM_TYPES.possession]

View File

@@ -15,8 +15,8 @@ export class RdDCreature extends RdDBaseActorSang {
} }
async remiseANeuf() { async remiseANeuf() {
await this.removeEffects(e => true); await this.removeEffects(e => true)
await this.supprimerBlessures(it => true); await this.supprimerBlessures(it => true)
await this.update({ await this.update({
'system.sante.endurance.value': this.system.sante.endurance.max, 'system.sante.endurance.value': this.system.sante.endurance.max,
'system.sante.vie.value': this.system.sante.vie.max, 'system.sante.vie.value': this.system.sante.vie.max,

View File

@@ -18,6 +18,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
formData.niveau = this.actor.getNiveau() formData.niveau = this.actor.getNiveau()
delete formData.system.carac.niveau delete formData.system.carac.niveau
formData.resonances = this.actor.system.sante.resonnance.actors.map(actorId => game.actors.get(actorId)) formData.resonances = this.actor.system.sante.resonnance.actors.map(actorId => game.actors.get(actorId))
.filter(actor => actor != undefined)
.map(actor => { return { id: actor.id, name: actor.name, img: actor.img } }) .map(actor => { return { id: actor.id, name: actor.name, img: actor.img } })
return formData return formData
} }
@@ -75,6 +76,6 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
async resonanceDelete(actorId) { async resonanceDelete(actorId) {
console.log('Delete : ', actorId); console.log('Delete : ', 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 }, { render: false });
} }
} }

View File

@@ -43,9 +43,7 @@ export class RdDEntite extends RdDBaseActorReve {
async remiseANeuf() { async remiseANeuf() {
if (!this.isEntiteNonIncarnee()) { if (!this.isEntiteNonIncarnee()) {
await this.update({ await this.update({ 'system.sante.endurance.value': this.system.sante.endurance.max })
'system.sante.endurance.value': this.system.sante.endurance.max
});
} }
await this.removeEffects(e => true) await this.removeEffects(e => true)
} }
@@ -85,12 +83,9 @@ export class RdDEntite extends RdDBaseActorReve {
if (this.isEntiteNonIncarnee()) { if (this.isEntiteNonIncarnee()) {
return return
} }
encaissement.isEntiteIncarnee = true
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance); const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance);
foundry.utils.mergeObject(encaissement, { foundry.utils.mergeObject(encaissement, { resteEndurance: perteEndurance.newValue, endurance: perteEndurance.perte })
resteEndurance: perteEndurance.newValue,
endurance: perteEndurance.perte,
blessure: RdDItemBlessure.prepareBlessure(encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken)
})
} }
isEntiteAccordee(attacker) { isEntiteAccordee(attacker) {

View File

@@ -46,9 +46,9 @@ export class RdDActorExportSheet extends RdDActorSheet {
formData.export = this.getMappingValues(formData.context, this.actor) formData.export = this.getMappingValues(formData.context, this.actor)
formData.competences = this.getCompetences(CATEGORIES_COMPETENCES_BASE) formData.competences = this.getCompetences(CATEGORIES_COMPETENCES_BASE)
formData.draconic = this.getCompetences(CATEGORIES_DRACONIC) formData.draconic = this.getCompetences(CATEGORIES_DRACONIC)
const legeres = this.actor.nbBlessuresLegeres() const legeres = this.actor.countBlessures(it => it.isLegere())
const graves = this.actor.nbBlessuresGraves() const graves = this.actor.countBlessures(it => it.isGrave())
const critiques = this.actor.nbBlessuresCritiques() const critiques = this.actor.countBlessures(it => it.isCritique())
formData.etat = { formData.etat = {
surenc: this.actor.computeMalusSurEncombrement(), surenc: this.actor.computeMalusSurEncombrement(),
fatigue: { fatigue: {
@@ -103,11 +103,10 @@ export class RdDActorExportSheet extends RdDActorSheet {
gravite: this.html.find(event.currentTarget).data('gravite') gravite: this.html.find(event.currentTarget).data('gravite')
}) })
) )
this.html.find('.click-blessure-add').click(async event => this.html.find('.click-blessure-add').click(async event => {
await this.actor.ajouterBlessure({ const blessure = this.actor.nouvelleBlessure(this.html.find(event.currentTarget).data('gravite'))
gravite: this.html.find(event.currentTarget).data('gravite') await actor.createEmbeddedDocuments('Item', [blessure])
}) })
)
this.html.find('.button-export').click(async event => await this.html.find('.button-export').click(async event => await
ExportScriptarium.INSTANCE.exportActors([this.actor], ExportScriptarium.INSTANCE.exportActors([this.actor],
`${this.actor.uuid}-${this.actor.name}` `${this.actor.uuid}-${this.actor.name}`

View File

@@ -70,9 +70,7 @@ export class RdDTextEditor {
options: { showLink: false } options: { showLink: false }
}, },
param) param)
ChatMessage.create({ await ChatMessage.create({ content: text })
content: text
})
} }
} }
} }

View File

@@ -92,48 +92,50 @@ export class ChatUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async createChatWithRollMode(messageData, actor = undefined, rollMode = game.settings.get("core", "rollMode")) { static adaptVisibility( messageData, options = { actor: undefined, rollMode: undefined }) {
switch (rollMode) { foundry.utils.mergeObject(options, { rollMode: game.settings.get("core", "rollMode") }, { overwrite: false });
switch (options.rollMode) {
case "blindroll": // GM only case "blindroll": // GM only
if (!game.user.isGM) { if (!game.user.isGM) {
ChatUtility.blindMessageToGM(messageData) ChatUtility.blindMessageToGM(messageData)
messageData.whisper = [game.user]; messageData.whisper = [game.user]
messageData.content = "Message envoyé en aveugle au Gardien" messageData.content = "Message envoyé en aveugle au Gardien";
} }
else { else {
messageData.whisper = ChatUtility.getGMs() messageData.whisper = ChatUtility.getGMs()
} }
break break;
case "gmroll": case "gmroll":
messageData.whisper = actor ? ChatUtility.getOwners(actor) : ChatUtility.getUserAndGMs() messageData.whisper = options.actor ? ChatUtility.getOwners(options.actor) : ChatUtility.getUserAndGMs()
break break;
case "selfroll": case "selfroll":
messageData.whisper = [game.user] messageData.whisper = [game.user]
break break
} }
messageData.alias = messageData.alias ?? actor?.name ?? game.user.name messageData.alias = messageData.alias ?? options.actor?.name ?? game.user.name
return await ChatMessage.create(messageData) return messageData
} }
static tellToUser(message) { static async tellToUser(message) {
ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id] }); await ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id] });
} }
static tellToGM(message) { static async tellToGM(message) {
ChatMessage.create({ await ChatMessage.create({
user: game.user.id, user: game.user.id,
content: message, content: message,
whisper: ChatUtility.getGMs() whisper: ChatUtility.getGMs()
}); })
} }
static tellToUserAndGM(message) { static async tellToUserAndGM(message) {
ChatMessage.create({ await ChatMessage.create({
user: game.user.id, user: game.user.id,
content: message, content: message,
whisper: ChatUtility.getUserAndGMs() whisper: ChatUtility.getUserAndGMs()
}) })
} }
static getOwners(document) { static getOwners(document) {
return document ? game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) : [game.user] return document ? game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) : [game.user]
} }

View File

@@ -71,28 +71,32 @@ export class RdDCoeur {
} }
static async applyCoeurChateauDormant(actor, message) { static async applyCoeurChateauDormant(actor, message) {
const newSuivants = foundry.utils.duplicate(actor.system.subacteurs.suivants)
let count = 0 let count = 0
newSuivants.forEach(async link => { let ajustMoral = 0
const newSuivants = actor.system.subacteurs.suivants.filter(link => game.actors.get(link.id) != undefined)
.map(link => {
const suivant = game.actors.get(link.id) const suivant = game.actors.get(link.id)
const prochainCoeur = link.prochainCoeur ?? 0; const prochainCoeur = link.prochainCoeur ?? 0
const coeurCourant = link.coeur ?? 0; const coeurCourant = link.coeur ?? 0
const diff = prochainCoeur - coeurCourant const diff = prochainCoeur - coeurCourant
if (diff < 0) { if (diff < 0) {
await actor.moralIncDec(-4); ajustMoral -= 4
link.coeur = Math.max(0, coeurCourant - 1) link.coeur = Math.max(0, coeurCourant - 1)
link.prochainCoeur = link.coeur link.prochainCoeur = link.coeur
message.content += `<br>Votre c&oelig;ur brisé pour ${suivant.name} vous fait perdre 4 points de moral, il vous reste ${link.coeur} points de C&oelig;ur.` message.content += `<br>Votre c&oelig;ur brisé pour ${suivant.name} vous fait perdre 4 points de moral, il vous reste ${link.coeur} points de C&oelig;ur.`
count++ count++
} }
else if (diff > 0) { if (diff > 0) {
link.coeur = Math.min(prochainCoeur, 4) link.coeur = Math.min(prochainCoeur, 4)
message.content += `<br>Votre c&oelig;ur bat fort, vous avez maintenant ${link.coeur} points de C&oelig;ur pour ${suivant.name}.` message.content += `<br>Votre c&oelig;ur bat fort, vous avez maintenant ${link.coeur} points de C&oelig;ur pour ${suivant.name}.`
link.prochainCoeur = link.coeur link.prochainCoeur = link.coeur
count++ count++
} }
return foundry.utils.duplicate(link)
})
if (ajustMoral != 0) {
await actor.moralIncDec(ajustMoral, 'Coeur')
} }
)
if (count > 0) { if (count > 0) {
await actor.update({ 'system.subacteurs.suivants': newSuivants }); await actor.update({ 'system.subacteurs.suivants': newSuivants });
} }

View File

@@ -48,7 +48,7 @@ export class Distance {
static isVisible(token, defenderToken) { static isVisible(token, defenderToken) {
// TODO: regarder les StatusEffect aveuglé? // TODO: regarder les StatusEffect aveuglé?
if (Distance.$isToken(token) && Distance.$isToken(defenderToken)) { if (Distance.$isToken(token) && Distance.$isToken(defenderToken)) {
return canvas.effects.visibility.testVisibility(defenderToken.getCenterPoint(), { object: token }) return canvas.visibility.testVisibility(defenderToken.getCenterPoint(), { object: token })
} }
return true return true
} }

View File

@@ -38,23 +38,23 @@ export class DialogCreateSigneDraconique extends Dialog {
} }
async _onCreerSigneActeurs() { async _onCreerSigneActeurs() {
await this.html.find("[name='signe.system.ephemere']").change(); await this.html.find("[name='signe.system.ephemere']").change()
await this.html.find(".signe-xp-sort").change(); await this.html.find(".signe-xp-sort").change()
this.validerSigne(); this.validerSigne()
this.dialogData.actors.filter(it => it.selected) await Promise.all(this.dialogData.actors.filter(it => it.selected)
.map(it => game.actors.get(it.id)) .map(it => game.actors.get(it.id))
.forEach(actor => this._createSigneForActor(actor, this.dialogData.signe)); .map(async actor => await this._createSigneForActor(actor, this.dialogData.signe)))
} }
async _createSigneForActor(actor, signe) { async _createSigneForActor(actor, signe) {
actor.createEmbeddedDocuments("Item", [signe]); await actor.createEmbeddedDocuments("Item", [signe]);
ChatMessage.create({ await ChatMessage.createChatMessage.create({
whisper: ChatUtility.getOwners(actor), whisper: ChatUtility.getOwners(actor),
content: await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.hbs", { content: await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.hbs", {
signe: signe, signe: signe,
alias: actor.getAlias() alias: actor.getAlias()
}) })
}); })
} }
validerSigne() { validerSigne() {

View File

@@ -0,0 +1,19 @@
export class RdDActiveEffect extends ActiveEffect {
async _preCreate(data, options, user) {
await this.parent?.delayedRenderSheet('_preCreateEffect', data, options)
return super._preCreate(data, options, user)
}
async _preUpdate(changed, options, user) {
await this.parent?.delayedRenderSheet('_preUpdateEffect', changed, options)
return super._preUpdate(changed, options, user)
}
async _preDelete(options, user) {
await this.parent?.delayedRenderSheet('_preDeleteEffect', { id: this.id }, options)
return super._preDelete(options, user)
}
}

View File

@@ -1,4 +1,4 @@
import { ChatUtility } from "./chat-utility.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { RdDInitiative } from "./initiative.mjs"; import { RdDInitiative } from "./initiative.mjs";
import { RdDItem } from "./item.js"; import { RdDItem } from "./item.js";
@@ -71,6 +71,36 @@ export class RdDItemCompetence extends RdDItem {
} }
return undefined return undefined
} }
async _preUpdate(changed, options, user) {
await this.checkCompetenceXP(changed.system?.xp)
return super._preUpdate(changed, options, user)
}
async checkCompetenceXP(newXP, display = true) {
if (this.actor?.isPersonnage() && newXP && newXP != this.system.xp && newXP > 0) {
const newNiv = this.system.niveau + 1
let needed = RdDItemCompetence.getCompetenceNextXp(newNiv)
if (newXP >= needed) {
const xpData = {
alias: this.actor.getAlias(),
competence: this.name,
niveau: newNiv,
xp: newXP,
archetype: this.system.niveau_archetype,
archetypeWarning: newNiv > this.system.niveau_archetype
}
if (display) {
await ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.hbs`, xpData)
})
}
return xpData
}
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static getLabelCategorie(category) { static getLabelCategorie(category) {
return CATEGORIES_COMPETENCES[category].label; return CATEGORIES_COMPETENCES[category].label;

View File

@@ -153,10 +153,10 @@ export class RdDItemSort extends RdDItem {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static incrementBonusCase(actor, sort, coord) { static async incrementBonusCase(actor, sort, coord) {
let bonuscase = RdDItemSort.calculBonuscase(sort, coord) let bonuscase = RdDItemSort.calculBonuscase(sort, coord)
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]); await actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]);
} }

View File

@@ -85,6 +85,10 @@ export const defaultItemImg = {
munition: "systems/foundryvtt-reve-de-dragon/icons/objets/fleche.webp" munition: "systems/foundryvtt-reve-de-dragon/icons/objets/fleche.webp"
} }
const ITEM_TYPES_PLURIEL = {
[ITEM_TYPES.jeu]: 'jeux'
}
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDItem extends Item { export class RdDItem extends Item {
@@ -112,6 +116,13 @@ export class RdDItem extends Item {
return true; return true;
} }
static itemTypePluriel(type) {
if (ITEM_TYPES[type]) {
return ITEM_TYPES_PLURIEL[type] ?? (type + 's')
}
console.error(`Item type ${type} is undefined`)
return type
}
static async getCorrespondingItem(itemRef) { static async getCorrespondingItem(itemRef) {
if (itemRef.pack) { if (itemRef.pack) {
return await SystemCompendiums.loadDocument(itemRef) return await SystemCompendiums.loadDocument(itemRef)
@@ -163,6 +174,21 @@ export class RdDItem extends Item {
super(docData, context); super(docData, context);
} }
async _preCreate(data, options, user) {
await this.parent?.delayedRenderSheet('_preCreateItem', data, options)
return super._preCreate(data, options, user)
}
async _preUpdate(changed, options, user) {
await this.parent?.delayedRenderSheet('_preUpdateItem', changed, options)
return super._preUpdate(changed, options, user)
}
async _preDelete(options, user) {
await this.parent?.delayedRenderSheet('_preDeleteItem', { id: this.id }, options)
return super._preDelete(options, user)
}
getUniteQuantite() { getUniteQuantite() {
switch (this.type) { switch (this.type) {
case ITEM_TYPES.monnaie: return "(Pièces)" case ITEM_TYPES.monnaie: return "(Pièces)"
@@ -601,14 +627,14 @@ export class RdDItem extends Item {
system: { description: this.system.description }, system: { description: this.system.description },
properties: this.getProprietes(), properties: this.getProprietes(),
} }
renderTemplate(this.getChatItemTemplate(), chatData).then(html => { renderTemplate(this.getChatItemTemplate(), chatData).then(async html => {
let chatOptions = RdDUtility.chatDataSetup(html, modeOverride); let chatOptions = RdDUtility.chatDataSetup(html, modeOverride);
ChatMessage.create(chatOptions) await ChatMessage.create(chatOptions)
}); })
} }
getChatItemTemplate() { getChatItemTemplate() {
return 'systems/foundryvtt-reve-de-dragon/templates/post-item.hbs'; return 'systems/foundryvtt-reve-de-dragon/templates/post-item.hbs'
} }
static propertyIfDefined(name, val, condition = true) { static propertyIfDefined(name, val, condition = true) {

View File

@@ -6,7 +6,7 @@ import { RdDInitiative } from "../initiative.mjs";
import { MappingCreatureArme } from "./mapping-creature-arme.mjs"; import { MappingCreatureArme } from "./mapping-creature-arme.mjs";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
const nomCategorieParade = { const categorie_parade = {
"sans-armes": "Sans arme", "sans-armes": "Sans arme",
"armes-naturelles": "Armes naturelles", "armes-naturelles": "Armes naturelles",
"hast": "Armes d'hast", "hast": "Armes d'hast",
@@ -18,6 +18,7 @@ const nomCategorieParade = {
"epees-lourdes": "Epées lourdes", "epees-lourdes": "Epées lourdes",
"haches": "Haches", "haches": "Haches",
"lances": "Lances", "lances": "Lances",
"masses": "Masses",
} }
export const ATTAQUE_TYPE = { export const ATTAQUE_TYPE = {
UNE_MAIN: '(1 main)', UNE_MAIN: '(1 main)',
@@ -122,7 +123,7 @@ export class RdDItemArme extends RdDItem {
/* -------------------------------------------- */ /* -------------------------------------------- */
static getNomCategorieParade(arme) { static getNomCategorieParade(arme) {
const categorie = arme?.system ? RdDItemArme.getCategorieParade(arme) : arme; const categorie = arme?.system ? RdDItemArme.getCategorieParade(arme) : arme;
return nomCategorieParade[categorie]; return categorie_parade[categorie];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@@ -21,7 +21,7 @@ export class RdDItemArmure extends RdDItem {
if (deterioration >= 10) { if (deterioration >= 10) {
deterioration -= 10; deterioration -= 10;
protection = this.calculProtectionDeterioree(); protection = this.calculProtectionDeterioree();
ChatMessage.create({ content: `Votre armure ${this.name} s'est détériorée, elle protège maintenant de ${protection}` }); await ChatMessage.create({ content: `Votre armure ${this.name} s'est détériorée, elle protège maintenant de ${protection}` });
} }
await this.update({ await this.update({
'system.deterioration': deterioration, 'system.deterioration': deterioration,

View File

@@ -19,7 +19,7 @@ const definitionsBlessures = [
{ type: "legere", gravite: 2, endurance: "1d6", vie: 0, label: 'Légère', max: 5, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" }, { type: "legere", gravite: 2, endurance: "1d6", vie: 0, label: 'Légère', max: 5, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
{ type: "grave", gravite: 4, endurance: "2d6", vie: -2, label: 'Grave', max: 2, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" }, { type: "grave", gravite: 4, endurance: "2d6", vie: -2, label: 'Grave', max: 2, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
{ type: "critique", gravite: 6, endurance: "-100", vie: -4, label: 'Critique', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" }, { type: "critique", gravite: 6, endurance: "-100", vie: -4, label: 'Critique', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/blessure.webp" },
{ type: "mort", gravite: 8, label: 'Mort', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/mort.webp" } { type: "mort", gravite: 8, endurance: "-100", vie: 0, label: 'Mort', max: 1, icon: "systems/foundryvtt-reve-de-dragon/icons/sante/mort.webp" }
] ]
export class RdDItemBlessure extends RdDItem { export class RdDItemBlessure extends RdDItem {
@@ -54,7 +54,7 @@ export class RdDItemBlessure extends RdDItem {
} }
await this.createBlessure(actor, gravite) await this.createBlessure(actor, gravite)
ChatMessage.create({ await ChatMessage.create({
//TODO: hbs //TODO: hbs
content: `Blessure ${definition.label} appliquée à ${actor.name}<br>Perte d'endurance : ${lostEndurance} (${definition.endurance})<br>Perte de Vie : ${definition.vie}`, content: `Blessure ${definition.label} appliquée à ${actor.name}<br>Perte d'endurance : ${lostEndurance} (${definition.endurance})<br>Perte de Vie : ${definition.vie}`,
whisper: ChatUtility.getOwners(actor) whisper: ChatUtility.getOwners(actor)
@@ -71,13 +71,13 @@ export class RdDItemBlessure extends RdDItem {
return 0 return 0
} }
static async createBlessure(actor, gravite, localisation = '', attackerToken = undefined) { static async createBlessure(actor, gravite, options = { localisation: '', origine: '', render: true }) {
const blessure = RdDItemBlessure.prepareBlessure(gravite, localisation, attackerToken); const blessure = RdDItemBlessure.prepareBlessure(gravite, options);
const blessures = await actor.createEmbeddedDocuments('Item', [blessure]) const blessures = await actor.createEmbeddedDocuments('Item', [blessure], options)
return blessures[0] return blessures[0]
} }
static prepareBlessure(gravite, localisation, attackerToken) { static prepareBlessure(gravite, options = { localisation: '', origine: '' }) {
const definition = RdDItemBlessure.getDefinition(gravite); const definition = RdDItemBlessure.getDefinition(gravite);
return { return {
name: definition.label, name: definition.label,
@@ -85,9 +85,11 @@ export class RdDItemBlessure extends RdDItem {
img: definition.icon, img: definition.icon,
system: { system: {
gravite: gravite, gravite: gravite,
vie: definition.vie,
endurance: definition.endurance,
difficulte: -gravite, difficulte: -gravite,
localisation: localisation, localisation: options.localisation,
origine: attackerToken?.name ?? "" origine: options.origine
} }
} }
} }
@@ -104,11 +106,9 @@ export class RdDItemBlessure extends RdDItem {
async updateTacheSoinBlessure(tache) { async updateTacheSoinBlessure(tache) {
if (tache) { if (tache) {
await tache.update({ await tache.update({
system: { 'system.itemId': this.id,
itemId: this.id, 'system.difficulte': Math.min(this.system.difficulte, tache.system.difficulte),
difficulte: Math.min(this.system.difficulte, tache.system.difficulte), 'system.points_de_tache_courant': Math.max(0, this.system.premierssoins.tache)
points_de_tache_courant: Math.max(0, this.system.premierssoins.tache)
}
}); });
} }
} }
@@ -160,7 +160,7 @@ export class RdDItemBlessure extends RdDItem {
message.content += ` -- une blessure ${label} reste stable`; message.content += ` -- une blessure ${label} reste stable`;
} }
} }
await this.update(update); await this.update(update)
} }
} }

View File

@@ -28,6 +28,7 @@ const _MONTRER = {
} }
const _SPLIT = { const _SPLIT = {
code: 'item-split', label: 'Séparer le goupe', icon: 'fa-solid fa-unlink', code: 'item-split', label: 'Séparer le goupe', icon: 'fa-solid fa-unlink',
actorFilter: actor => actor.isOwner,
filter: it => Misc.toInt(it.system.quantite) > 1 && it.parent?.type != ACTOR_TYPES.commerce, filter: it => Misc.toInt(it.system.quantite) > 1 && it.parent?.type != ACTOR_TYPES.commerce,
action: (item, actor) => RdDSheetUtility.splitItem(item, actor) action: (item, actor) => RdDSheetUtility.splitItem(item, actor)
} }
@@ -45,6 +46,7 @@ const _DELETE = {
} }
const _EQUIPER = { const _EQUIPER = {
code: 'item-equip', label: 'Equiper', icon: it => it.system.equipe ? 'fa-solid fa-hand-rock' : 'fa-regular fa-hand-paper', code: 'item-equip', label: 'Equiper', icon: it => it.system.equipe ? 'fa-solid fa-hand-rock' : 'fa-regular fa-hand-paper',
actorFilter: actor => actor.isPersonnage(),
filter: it => !it.estContenu && it.isEquipable(), filter: it => !it.estContenu && it.isEquipable(),
action: (item, actor) => actor.equiperObjet(item) action: (item, actor) => actor.equiperObjet(item)
} }
@@ -52,26 +54,31 @@ const _EQUIPER = {
const _CUISINER = { const _CUISINER = {
code: 'item-cuisiner', label: 'Cuisiner', code: 'item-cuisiner', label: 'Cuisiner',
img: 'systems/foundryvtt-reve-de-dragon/assets/actions/cuisine.svg', img: 'systems/foundryvtt-reve-de-dragon/assets/actions/cuisine.svg',
actorFilter: actor => actor.isPersonnage(),
filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0, filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0,
action: (item, actor) => actor.preparerNourriture(item) action: (item, actor) => actor.preparerNourriture(item)
} }
const _MANGER_CRU = { const _MANGER_CRU = {
code: 'item-manger-cru', label: 'Manger cru', icon: 'fa-solid fa-drumstick-bite', code: 'item-manger-cru', label: 'Manger cru', icon: 'fa-solid fa-drumstick-bite',
actorFilter: actor => actor.isPersonnage(),
filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0, filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0,
action: (item, actor) => actor.mangerNourriture(item) action: (item, actor) => actor.mangerNourriture(item)
} }
const _MANGER = { const _MANGER = {
code: 'item-manger', label: 'Manger', icon: 'fa-solid fa-utensils', code: 'item-manger', label: 'Manger', icon: 'fa-solid fa-utensils',
actorFilter: actor => actor.isPersonnage(),
filter: it => !(it.system.boisson), filter: it => !(it.system.boisson),
action: (item, actor) => actor.mangerNourriture(item) action: (item, actor) => actor.mangerNourriture(item)
} }
const _BOIRE = { const _BOIRE = {
code: 'item-boire', label: 'Boire', icon: 'fa-solid fa-glass-water', code: 'item-boire', label: 'Boire', icon: 'fa-solid fa-glass-water',
actorFilter: actor => actor.isPersonnage(),
filter: it => it.system.boisson, filter: it => it.system.boisson,
action: (item, actor) => actor.mangerNourriture(item) action: (item, actor) => actor.mangerNourriture(item)
} }
const _DECOCTION = { const _DECOCTION = {
code: 'item-decoction', label: 'Décoction', icon: 'fa-solid fa-flask-vial', code: 'item-decoction', label: 'Décoction', icon: 'fa-solid fa-flask-vial',
actorFilter: actor => actor.isPersonnage(),
action: (item, actor) => actor.fabriquerDecoctionHerbe(item) action: (item, actor) => actor.fabriquerDecoctionHerbe(item)
} }
@@ -82,17 +89,20 @@ const _OUVRIR = {
} }
const _LIRE = { const _LIRE = {
code: 'item-lire', label: 'Lire', icon: 'fa-solid fa-book-open', code: 'item-lire', label: 'Lire', icon: 'fa-solid fa-book-open',
actorFilter: actor => actor.isPersonnage(),
action: (item, actor) => actor.actionLire(item) action: (item, actor) => actor.actionLire(item)
} }
const _REFOULER = { const _REFOULER = {
code: 'item-refouler', label: 'Refouler', icon: 'fa-solid fa-burst', code: 'item-refouler', label: 'Refouler', icon: 'fa-solid fa-burst',
actorFilter: actor => actor.isPersonnage(),
filter: it => it.system.refoulement > 0, filter: it => it.system.refoulement > 0,
action: (item, actor) => actor.actionRefoulement(item) action: (item, actor) => actor.actionRefoulement(item)
} }
const _SORT_RESERVE = { const _SORT_RESERVE = {
code: 'item-sortreserve-add', label: 'Ajouter en réserve', icon: 'fa-solid fa-sparkles', code: 'item-sortreserve-add', label: 'Ajouter en réserve', icon: 'fa-solid fa-sparkles',
actorFilter: actor => actor.isPersonnage(),
filter: it => game.user.isGM && !it.system.isrituel, filter: it => game.user.isGM && !it.system.isrituel,
action: (item, actor) => actor.addSortReserve(item) action: (item, actor) => actor.addSortReserve(item)
} }
@@ -118,6 +128,7 @@ export class ItemAction {
static applies(action, item, options) { static applies(action, item, options) {
return action && item return action && item
&& item.isActionAllowed(action.code) && item.isActionAllowed(action.code)
&& (!action.actorFilter || (item.actor && action.actorFilter(item.actor)))
&& (!action.filter || action.filter(item)) && (!action.filter || action.filter(item))
&& (action.allowLimited || options.editable) && (action.allowLimited || options.editable)
&& (!action.optionsFilter || action.optionsFilter(options)) && (!action.optionsFilter || action.optionsFilter(options))

View File

@@ -22,7 +22,7 @@ export class RdDItemMaladie extends RdDItem {
const souffrance = mal.system.identifie const souffrance = mal.system.identifie
? `de ${mal.name}` ? `de ${mal.name}`
: `d'un mal inconnu` : `d'un mal inconnu`
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(mal.actor), whisper: ChatUtility.getOwners(mal.actor),
content: `${mal.actor.name} souffre ${souffrance} (${Misc.typeName('Item', mal.type)}): vérifiez que les effets ne se sont pas aggravés !` content: `${mal.actor.name} souffre ${souffrance} (${Misc.typeName('Item', mal.type)}): vérifiez que les effets ne se sont pas aggravés !`
}) })

View File

@@ -77,41 +77,41 @@ export class RdDInventaireItemSheet extends RdDItemSheetV1 {
} }
async onAddMilieu(event) { async onAddMilieu(event) {
const milieu = this.html.find('input.input-selection-milieu').val(); const milieu = this.html.find('input.input-selection-milieu').val()
if (!milieu) { if (!milieu) {
ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${this.item.name}`); ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${this.item.name}`)
return return
} }
const list = this.item.getEnvironnements(); const list = this.item.getEnvironnements()
const exists = list.find(it => it.milieu == milieu); const exists = list.find(it => it.milieu == milieu)
if (exists) { if (exists) {
ui.notifications.warn(`${this.item.name} a déjà une rareté ${exists.rarete} en ${milieu} (fréquence: ${exists.frequence})`); ui.notifications.warn(`${this.item.name} a déjà une rareté ${exists.rarete} en ${milieu} (fréquence: ${exists.frequence})`);
return return
} }
const rarete = RdDRaretes.rareteFrequente(); const rarete = RdDRaretes.rareteFrequente()
const added = { milieu, rarete: rarete.code, frequence: rarete.frequence }; const added = { milieu, rarete: rarete.code, frequence: rarete.frequence }
const newList = [added, ...list].sort(Misc.ascending(it => it.milieu)) const newList = [added, ...list].sort(Misc.ascending(it => it.milieu))
await this.item.update({ 'system.environnement': newList }) await this.item.update({ 'system.environnement': newList })
} }
async onDeleteMilieu(event) { async onDeleteMilieu(event) {
const milieu = this.$getEventMilieu(event); const milieu = this.$getEventMilieu(event)
if (milieu != undefined) { if (milieu != undefined) {
const newList = this.item.getEnvironnements().filter(it => it.milieu != milieu) const newList = this.item.getEnvironnements().filter(it => it.milieu != milieu)
.sort(Misc.ascending(it => it.milieu)); .sort(Misc.ascending(it => it.milieu))
await this.item.update({ 'system.environnement': newList }); await this.item.update({ 'system.environnement': newList })
} }
} }
async onChange(event, doMutation) { async onChange(event, doMutation) {
const list = this.item.system.environnement; const list = this.item.system.environnement
const milieu = this.$getEventMilieu(event); const milieu = this.$getEventMilieu(event)
const updated = list.find(it => it.milieu == milieu); const updated = list.find(it => it.milieu == milieu)
if (updated) { if (updated) {
doMutation(updated); doMutation(updated)
const newList = [...list.filter(it => it.milieu != milieu), updated] const newList = [...list.filter(it => it.milieu != milieu), updated]
.sort(Misc.ascending(it => it.milieu)); .sort(Misc.ascending(it => it.milieu))
await this.item.update({ 'system.environnement': newList }); await this.item.update({ 'system.environnement': newList })
} }
} }

View File

@@ -20,7 +20,7 @@ export class RdDFauneItemSheet extends RdDInventaireItemSheet {
'system.actor.pack': linkedActor.pack, 'system.actor.pack': linkedActor.pack,
'system.actor.id': linkedActor._id, 'system.actor.id': linkedActor._id,
'system.actor.name': linkedActor.name 'system.actor.name': linkedActor.name
}); })
} }
else { else {
ui.notifications.warn(`${linkedActor.name} ne provient pas d'un compendium. ui.notifications.warn(`${linkedActor.name} ne provient pas d'un compendium.
@@ -32,7 +32,7 @@ export class RdDFauneItemSheet extends RdDInventaireItemSheet {
'system.actor.pack': '', 'system.actor.pack': '',
'system.actor.id': '', 'system.actor.id': '',
'system.actor.name': '' 'system.actor.name': ''
}); })
} }
} }

View File

@@ -16,22 +16,18 @@ class Migration {
async migrate() { } async migrate() { }
async applyItemsUpdates(computeUpdates) { async applyItemsUpdates(computeUpdates) {
await game.actors.forEach(async (actor) => { await Promise.all(game.actors.map(actor => {
const actorItemUpdates = computeUpdates(actor.items).filter(it => it != undefined); const actorItemUpdates = computeUpdates(actor.items).filter(it => it != undefined);
if (actorItemUpdates.length > 0) { if (actorItemUpdates.length > 0) {
console.log( console.log(this.code, `Applying updates on actor ${actor.name} items`, actorItemUpdates);
this.code, return actor.updateEmbeddedDocuments("Item", actorItemUpdates);
`Applying updates on actor ${actor.name} items`,
actorItemUpdates
);
await actor.updateEmbeddedDocuments("Item", actorItemUpdates);
} }
}); }))
const itemUpdates = computeUpdates(game.items).filter(it => it != undefined); const itemUpdates = computeUpdates(game.items).filter(it => it != undefined)
if (itemUpdates.length > 0) { if (itemUpdates.length > 0) {
console.log(this.code, "Applying updates on items", itemUpdates); console.log(this.code, "Applying updates on items", itemUpdates)
await Item.updateDocuments(itemUpdates); await Item.updateDocuments(itemUpdates)
} }
} }
} }
@@ -58,13 +54,13 @@ class _1_5_34_migrationPngWebp {
//Migrate system png to webp //Migrate system png to webp
await Item.updateDocuments(itemsUpdates); await Item.updateDocuments(itemsUpdates);
await Actor.updateDocuments(actorsUpdates); await Actor.updateDocuments(actorsUpdates);
game.actors.forEach(actor => { await Promise.all(game.actors
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) { .filter(actor => actor.token?.img && actor.token.img.match(regexOldPngJpg))
actor.update({ "token.img": convertImgToWebp(actor.token.img) }); .map(actor => actor.update({ "token.img": convertImgToWebp(actor.token.img) }))
} )
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items); await Promise.all(game.actors.map(actor =>
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate); actor.updateEmbeddedDocuments('Item', prepareDocumentsImgUpdate(actor.items))
}); ))
} }
} }
@@ -125,16 +121,15 @@ class _10_0_21_VehiculeStructureResistanceMax extends Migration {
get version() { return "10.0.21"; } get version() { return "10.0.21"; }
async migrate() { async migrate() {
await game.actors await Promise.all(
.filter((actor) => actor.type == "vehicule") game.actors.filter(actor => actor.type == "vehicule")
.forEach(async (actor) => { .map(actor => actor.update({
await actor.update({
'system.etat.resistance.value': actor.system.resistance, 'system.etat.resistance.value': actor.system.resistance,
'system.etat.resistance.max': actor.system.resistance, 'system.etat.resistance.max': actor.system.resistance,
'system.etat.structure.value': actor.system.structure, 'system.etat.structure.value': actor.system.structure,
'system.etat.structure.max': actor.system.structure 'system.etat.structure.max': actor.system.structure
}) }))
}); )
} }
} }
@@ -192,9 +187,9 @@ class _10_2_5_ArmesTirLancer extends Migration {
get version() { return "10.2.5"; } get version() { return "10.2.5"; }
migrateArmeTirLancer(it) { migrateArmeTirLancer(it) {
let updates = foundry.utils.mergeObject({ _id: it.id }, this.getMapping(it).updates); const updates = foundry.utils.mergeObject({ _id: it.id }, this.getMapping(it).updates)
console.log(it.name, updates); console.log(it.name, updates)
return updates; return updates
} }
async migrate() { async migrate() {
@@ -359,7 +354,7 @@ class _10_4_6_ServicesEnCommerces extends Migration {
} }
async transformInventaireCommerce(service) { async transformInventaireCommerce(service) {
const serviceItems = (service.system.items ?? []); const serviceItems = (service.system.items ?? []);
const commerceItems = await Promise.all(serviceItems.map(async (it) => { return await this.transformToItemBoutique(it); })); const commerceItems = await Promise.all(serviceItems.map((it) => this.transformToItemBoutique(it)))
return commerceItems.concat(Monnaie.monnaiesStandard()); return commerceItems.concat(Monnaie.monnaiesStandard());
} }
@@ -439,7 +434,7 @@ class _10_7_0_MigrationBlessures extends Migration {
'system.blessures.graves.liste': [], 'system.blessures.graves.liste': [],
'system.blessures.critiques.liste': [] 'system.blessures.critiques.liste': []
}) })
})); }))
} }
creerBlessure(gravite, graviteTexte, blessure, timestamp) { creerBlessure(gravite, graviteTexte, blessure, timestamp) {
const dateBlessure = timestamp.addJours(-blessure.jours); const dateBlessure = timestamp.addJours(-blessure.jours);
@@ -791,6 +786,6 @@ export class Migrations {
} }
compareVersions(a, b) { compareVersions(a, b) {
return isNewerVersion(a.version, b.version) ? 1 : isNewerVersion(b.version, a.version) ? -1 : 0; return foundry.utils.isNewerVersion(a.version, b.version) ? 1 : foundry.utils.isNewerVersion(b.version, a.version) ? -1 : 0;
} }
} }

View File

@@ -24,6 +24,13 @@ export class Misc {
return text.charAt(0).toLowerCase() + text.slice(1); return text.charAt(0).toLowerCase() + text.slice(1);
} }
static stripHtml(html)
{
const tmp = document.createElement("DIV")
tmp.innerHTML = html
return tmp.textContent || tmp.innerText || ""
}
static toSignedString(number) { static toSignedString(number) {
const value = parseInt(number) const value = parseInt(number)
const isPositiveNumber = value != NaN && value > 0; const isPositiveNumber = value != NaN && value > 0;

View File

@@ -4,9 +4,8 @@ import { SANS_COMPETENCE } from "../item/base-items.js"
import { Misc } from "../misc.js" import { Misc } from "../misc.js"
import { CARACS } from "../rdd-carac.js" import { CARACS } from "../rdd-carac.js"
import { RdDUtility } from "../rdd-utility.js" import { RdDUtility } from "../rdd-utility.js"
import { DIFF } from "../roll/roll-constants.mjs" import { DIFF, ROLL_TYPE_COMP } from "../roll/roll-constants.mjs"
import RollDialog from "../roll/roll-dialog.mjs" import RollDialog from "../roll/roll-dialog.mjs"
import { PART_COMP } from "../roll/roll-part-comp.mjs"
export const MORAL = { export const MORAL = {
MALHEUREUX: "malheureux", MALHEUREUX: "malheureux",
@@ -134,7 +133,7 @@ export class Apprecier {
const competence = (this.appreciation.jetComp && this.appreciation.competence) ? this.appreciation.competence : "" const competence = (this.appreciation.jetComp && this.appreciation.competence) ? this.appreciation.competence : ""
const rollData = { const rollData = {
ids: { actorId: this.actor.id }, ids: { actorId: this.actor.id },
type: { allowed: [PART_COMP], current: PART_COMP, appreciation: true }, type: { allowed: [ROLL_TYPE_COMP], current: ROLL_TYPE_COMP, appreciation: true },
selected: { selected: {
carac: { key: this.appreciation.carac, forced: true }, carac: { key: this.appreciation.carac, forced: true },
comp: { key: competence, forced: true }, comp: { key: competence, forced: true },
@@ -168,7 +167,7 @@ export class Apprecier {
async rollMoral(moral = undefined) { async rollMoral(moral = undefined) {
if (this.raisons.length > 0) { if (this.raisons.length > 0) {
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor), whisper: ChatUtility.getOwners(this.actor),
content: 'Pas de jet de moral:' + Misc.concat(this.raisons.map(r => `<br> - ${r}`)) content: 'Pas de jet de moral:' + Misc.concat(this.raisons.map(r => `<br> - ${r}`))
}) })
@@ -176,7 +175,6 @@ export class Apprecier {
} }
moral = moral ?? this.appreciation.moral moral = moral ?? this.appreciation.moral
// TODO: jet de moral
await this.actor.jetDeMoral(moral, this.appreciation.bonmoment) await this.actor.jetDeMoral(moral, this.appreciation.bonmoment)
} }
} }

View File

@@ -63,6 +63,7 @@ export class RdDCombatManager extends Combat {
it.token.id == tokenId it.token.id == tokenId
) )
} }
static getRangInitiativeCombatant(actorId, tokenId) { static getRangInitiativeCombatant(actorId, tokenId) {
const combatant = RdDCombatManager.getCombatant(actorId, tokenId) const combatant = RdDCombatManager.getCombatant(actorId, tokenId)
return combatant?.system.init?.rang return combatant?.system.init?.rang
@@ -169,7 +170,7 @@ export class RdDCombatManager extends Combat {
} }
static getFirstInitRollFormula(actor) { static getFirstInitRollFormula(actor) {
const actions = actor.listActions({ isEquipe: true }) const actions = actor.listActions()
if (actions.length > 0) { if (actions.length > 0) {
const action = actions[0] const action = actions[0]
const init = RdDCombatManager.getInitData(actor, action) const init = RdDCombatManager.getInitData(actor, action)
@@ -198,8 +199,8 @@ export class RdDCombatManager extends Combat {
<div> <div>
Etant donné son ${action.name}, son initative pour ce premier round est désormais de ${initData.init}. Etant donné son ${action.name}, son initative pour ce premier round est désormais de ${initData.init}.
</div>` </div>`
ChatMessage.create({ content: msg }); ChatMessage.create({ content: msg })
game.combat.setInitiative(combatant._id, initData.init); game.combat.setInitiative(combatant._id, initData.init)
} }
} }
} }
@@ -306,7 +307,7 @@ export class RdDCombatManager extends Combat {
const possessions = actor.listActionsPossessions() const possessions = actor.listActionsPossessions()
const actions = possessions.length > 0 const actions = possessions.length > 0
? possessions ? possessions
: actor.listActions({ isEquipe: true }) : actor.listActions()
return Misc.indexed(actions) return Misc.indexed(actions)
} }
@@ -387,7 +388,7 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
static onMsgEncaisser(msg) { static onMsgEncaisser(msg) {
let defender = canvas.tokens.get(msg.defenderToken.id).actor; let defender = canvas.tokens.get(msg.defenderToken.id)?.actor;
if (Misc.isOwnerPlayer(defender)) { if (Misc.isOwnerPlayer(defender)) {
let attackerRoll = msg.attackerRoll; let attackerRoll = msg.attackerRoll;
let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined; let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined;
@@ -466,24 +467,10 @@ export class RdDCombat {
this.defenderId = this.defender.id this.defenderId = this.defender.id
this.attackerTokenId = attackerTokenId this.attackerTokenId = attackerTokenId
this.defenderTokenId = defenderTokenId this.defenderTokenId = defenderTokenId
this.attackerToken = RdDCombat.$extractAttackerTokenData(attacker, attackerTokenId) this.attackerToken = Targets.getTokenData(attacker, attackerTokenId)
this.defenderToken = RdDCombat.$extractDefenderTokenData(defender, defenderTokenId, target) this.defenderToken = Targets.getTokenData(defender, defenderTokenId, target)
} }
static $extractAttackerTokenData(attacker, attackerTokenId) {
const token = canvas.tokens.get(attackerTokenId);
return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(attackerTokenId, attacker)
}
static $extractDefenderTokenData(defender, defenderTokenId, target) {
if (target) {
return Targets.extractTokenData(target)
}
const token = canvas.tokens.get(defenderTokenId);
return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(defenderTokenId, defender)
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async onEvent(button, event) { async onEvent(button, event) {
const chatMessage = ChatUtility.getChatMessage(event); const chatMessage = ChatUtility.getChatMessage(event);
@@ -623,7 +610,7 @@ export class RdDCombat {
async proposerAjustementTirLancer(rollData) { async proposerAjustementTirLancer(rollData) {
if (['tir', 'lancer'].includes(rollData.competence.system.categorie)) { if (['tir', 'lancer'].includes(rollData.competence.system.categorie)) {
if (this.defender.isEntiteBlurette()) { if (this.defender.isEntiteBlurette()) {
ChatMessage.create({ await ChatMessage.create({
content: `<strong>La cible est une blurette, l'arme à distance sera perdue dans le blurêve`, content: `<strong>La cible est une blurette, l'arme à distance sera perdue dans le blurêve`,
whisper: ChatUtility.getGMs() whisper: ChatUtility.getGMs()
}) })
@@ -638,7 +625,7 @@ export class RdDCombat {
}, },
Distance.ajustements(_token, defenderToken, { arme: rollData.arme, main: rollData.competence.system.categorie }) Distance.ajustements(_token, defenderToken, { arme: rollData.arme, main: rollData.competence.system.categorie })
) )
ChatMessage.create({ await ChatMessage.create({
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.hbs', info), content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.hbs', info),
whisper: ChatUtility.getGMs() whisper: ChatUtility.getGMs()
}) })
@@ -657,7 +644,7 @@ export class RdDCombat {
opponentId: this.defender.id, opponentId: this.defender.id,
opponentTokenId: this.defenderTokenId, opponentTokenId: this.defenderTokenId,
}, },
type: { allowed: ['attaque'], current: 'attaque' }, type: { allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE },
selected: {}, selected: {},
passeArme: foundry.utils.randomID(16), passeArme: foundry.utils.randomID(16),
} }
@@ -736,7 +723,7 @@ export class RdDCombat {
const choixDefense = await ChatMessage.create({ const choixDefense = await ChatMessage.create({
// message privé: du défenseur à lui même (et aux GMs) // message privé: du défenseur à lui même (et aux GMs)
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)), speaker: ChatMessage.getSpeaker({ actor: this.defender, token: canvas.tokens.get(this.defenderTokenId) }),
alias: this.attacker?.getAlias(), alias: this.attacker?.getAlias(),
whisper: ChatUtility.getOwners(this.defender), whisper: ChatUtility.getOwners(this.defender),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', defenseData) content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', defenseData)
@@ -769,7 +756,7 @@ export class RdDCombat {
let rollData = this._prepareAttaque(competence, arme) let rollData = this._prepareAttaque(competence, arme)
console.log("RdDCombat.attaque >>>", rollData) console.log("RdDCombat.attaque >>>", rollData)
if (arme) { if (arme) {
this.attacker.verifierForceMin(arme); await this.attacker.verifierForceMin(arme);
} }
await this.proposerAjustementTirLancer(rollData) await this.proposerAjustementTirLancer(rollData)
@@ -942,7 +929,7 @@ export class RdDCombat {
async _chatMessageDefense(paramDemandeDefense, defenderRoll) { async _chatMessageDefense(paramDemandeDefense, defenderRoll) {
const choixDefense = await ChatMessage.create({ const choixDefense = await ChatMessage.create({
// message privé: du défenseur à lui même (et aux GMs) // message privé: du défenseur à lui même (et aux GMs)
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)), speaker: ChatMessage.getSpeaker({ actor: this.defender, token: canvas.tokens.get(this.defenderTokenId) }),
alias: this.attacker?.getAlias(), alias: this.attacker?.getAlias(),
whisper: ChatUtility.getOwners(this.defender), whisper: ChatUtility.getOwners(this.defender),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense-v1.hbs', paramDemandeDefense), content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense-v1.hbs', paramDemandeDefense),
@@ -1009,9 +996,9 @@ export class RdDCombat {
const arme = rollData.arme; const arme = rollData.arme;
const avecArme = !['', 'sans-armes', 'armes-naturelles'].includes(arme?.system.categorie_parade ?? ''); const avecArme = !['', 'sans-armes', 'armes-naturelles'].includes(arme?.system.categorie_parade ?? '');
const action = (rollData.attackerRoll ? (arme ? "la parade" : "l'esquive") : "l'attaque"); const action = (rollData.attackerRoll ? (arme ? "la parade" : "l'esquive") : "l'attaque");
ChatUtility.createChatWithRollMode( await ChatMessage.create(ChatUtility.adaptVisibility(
{ content: `<strong>Maladresse à ${action}!</strong> ` + await RdDRollTables.getMaladresse({ arme: avecArme }) }, { content: `<strong>Maladresse à ${action}!</strong> ` + await RdDRollTables.getMaladresse({ arme: avecArme }) },
this.defender) { actor: this.defender }))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -1135,9 +1122,9 @@ export class RdDCombat {
async infoAttaquantDesarme(rollData) { async infoAttaquantDesarme(rollData) {
if (/*TODO: parade?*/!rollData.attackerRoll?.particuliere) { if (/*TODO: parade?*/!rollData.attackerRoll?.particuliere) {
// TODO: attaquant doit jouer résistance et peut être désarmé p132 // TODO: attaquant doit jouer résistance et peut être désarmé p132
ChatUtility.createChatWithRollMode( await ChatMessage.create(ChatUtility.adaptVisibility(
{ content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` }, { content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` },
this.defender) { actor: this.defender }))
} }
} }
@@ -1169,9 +1156,9 @@ export class RdDCombat {
console.log("RdDCombat._onParadeParticuliere >>>", defenderRoll); console.log("RdDCombat._onParadeParticuliere >>>", defenderRoll);
if (!defenderRoll.attackerRoll.isPart) { if (!defenderRoll.attackerRoll.isPart) {
// TODO: attaquant doit jouer résistance et peut être désarmé p132 // TODO: attaquant doit jouer résistance et peut être désarmé p132
ChatUtility.createChatWithRollMode( await ChatMessage.create(ChatUtility.adaptVisibility(
{ content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` }, { content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` },
this.defender) { actor: this.defender }))
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -1256,9 +1243,9 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onEsquiveParticuliere(defenderRoll) { async _onEsquiveParticuliere(defenderRoll) {
console.log("RdDCombat._onEsquiveParticuliere >>>", defenderRoll); console.log("RdDCombat._onEsquiveParticuliere >>>", defenderRoll);
ChatUtility.createChatWithRollMode( await ChatMessage.create(ChatUtility.adaptVisibility(
{ content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" }, { content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" },
this.defender); { actor: this.defender }))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@@ -27,20 +27,8 @@ const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
export class RdDCommands { export class RdDCommands {
static init() { static init() {
const rddCommands = new RdDCommands(); game.system.rdd.commands = new RdDCommands()
game.system.rdd.commands = rddCommands; Hooks.on("chatMessage", (chatLog, message, msg) => game.system.rdd.commands.onChatMessage(message, msg))
Hooks.on("chatMessage", (html, content, msg) => {
if (content[0] == '/') {
let regExp = /(\S+)/g;
let commands = content.match(regExp);
if (rddCommands.processChatCommand(commands, content, msg)) {
return false;
}
}
return true;
});
} }
constructor() { constructor() {
@@ -216,12 +204,20 @@ export class RdDCommands {
} }
onChatMessage(message, msg = {}) {
const content = Misc.stripHtml(message)
if (content[0] == '/') {
const commands = content.match(/(\S+)/g)
if (this.processChatCommand(commands, content, msg)) {
return false
}
}
return true
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Manage chat commands */ /* Manage chat commands */
processChatCommand(commandLine, content = '', msg = {}) { processChatCommand(commandLine, content = '', msg = {}) {
// Setup new message's visibility
ChatUtility.applyRollMode(msg)
msg.type = 0;
if (!this.commandsTable) { if (!this.commandsTable) {
this._registerCommands() this._registerCommands()
@@ -229,6 +225,9 @@ export class RdDCommands {
let command = commandLine[0].toLowerCase(); let command = commandLine[0].toLowerCase();
if (this._isCommandHandled(command)) { if (this._isCommandHandled(command)) {
// Setup new message's visibility
ChatUtility.applyRollMode(msg)
msg.type = 0;
let params = commandLine.slice(1); let params = commandLine.slice(1);
this._processCommand(this.commandsTable, command, params, content, msg) this._processCommand(this.commandsTable, command, params, content, msg)
return true return true
@@ -368,7 +367,7 @@ export class RdDCommands {
const carac = params[0]; const carac = params[0];
const competence = length > 1 ? '/' + Misc.join(params.slice(1, length), ' ') : '' const competence = length > 1 ? '/' + Misc.join(params.slice(1, length), ' ') : ''
ChatMessage.create({ content: `@roll[${carac}${competence}/${diff}]` }) await ChatMessage.create({ content: `@roll[${carac}${competence}/${diff}]` })
} }
} }

View File

@@ -18,7 +18,7 @@ export class DeTMR extends foundry.dice.terms.Die {
static diceSoNiceData(system) { static diceSoNiceData(system) {
return { return {
type: "dt", type: "d8",
font: "HeuresDraconiques", font: "HeuresDraconiques",
fontScale: 0.8, fontScale: 0.8,
labels: ['1', '2', '3', '4', '5', '6', 'd', '0'], labels: ['1', '2', '3', '4', '5', '6', 'd', '0'],
@@ -56,7 +56,7 @@ export class DeDraconique extends foundry.dice.terms.Die {
static diceSoNiceData(system) { static diceSoNiceData(system) {
return { return {
type: "dr", type: "d8",
font: "HeuresDraconiques", font: "HeuresDraconiques",
fontScale: 0.8, fontScale: 0.8,
labels: ['1', '2', '3', '4', '5', '6', 'd', '0'], labels: ['1', '2', '3', '4', '5', '6', 'd', '0'],
@@ -96,7 +96,7 @@ export class DeHeure extends foundry.dice.terms.Die {
static diceSoNiceData(system) { static diceSoNiceData(system) {
return { return {
type: "dh", type: "d12",
font: "HeuresDraconiques", font: "HeuresDraconiques",
fontScale: 1.2, fontScale: 1.2,
labels: ['v', 'i', 'f', 'o', 'd', 'e', 'l', 's', 'p', 'a', 'r', 'c'], labels: ['v', 'i', 'f', 'o', 'd', 'e', 'l', 's', 'p', 'a', 'r', 'c'],

View File

@@ -15,21 +15,28 @@ export class RdDEmpoignade {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getActorEmpoignade(actorId) {
const actor = game.actors.get(actorId)
if (actor == undefined) {
ui.notifications.warn(`Impossible de retrouver l'acteur ${actorId}, l'empoignade ne peut pas être continuée.`)
}
return actor
}
static isCombatantEmpoignade(actorId, tokenId) { static isCombatantEmpoignade(actorId, tokenId) {
const combatant = RdDCombatManager.getCombatant(actorId, tokenId) const combatant = RdDCombatManager.getCombatant(actorId, tokenId)
return MAP_PHASE.empoignade.rang == combatant?.system.init?.rang return combatant && MAP_PHASE.empoignade.rang == combatant?.system.init?.rang
} }
static async ajustementEmpoignade(attacker, defender, adjust = 1) { static async ajustementEmpoignade(attacker, defender, adjust = 1) {
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender) let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
if (empoignade?.system.empoigneurid == defender.id) { if (empoignade?.system.empoigneurid == defender.id) {
let empoignade = RdDEmpoignade.getEmpoignade(defender, attacker) empoignade = RdDEmpoignade.getEmpoignade(defender, attacker)
return await RdDEmpoignade.$ajustementEmpoignade(empoignade, defender, attacker, - adjust); return await RdDEmpoignade.$ajustementEmpoignade(empoignade, defender, attacker, - adjust);
} }
return await RdDEmpoignade.$ajustementEmpoignade(empoignade, attacker, defender, adjust); return await RdDEmpoignade.$ajustementEmpoignade(empoignade, attacker, defender, adjust);
} }
static async $ajustementEmpoignade(empoignade, attacker, defender, adjust) { static async $ajustementEmpoignade(empoignade, attacker, defender, adjust) {
const empId = empoignade?.system.empoignadeid ?? foundry.utils.randomID(16); const empId = empoignade?.system.empoignadeid ?? foundry.utils.randomID(16);
const empFin = (empoignade?.system.pointsemp ?? 0) + adjust const empFin = (empoignade?.system.pointsemp ?? 0) + adjust
@@ -73,30 +80,32 @@ export class RdDEmpoignade {
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee") RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee")
}); })
$(html).on("click", '.defense-empoignade-esquive', event => { $(html).on("click", '.defense-empoignade-esquive', event => {
const chatMessage = ChatUtility.getChatMessage(event); const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee") RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee")
}); })
$(html).on("click", '.empoignade-poursuivre', event => { $(html).on("click", '.empoignade-poursuivre', event => {
let attackerId = event.currentTarget.attributes['data-attackerId'].value const attacker = RdDEmpoignade.getActorFromEventTag(event, 'data-attackerId')
let defenderId = event.currentTarget.attributes['data-defenderId'].value const defender = RdDEmpoignade.getActorFromEventTag(event, 'data-defenderId')
RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId)) if (attacker && defender) {
}); RdDEmpoignade.onAttaqueEmpoignadeValidee(attacker, defender)
}
})
$(html).on("click", '.empoignade-entrainer-sol', event => { $(html).on("click", '.empoignade-entrainer-sol', event => {
const chatMessage = ChatUtility.getChatMessage(event); const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
RdDEmpoignade.entrainerAuSol(rollData) RdDEmpoignade.entrainerAuSol(rollData)
ChatUtility.remover(chatMessage)() ChatUtility.remover(chatMessage)()
}); })
$(html).on("click", '.empoignade-projeter-sol', event => { $(html).on("click", '.empoignade-projeter-sol', event => {
const chatMessage = ChatUtility.getChatMessage(event); const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
RdDEmpoignade.projeterAuSol(rollData) RdDEmpoignade.projeterAuSol(rollData)
ChatUtility.remover(chatMessage)() ChatUtility.remover(chatMessage)()
}); })
$(html).on("change", '.empoignade-perte-endurance', event => { $(html).on("change", '.empoignade-perte-endurance', event => {
const chatMessage = ChatUtility.getChatMessage(event); const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage); const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
@@ -104,7 +113,11 @@ export class RdDEmpoignade {
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value) RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
ChatUtility.remover(chatMessage)() ChatUtility.remover(chatMessage)()
} }
}); })
}
static getActorFromEventTag(event, tag) {
return RdDEmpoignade.getActorEmpoignade(event.currentTarget.attributes[tag]?.value ?? '<inconnu>')
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -112,32 +125,31 @@ export class RdDEmpoignade {
// TODO: autoriser la perception? la comédie/séduction? // TODO: autoriser la perception? la comédie/séduction?
if (RdDEmpoignade.isEmpoignadeEnCours(actor)) { if (RdDEmpoignade.isEmpoignadeEnCours(actor)) {
ui.notifications.warn("Une empoignade est en cours ! Normalement, vous ne pouvez rien faire d'autre que continuer l'empoignade ou la rompre.") ui.notifications.warn("Une empoignade est en cours ! Normalement, vous ne pouvez rien faire d'autre que continuer l'empoignade ou la rompre.")
return true; return true
} }
return false; return false
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static $storeRollEmpoignade(msg, rollData) { static $storeRollEmpoignade(msg, rollData) {
RdDEmpoignade.$reduceActorToIds(rollData); ChatUtility.setMessageData(msg, "empoignade-roll-data", RdDEmpoignade.$reduceActorToIds(rollData))
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData);
} }
static $reduceActorToIds(rollData) { static $reduceActorToIds(rollData) {
rollData.attacker = { id: rollData.attacker.id }; rollData.attacker = { id: rollData.attacker.id }
rollData.defender = { id: rollData.defender.id }; rollData.defender = { id: rollData.defender.id }
return rollData
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static $readRollEmpoignade(msg) { static $readRollEmpoignade(msg) {
const rollData = ChatUtility.getMessageData(msg, 'empoignade-roll-data'); return RdDEmpoignade.$replaceIdsWithActors(ChatUtility.getMessageData(msg, 'empoignade-roll-data'))
RdDEmpoignade.$replaceIdsWithActors(rollData);
return rollData
} }
static $replaceIdsWithActors(rollData) { static $replaceIdsWithActors(rollData) {
rollData.attacker = game.actors.get(rollData.attacker.id); rollData.attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
rollData.defender = game.actors.get(rollData.defender.id); rollData.defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
return rollData
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -147,19 +159,21 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static getEmpoignadeById(actor, id) { static getEmpoignadeById(actor, id) {
return actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id) return actor?.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static getEmpoignade(attacker, defender) { static getEmpoignade(attacker, defender) {
let emp = attacker.itemTypes[ITEM_TYPES.empoignade].find(it => if (attacker && defender) {
const empoignade = attacker.itemTypes[ITEM_TYPES.empoignade].find(it =>
(it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) || (it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) ||
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id) (it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
) )
if (emp) { if (empoignade) {
return foundry.utils.duplicate(emp); return foundry.utils.duplicate(empoignade)
} }
return undefined; }
return undefined
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -180,10 +194,14 @@ export class RdDEmpoignade {
} }
static isActionAutorisee(mode, attacker, defender) { static isActionAutorisee(mode, attacker, defender) {
const acting = RdDEmpoignade.isActionDefenseur(mode) ? defender : attacker; if (!defender || !attacker) {
return false
}
const acting = RdDEmpoignade.isActionDefenseur(mode) ? defender : attacker
if (acting.getUserLevel(game.user) < CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) { if (acting.getUserLevel(game.user) < CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) {
ui.notifications.warn(`Vous n'êtes pas autorisé à choisir l'action de ${acting.name}`) ui.notifications.warn(`Vous n'êtes pas autorisé à choisir l'action de ${acting.name}`)
return false; return false
} }
return true return true
} }
@@ -205,14 +223,11 @@ export class RdDEmpoignade {
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender) let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
const isNouvelle = empoignade == undefined; const isNouvelle = empoignade == undefined;
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender)) empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
//console.log("W.", empoignade, defender.hasArmeeMeleeEquipee())
if ((isNouvelle || empoignade.system.pointsemp == 0) && defender.hasArmeeMeleeEquipee()) { if ((isNouvelle || empoignade.system.pointsemp == 0) && defender.hasArmeeMeleeEquipee()) {
ChatUtility.createChatWithRollMode( await ChatMessage.create(ChatUtility.adaptVisibility(
{ { content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-valider.hbs`, { attacker: attacker, defender: defender }) },
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-valider.hbs`, { attacker: attacker, defender: defender }) { actor: attacker }
}, ))
attacker
)
} else { } else {
await this.onAttaqueEmpoignadeValidee(attacker, defender) await this.onAttaqueEmpoignadeValidee(attacker, defender)
} }
@@ -264,13 +279,16 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async onAttaqueEmpoignadeFromItem(empoignade) { static async onAttaqueEmpoignadeFromItem(empoignade) {
let attacker = game.actors.get(empoignade.system.empoigneurid) const attacker = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneurid)
let defender = game.actors.get(empoignade.system.empoigneid) const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
if (attacker && defender) {
await this.onAttaqueEmpoignadeValidee(attacker, defender) await this.onAttaqueEmpoignadeValidee(attacker, defender)
} }
}
static async onImmobilisation(attacker, empoignade) { static async onImmobilisation(attacker, empoignade) {
const defender = game.actors.get(empoignade.system.empoigneid) const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
if (defender) {
const empDefenseur = defender.itemTypes[ITEM_TYPES.empoignade] const empDefenseur = defender.itemTypes[ITEM_TYPES.empoignade]
.find(it => it.system.empoignadeid == empoignade.system.empoignadeid); .find(it => it.system.empoignadeid == empoignade.system.empoignadeid);
await defender.updateEmbeddedDocuments('Item', [{ await defender.updateEmbeddedDocuments('Item', [{
@@ -289,6 +307,7 @@ export class RdDEmpoignade {
}) })
RdDEmpoignade.$storeRollEmpoignade(msg, rollData); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) { static async $rollAttaqueEmpoignade(attacker, rollData, isNouvelle = false) {
@@ -304,10 +323,10 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $onRollEmpoignade(rollData, isNouvelle = false) { static async $onRollEmpoignade(rollData, isNouvelle = false) {
let attacker = game.actors.get(rollData.attacker.id) const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id) const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (attacker && defender) {
if (rollData.rolled.isSuccess && isNouvelle) { if (rollData.rolled.isSuccess && isNouvelle) {
RdDEmpoignade.$createEtatEmpoignade(rollData.empoignade) RdDEmpoignade.$createEtatEmpoignade(rollData.empoignade)
} }
@@ -319,15 +338,15 @@ export class RdDEmpoignade {
let msg = await RdDRollResult.displayRollData(rollData, defender, 'chat-empoignade-resultat.hbs'); let msg = await RdDRollResult.displayRollData(rollData, defender, 'chat-empoignade-resultat.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async onDefenseEmpoignade(attackerRoll, mode, competenceName = "Corps à corps", carac = "melee") { static async onDefenseEmpoignade(attackerRoll, mode, competenceName = "Corps à corps", carac = "melee") {
let attacker = game.actors.get(attackerRoll.attacker.id) const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
let defender = game.actors.get(attackerRoll.defender.id) const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) { if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) {
return return
} }
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender) let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
if (!empoignade) { if (!empoignade) {
@@ -367,7 +386,7 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $onRollContrerLiberer(rollData) { static async $onRollContrerLiberer(rollData) {
let empoignade = rollData.empoignade const empoignade = rollData.empoignade
if (rollData.mode == "contrer-empoigner" && !rollData.rolled.isSuccess) { if (rollData.mode == "contrer-empoigner" && !rollData.rolled.isSuccess) {
empoignade.system.pointsemp++ empoignade.system.pointsemp++
@@ -389,19 +408,23 @@ export class RdDEmpoignade {
static async $createEtatEmpoignade(empoignade) { static async $createEtatEmpoignade(empoignade) {
console.log("CREATE Empoignade", empoignade) console.log("CREATE Empoignade", empoignade)
let defender = game.actors.get(empoignade.system.empoigneid) const attacker = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneurid)
let attacker = game.actors.get(empoignade.system.empoigneurid) const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
// Creer l'empoignade sur attaquant/defenseur if (attacker && defender) {
// Creer l'empoignade sur attaquant et defenseur
await attacker.creerObjetParMJ(empoignade) await attacker.creerObjetParMJ(empoignade)
await defender.creerObjetParMJ(empoignade) await defender.creerObjetParMJ(empoignade)
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $updateEtatEmpoignade(empoignade, attacker, defender) { static async $updateEtatEmpoignade(empoignade, attacker, defender) {
const belligerants = [ attacker = attacker ?? RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneurid)
attacker ?? game.actors.get(empoignade.system.empoigneurid), defender = defender ?? RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
defender ?? game.actors.get(empoignade.system.empoigneid)]
if (attacker && defender) {
const belligerants = [attacker, defender]
const removeEmp = empoignade.system.pointsemp == 0 const removeEmp = empoignade.system.pointsemp == 0
if (removeEmp) { if (removeEmp) {
@@ -420,24 +443,27 @@ export class RdDEmpoignade {
})) }))
} }
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async $deleteEmpoignade(empoignade) { static async $deleteEmpoignade(empoignade) {
console.log("DELETE Empoignade", empoignade) console.log("DELETE Empoignade", empoignade)
const defender = game.actors.get(empoignade.system.empoigneid) const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
if (defender) {
const emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid) const emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
await defender.deleteEmbeddedDocuments('Item', [emp.id]) await defender.deleteEmbeddedDocuments('Item', [emp.id])
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async entrainerAuSol(rollData) { static async entrainerAuSol(rollData) {
let attacker = game.actors.get(rollData.attacker.id) const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id) const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) { if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return return
} }
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender) const empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
empoignade.system.ausol = true empoignade.system.ausol = true
await this.$updateEtatEmpoignade(empoignade) await this.$updateEtatEmpoignade(empoignade)
@@ -445,14 +471,14 @@ export class RdDEmpoignade {
await attacker.setEffect(STATUSES.StatusProne, true); await attacker.setEffect(STATUSES.StatusProne, true);
await defender.setEffect(STATUSES.StatusProne, true); await defender.setEffect(STATUSES.StatusProne, true);
let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.hbs'); const msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData); RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async projeterAuSol(rollData) { static async projeterAuSol(rollData) {
let attacker = game.actors.get(rollData.attacker.id) const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id) const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) { if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return return
} }
@@ -467,8 +493,8 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async perteEndurance(rollData, perteMode) { static async perteEndurance(rollData, perteMode) {
let attacker = game.actors.get(rollData.attacker.id) const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id) const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (perteMode == "none" || !RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) { if (perteMode == "none" || !RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return return
} }
@@ -501,11 +527,11 @@ export class RdDEmpoignade {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async deleteLinkedEmpoignade(actorId, empoignade) { static async deleteLinkedEmpoignade(actorId, empoignade) {
let actorDeleteId = (actorId == empoignade.system.empoigneurid) ? empoignade.system.empoigneid : empoignade.system.empoigneurid const actorDeleteId = (actorId == empoignade.system.empoigneurid) ? empoignade.system.empoigneid : empoignade.system.empoigneurid
let actor = game.actors.get(actorDeleteId) const actor = RdDEmpoignade.getActorEmpoignade(actorDeleteId)
let emp = this.getEmpoignadeById(actor, empoignade.system.empoignadeid) const empoignadeOpposant = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
if (emp) { if (actor && empoignadeOpposant) {
await actor.deleteEmbeddedDocuments('Item', [emp.id]) await actor.deleteEmbeddedDocuments('Item', [empoignadeOpposant.id])
} }
} }

View File

@@ -94,6 +94,7 @@ import ChatRollResult from "./roll/chat-roll-result.mjs"
import ExportPdf from "./actor/export-pdf/export-pdf.mjs" import ExportPdf from "./actor/export-pdf/export-pdf.mjs"
import { DialogFlushByDate } from "./chat/dialog-flush-by-date.mjs" import { DialogFlushByDate } from "./chat/dialog-flush-by-date.mjs"
import { Remote } from "./remote.mjs" import { Remote } from "./remote.mjs"
import { RdDActiveEffect } from "./effect/base-active-effect.js"
/** /**
* RdD system * RdD system
@@ -199,6 +200,7 @@ export class SystemReveDeDragon {
// Define custom Entity classes // Define custom Entity classes
console.log(`Initializing Reve de Dragon Documents`) console.log(`Initializing Reve de Dragon Documents`)
CONFIG.Actor.documentClass = RdDBaseActor CONFIG.Actor.documentClass = RdDBaseActor
CONFIG.ActiveEffect.documentClass = RdDActiveEffect
CONFIG.Item.documentClass = RdDItem CONFIG.Item.documentClass = RdDItem
CONFIG.Item.dataModels = { CONFIG.Item.dataModels = {
monnaie: models.RdDModelMonnaie, monnaie: models.RdDModelMonnaie,
@@ -375,7 +377,17 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */ /* -------------------------------------------- */
game.system.rdd.calendrier = new RdDCalendrier() game.system.rdd.calendrier = new RdDCalendrier()
if (Misc.isFirstConnectedGM()) { if (Misc.isFirstConnectedGM()) {
try {
new Migrations().migrate() new Migrations().migrate()
}
catch (erreur) {
const message = `<p>Erreur lors de la migration du système Rêve de Dragon: ${erreur}</p><p>Plus de détails sont sans doute disponibles dans la console de Foundry/du navigateur.</p><p>Merci de nous signaler cetter erreur qu'on puisse ous aider et réparer le problème.</p>`
ui.notifications.error(message)
await ChatMessage.create({
user: game.user.id,
content: message
})
}
this.messageDeBienvenue() this.messageDeBienvenue()
import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => { import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => {
console.log("ClassCounter loaded", moduleCounter) console.log("ClassCounter loaded", moduleCounter)
@@ -397,7 +409,7 @@ export class SystemReveDeDragon {
if (!game.user.isGM && game.user.character == undefined) { if (!game.user.isGM && game.user.character == undefined) {
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !") ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !")
ChatMessage.create({ ChatMessage.create({
content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !", content: `<b>ATTENTION</b> Le joueur ${game.user.name} n'est connecté à aucun personnage !`,
user: game.user.id user: game.user.id
}) })
} }

View File

@@ -117,7 +117,7 @@ export class RdDMeteo {
meteo.nuage.description = RdDMeteo.nuage(meteo.nuage.force); meteo.nuage.description = RdDMeteo.nuage(meteo.nuage.force);
meteo.pluie.description = RdDMeteo.pluie(meteo.pluie.force); meteo.pluie.description = RdDMeteo.pluie(meteo.pluie.force);
ChatMessage.create({ await ChatMessage.create({
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-meteo.hbs', meteo), content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-meteo.hbs', meteo),
whisper: ChatUtility.getGMs() whisper: ChatUtility.getGMs()
}); });

View File

@@ -4,12 +4,10 @@ import { renderTemplate } from "./constants.js";
export class RdDRollResult { export class RdDRollResult {
static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.hbs') { static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.hbs') {
const chatMessage = await ChatUtility.createChatWithRollMode( return await ChatMessage.create(ChatUtility.adaptVisibility(
{ content: await RdDRollResult.buildRollDataHtml(rollData, template) }, { content: await RdDRollResult.buildRollDataHtml(rollData, template) },
actor, { actor: actor, rollMode: rollData.current?.rollmode?.key }
rollData.current?.rollmode?.key ))
)
return chatMessage
} }
static async buildRollDataHtml(rollData, template = 'chat-resultat-general.hbs') { static async buildRollDataHtml(rollData, template = 'chat-resultat-general.hbs') {

View File

@@ -34,9 +34,9 @@ export class RdDRollTables {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getCompetence(toChat = false) { static async getCompetence(toChat = false, rollMode = "gmroll") {
if (toChat == 'liste') { if (toChat == 'liste') {
return await RdDRollTables.listOrRoll('competences', 'Item', ['competence'], toChat, it => 1); return await RdDRollTables.listOrRoll('competences', 'Item', ['competence'], toChat, rollMode, it => 1);
} }
else { else {
return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat); return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat);
@@ -44,56 +44,58 @@ export class RdDRollTables {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getSouffle(toChat = false) { static async getSouffle(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('souffles-de-dragon', 'Item', ['souffle'], toChat); return await RdDRollTables.listOrRoll('souffles-de-dragon', 'Item', ['souffle'], toChat, rollMode);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getQueue(toChat = false) { static async getQueue(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat); return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat, rollMode);
} }
static async getDesirLancinant(toChat = false) { static async getDesirLancinant(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat, return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat, rollMode,
it => it.system.frequence, it => it.system.frequence,
it => it.system.categorie == 'lancinant'); it => it.system.categorie == 'lancinant');
} }
static async getIdeeFixe(toChat = false) { static async getIdeeFixe(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat, return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat, rollMode,
it => it.system.frequence, it => it.system.frequence,
it => it.system.categorie == 'ideefixe'); it => it.system.categorie == 'ideefixe');
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getTeteHR(toChat = false) { static async getTeteHR(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-haut-revants', 'Item', ['tete'], toChat); return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-haut-revants', 'Item', ['tete'], toChat, rollMode);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getTete(toChat = false) { static async getTete(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-tous-personnages', 'Item', ['tete'], toChat); return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-tous-personnages', 'Item', ['tete'], toChat, rollMode);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getOmbre(toChat = false) { static async getOmbre(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('ombres-de-thanatos', 'Item', ['ombre'], toChat); return await RdDRollTables.listOrRoll('ombres-de-thanatos', 'Item', ['ombre'], toChat, rollMode);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getTarot(toChat = true) { static async getTarot(toChat = true, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('tarot-draconique', 'Item', ['tarot'], toChat); return await RdDRollTables.listOrRoll('tarot-draconique', 'Item', ['tarot'], toChat, rollMode);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async listOrRoll(compendium, type, subTypes, toChat, itemFrequence = it => it.system.frequence, filter = it => true) { static async listOrRoll(compendium, type, subTypes, toChat, rollMode,
itemFrequence = it => it.system.frequence,
filter = it => true) {
const table = new CompendiumTable(compendium, type, subTypes); const table = new CompendiumTable(compendium, type, subTypes);
if (toChat == 'liste') { if (toChat == 'liste') {
return await table.toChatMessage(itemFrequence, filter); return await table.toChatMessage(itemFrequence, filter);
} }
const row = await table.getRandom(itemFrequence, filter); const row = await table.getRandom(itemFrequence, filter);
if (row) { if (row) {
await CompendiumTableHelpers.tableRowToChatMessage(row, type); await CompendiumTableHelpers.tableRowToChatMessage(row, type, { rollMode: rollMode });
return row.document; return row.document;
} }
return undefined; return undefined;

View File

@@ -49,7 +49,7 @@ export class RdDTMRDialog extends Dialog {
await PixiTMR.init() await PixiTMR.init()
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.hbs', tmrData); let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.hbs', tmrData);
if (tmrData.mode != 'visu' && !game.user.isGM) { if (tmrData.mode != 'visu' && !game.user.isGM) {
ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatUtility.getGMs() }); await ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatUtility.getGMs() });
} }
return new RdDTMRDialog(html, actor, tmrData) return new RdDTMRDialog(html, actor, tmrData)
} }
@@ -138,7 +138,7 @@ export class RdDTMRDialog extends Dialog {
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')));
// Gestion du cout de montée en points de rêve // Gestion du cout de montée en points de rêve
await this.actor.reveActuelIncDec(this.calculCoutMonteeTMR()); await this.actor.reveActuelIncDec(await this.calculCoutMonteeTMR());
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
// Le reste... // Le reste...
@@ -305,8 +305,8 @@ export class RdDTMRDialog extends Dialog {
await this.$checkQuitterTMR(); await this.$checkQuitterTMR();
} }
calculCoutMonteeTMR() { async calculCoutMonteeTMR() {
return ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse(); return ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - (await this.actor.countMonteeLaborieuse())
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -501,7 +501,7 @@ export class RdDTMRDialog extends Dialog {
rencData.poesie = { extrait: result.poesie, reference: result.reference }; rencData.poesie = { extrait: result.poesie, reference: result.reference };
rencData.message = this.$formatMessageRencontre(rencData, result.message); rencData.message = this.$formatMessageRencontre(rencData, result.message);
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor), whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.hbs`, rencData) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.hbs`, rencData)
}); });
@@ -653,7 +653,7 @@ export class RdDTMRDialog extends Dialog {
this.restoreTMRAfterAction() this.restoreTMRAfterAction()
if (myRoll == 7) { if (myRoll == 7) {
ChatUtility.tellToUser(myRoll + ": Rencontre en " + coordTMR); ChatUtility.tellToUser(myRoll + ": Rencontre en " + coordTMR);
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre()) return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, await this.actor.isMauvaiseRencontre())
} else { } else {
ChatUtility.tellToUser(myRoll + ": Pas de rencontre en " + coordTMR); ChatUtility.tellToUser(myRoll + ": Pas de rencontre en " + coordTMR);
return undefined; return undefined;
@@ -708,7 +708,7 @@ export class RdDTMRDialog extends Dialog {
return; return;
} }
rollData.poesie = await Poetique.getExtrait(); rollData.poesie = await Poetique.getExtrait();
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor), whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData)
}); });
@@ -728,16 +728,16 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
isCaseHumide(tmr) { isCaseHumide(tmr) {
if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) { if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) {
return false; return false
} }
if (this.isCaseMaitrisee(tmr.coord)) { if (this.isCaseMaitrisee(tmr.coord)) {
ChatMessage.create({ ChatMessage.create({
content: tmr.label + ": cette case humide est déja maitrisée grâce à votre Tête <strong>Quête des Eaux</strong>", content: tmr.label + ": cette case humide est déja maitrisée grâce à votre Tête <strong>Quête des Eaux</strong>",
whisper: ChatUtility.getOwners(this.actor) whisper: ChatUtility.getOwners(this.actor)
}); })
return false; return false
} }
return true; return true
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -747,16 +747,16 @@ export class RdDTMRDialog extends Dialog {
content: tmr.label + ": Vous êtes sous le coup d'une Impraticabilité des Ponts : ce pont doit être maîtrisé comme une case humide.", content: tmr.label + ": Vous êtes sous le coup d'une Impraticabilité des Ponts : ce pont doit être maîtrisé comme une case humide.",
whisper: ChatUtility.getOwners(this.actor) whisper: ChatUtility.getOwners(this.actor)
}); });
return true; return true
} }
if (this.isCaseInondee(tmr.coord)) { if (this.isCaseInondee(tmr.coord)) {
ChatMessage.create({ ChatMessage.create({
content: tmr.label + ": cette case est inondée, elle doit être maîtrisée comme une case humide.", content: tmr.label + ": cette case est inondée, elle doit être maîtrisée comme une case humide.",
whisper: ChatUtility.getOwners(this.actor) whisper: ChatUtility.getOwners(this.actor)
}); });
return true; return true
} }
return false; return false
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -825,7 +825,7 @@ export class RdDTMRDialog extends Dialog {
rollData.souffle = await this.actor.ajouterSouffle({ chat: false }) rollData.souffle = await this.actor.ajouterSouffle({ chat: false })
} }
rollData.poesie = await Poetique.getExtrait() rollData.poesie = await Poetique.getExtrait()
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor), whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData)
}) })
@@ -876,7 +876,7 @@ export class RdDTMRDialog extends Dialog {
const reserveSecurite = EffetsDraconiques.isReserveEnSecurite(this.actor); const reserveSecurite = EffetsDraconiques.isReserveEnSecurite(this.actor);
const reserveExtensible = this.isReserveExtensible(coord); const reserveExtensible = this.isReserveExtensible(coord);
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) && (reserveSecurite || reserveExtensible)) { if (!EffetsDraconiques.isUrgenceDraconique(this.actor) && (reserveSecurite || reserveExtensible)) {
ChatMessage.create({ await ChatMessage.create({
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-demande-declencher-sort.hbs`, { content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-demande-declencher-sort.hbs`, {
actor: this.actor, actor: this.actor,
sorts: sorts, sorts: sorts,
@@ -892,13 +892,13 @@ export class RdDTMRDialog extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
lancerSortEnReserve(coord, sortId) { async lancerSortEnReserve(coord, sortId) {
const sort = this.getSortsReserve(coord) const sort = this.getSortsReserve(coord)
.find(it => it.id == sortId); .find(it => it.id == sortId);
if (sort) { if (sort) {
this.processSortReserve(sort); await this.processSortReserve(sort);
} else { } else {
ChatMessage.create({ await ChatMessage.create({
content: "Une erreur est survenue : impossible de récupérer le sort en réserve demandé.", content: "Une erreur est survenue : impossible de récupérer le sort en réserve demandé.",
whisper: ChatUtility.getOwners(this.actor) whisper: ChatUtility.getOwners(this.actor)
}); });
@@ -1137,12 +1137,12 @@ export class RdDTMRDialog extends Dialog {
if (!token) { if (!token) {
return return
} }
if (this.demiReve === token && this.isDemiReveCache()) { if (this.isDemiReveCache() && [EffetsDraconiques.rencontre.code(), EffetsDraconiques.demiReve.code()].includes(token.code)) {
return return
} }
this.pixiTMR.positionToken(token); this.pixiTMR.positionToken(token)
if (!this.allTokens.includes(token)) { if (!this.allTokens.includes(token)) {
this.allTokens.push(token); this.allTokens.push(token)
} }
} }
} }

View File

@@ -49,7 +49,7 @@ export class RdDTokenHud {
static async addExtensionHudCombatV2(html, combatant, actor, token) { static async addExtensionHudCombatV2(html, combatant, actor, token) {
const isPossession = actor.listActionsPossessions().length > 0; const isPossession = actor.listActionsPossessions().length > 0;
const actionsCombat = isPossession ? [] : actor.listAttaques() const actionsCombat = isPossession ? [] : actor.listActions()
const ajustements = combatant?.initiative ? const ajustements = combatant?.initiative ?
[ [
{ label: 'Initiative +1', action: 'delta', value: 1 }, { label: 'Initiative +1', action: 'delta', value: 1 },

View File

@@ -132,9 +132,9 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-entitee.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/carac-entitee.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/competence.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/competence.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.hbs',
@@ -147,7 +147,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/taches.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/jeus.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/jeux.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.hbs',
@@ -173,6 +173,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.hbs', 'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/tooltip-bonmoments.hbs',
//Items //Items
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs', 'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs',
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs', 'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs',
@@ -300,6 +301,7 @@ export class RdDUtility {
Handlebars.registerHelper('grammar-un', str => Grammar.articleIndetermine(str)); Handlebars.registerHelper('grammar-un', str => Grammar.articleIndetermine(str));
Handlebars.registerHelper('grammar-accord', (genre, ...args) => Grammar.accord(genre, args)); Handlebars.registerHelper('grammar-accord', (genre, ...args) => Grammar.accord(genre, args));
Handlebars.registerHelper('json-stringify', object => JSON.stringify(object)) Handlebars.registerHelper('json-stringify', object => JSON.stringify(object))
Handlebars.registerHelper('escapeHtml', object => foundry.utils.escapeHTML(object))
// math // math
Handlebars.registerHelper('math-sum', (...values) => values.slice(0, -1).reduce(Misc.sum(), 0)) Handlebars.registerHelper('math-sum', (...values) => values.slice(0, -1).reduce(Misc.sum(), 0))
@@ -483,7 +485,7 @@ export class RdDUtility {
static filterItemsPerTypeForSheet(formData, itemTypes) { static filterItemsPerTypeForSheet(formData, itemTypes) {
Object.values(ITEM_TYPES).forEach(t => { Object.values(ITEM_TYPES).forEach(t => {
formData[t + 's'] = Misc.arrayOrEmpty(itemTypes[t]) formData[RdDItem.itemTypePluriel(t)] = Misc.arrayOrEmpty(itemTypes[t])
itemTypes[t].forEach(item => item.actions = item.itemActions()) itemTypes[t].forEach(item => item.actions = item.itemActions())
}) })
@@ -680,7 +682,7 @@ export class RdDUtility {
encaissement.dmg = dmg encaissement.dmg = dmg
if (ReglesOptionnelles.isUsing('localisation-aleatoire')) { if (ReglesOptionnelles.isUsing('localisation-aleatoire')) {
encaissement.dmg.loc = dmg.loc ?? await RdDUtility.getLocalisation(targetActor.type) encaissement.dmg.loc = dmg.loc ?? await RdDUtility.getLocalisation(targetActor.type)
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;' encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps'
} }
else { else {
encaissement.dmg.loc = { label: '' } encaissement.dmg.loc = { label: '' }
@@ -689,9 +691,9 @@ export class RdDUtility {
encaissement.armure = armure encaissement.armure = armure
encaissement.penetration = dmg.penetration encaissement.penetration = dmg.penetration
encaissement.total = jetTotal encaissement.total = jetTotal
encaissement.vie = await RdDUtility._evaluatePerte(encaissement.vie, over20); encaissement.vie = await RdDUtility._evaluatePerte(encaissement.vie, over20)
encaissement.endurance = await RdDUtility._evaluatePerte(encaissement.endurance, over20); encaissement.endurance = await RdDUtility._evaluatePerte(encaissement.endurance, over20)
return encaissement; return encaissement
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -750,12 +752,12 @@ export class RdDUtility {
actor.tmrApp.positionnerDemiReve(coord); actor.tmrApp.positionnerDemiReve(coord);
}); });
// Gestion spécifique des sorts en réserve multiples (ie têtes) // Gestion spécifique des sorts en réserve multiples (ie têtes)
$(html).on("click", '.declencher-sort-reserve', event => { $(html).on("click", '.declencher-sort-reserve', async event => {
let coord = event.currentTarget.attributes['data-tmr-coord'].value; let coord = event.currentTarget.attributes['data-tmr-coord'].value;
let sortId = event.currentTarget.attributes['data-sort-id'].value; let sortId = event.currentTarget.attributes['data-sort-id'].value;
let actorId = event.currentTarget.attributes['data-actor-id'].value; let actorId = event.currentTarget.attributes['data-actor-id'].value;
let actor = game.actors.get(actorId); let actor = game.actors.get(actorId);
actor.tmrApp.lancerSortEnReserve(coord, sortId); await actor.tmrApp.lancerSortEnReserve(coord, sortId);
// TODO: supprimer le message? // TODO: supprimer le message?
}); });
@@ -844,12 +846,12 @@ export class RdDUtility {
return game.user.character; return game.user.character;
} }
if (msgPlayer != undefined) { if (msgPlayer != undefined) {
msgPlayer += "<br>vous pouvez sélectionner un seul token lié à un personnage"; msgPlayer += "<br>vous pouvez sélectionner un seul token lié à un personnage"
msgPlayer += "<br>vous devez être connecté comme joueur avec un personnage sélectionné"; msgPlayer += "<br>vous devez être connecté comme joueur avec un personnage sélectionné";
ui.notifications.warn(msgPlayer); ui.notifications.warn(msgPlayer);
ChatMessage.create({ content: msgPlayer, whisper: [game.user] }); ChatMessage.create({ content: msgPlayer, whisper: [game.user] })
} }
return undefined; return undefined
} }
static doWithSelectedActor(onSelected = () => { }, filter = actor => true) { static doWithSelectedActor(onSelected = () => { }, filter = actor => true) {
@@ -942,9 +944,9 @@ export class RdDUtility {
content: `<p>Etes vous certain de vouloir supprimer: ${item.name}?</p>`, content: `<p>Etes vous certain de vouloir supprimer: ${item.name}?</p>`,
title: `Supprimer ${item.name}`, title: `Supprimer ${item.name}`,
buttonLabel: "Supprimer", buttonLabel: "Supprimer",
onAction: () => { onAction: async () => {
console.log('Delete : ', itemId); console.log('Delete : ', itemId);
actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false }); await actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false });
} }
}; };
if (item.isConteneurNonVide()) { if (item.isConteneurNonVide()) {
@@ -955,9 +957,9 @@ export class RdDUtility {
'deleteall': { 'deleteall': {
icon: '<i class="fas fa-check"></i>', icon: '<i class="fas fa-check"></i>',
label: "Supprimer conteneur et contenu", label: "Supprimer conteneur et contenu",
callback: () => { callback: async () => {
console.log("Delete : ", itemId); console.log("Delete : ", itemId);
actor.deleteAllConteneur(itemId, { renderSheet: false }); await actor.deleteAllConteneur(itemId, { renderSheet: false });
} }
} }
}); });
@@ -995,10 +997,10 @@ export class RdDUtility {
} }
/*-------------------------------------------- */ /*-------------------------------------------- */
static checkThanatosXP(item) { static async checkThanatosXP(item) {
if (item.isCompetencePersonnage() && item.name.includes('Thanatos')) { if (item.isCompetencePersonnage() && item.name.includes('Thanatos')) {
let message = "Vous avez mis des points d'Expérience en Thanatos !<br>Vous devez réduire manuellement d'un même montant d'XP une autre compétence Draconique."; let message = "Vous avez mis des points d'Expérience en Thanatos !<br>Vous devez réduire manuellement d'un même montant d'XP une autre compétence Draconique.";
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getUserAndGMs(), whisper: ChatUtility.getUserAndGMs(),
content: message content: message
}); });

View File

@@ -43,13 +43,15 @@ export default class ChatRollResult {
async display(roll, impacts) { async display(roll, impacts) {
this.prepareDisplay(roll) this.prepareDisplay(roll)
const chatMessage = await ChatUtility.createChatWithRollMode( const chatMessage = await ChatMessage.create(ChatUtility.adaptVisibility(
{ {
content: await this.buildRollHtml(roll) content: await this.buildRollHtml(roll)
}, },
roll.active.actor, {
roll.current?.rollmode?.key actor: roll.active.actor,
) rollmode: roll.current?.rollmode?.key
}
))
await this.saveChatMessageRoll(chatMessage, roll, impacts) await this.saveChatMessageRoll(chatMessage, roll, impacts)
return chatMessage return chatMessage
@@ -105,8 +107,8 @@ export default class ChatRollResult {
if (attaque && if (attaque &&
(roll.rolled.isEchec || !roll.current.defense.isEsquive) && (roll.rolled.isEchec || !roll.current.defense.isEsquive) &&
(attaque.particuliere == 'force' || 'charge' == attaque.tactique?.key)) { (attaque.particuliere == 'force' || 'charge' == attaque.tactique?.key)) {
const taille = defender.system.carac.taille.value const taille = defender.getTaille()
const impact = attacker.system.carac.force.value + roll.attackerRoll?.dmg.dmgArme const impact = attacker.getForce() + roll.attackerRoll?.dmg.dmgArme
return { return {
raison: 'charge' == attaque.tactique?.key ? 'charge' : 'particulière en force', raison: 'charge' == attaque.tactique?.key ? 'charge' : 'particulière en force',
taille: taille, taille: taille,
@@ -200,6 +202,7 @@ export default class ChatRollResult {
const chatMessage = ChatUtility.getChatMessage(event) const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage) const savedRoll = this.loadChatMessageRoll(chatMessage)
const actor = this.getActiveActor(savedRoll) const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, it => it.rollAppelChance( Misc.doIfOwner(actor, it => it.rollAppelChance(
() => this.onAppelChanceSuccess(savedRoll, chatMessage), () => this.onAppelChanceSuccess(savedRoll, chatMessage),
() => this.onAppelChanceEchec(savedRoll, chatMessage)) () => this.onAppelChanceEchec(savedRoll, chatMessage))
@@ -208,6 +211,7 @@ export default class ChatRollResult {
async onAppelChanceSuccess(roll, chatMessage) { async onAppelChanceSuccess(roll, chatMessage) {
roll.type.retry = true roll.type.retry = true
roll.type.appelChance = true
await this.updateChatMessage(chatMessage, roll) await this.updateChatMessage(chatMessage, roll)
const callbacks = [ChatUtility.remover(chatMessage)] const callbacks = [ChatUtility.remover(chatMessage)]

View File

@@ -9,6 +9,8 @@ export const ROLL_TYPE_MEDITATION = 'meditation'
export const ROLL_TYPE_OEUVRE = 'oeuvre' export const ROLL_TYPE_OEUVRE = 'oeuvre'
export const ROLL_TYPE_SORT = 'sort' export const ROLL_TYPE_SORT = 'sort'
export const ROLL_TYPE_TACHE = 'tache' export const ROLL_TYPE_TACHE = 'tache'
export const ROLL_TYPE_APPEL_CHANCE = 'appel-chance'
export const ROLL_TYPE_REVE_RESISTANCE = 'reve-resistance'
export const ATTAQUE_ROLL_TYPES = [ROLL_TYPE_ATTAQUE] export const ATTAQUE_ROLL_TYPES = [ROLL_TYPE_ATTAQUE]
export const COMBAT_ROLL_TYPES = [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE] export const COMBAT_ROLL_TYPES = [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE]

View File

@@ -50,6 +50,8 @@ import { RollPartResistance } from "./roll-part-resistance.mjs";
import { RollTypePossession } from "./roll-type-possession.mjs"; import { RollTypePossession } from "./roll-type-possession.mjs";
import { RollPartPossession } from "./roll-part-possession.mjs"; import { RollPartPossession } from "./roll-part-possession.mjs";
import { RollPartApprecier } from "./roll-part-apprecier.mjs"; import { RollPartApprecier } from "./roll-part-apprecier.mjs";
import { RollTypeAppelChance } from "./roll-type-appel-chance.mjs";
import { RollTypeReveResistance } from "./roll-type-resistance.mjs";
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
@@ -65,7 +67,8 @@ export const ALL_ROLL_TYPES = [
new RollTypeCuisine(), new RollTypeCuisine(),
new RollTypeOeuvre(), new RollTypeOeuvre(),
new RollTypeJeu(), new RollTypeJeu(),
// new RollTypeResistance ?? new RollTypeAppelChance(),
new RollTypeReveResistance(),
// new RollTypeFixedCarac ?? // new RollTypeFixedCarac ??
] ]
@@ -290,7 +293,6 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
return rollData.type?.allowed return rollData.type?.allowed
? ROLL_PARTS.filter(p => RollDialog.$isIntersecting(rollData.type.allowed, p.rollTypes)) ? ROLL_PARTS.filter(p => RollDialog.$isIntersecting(rollData.type.allowed, p.rollTypes))
: ROLL_PARTS : ROLL_PARTS
} }
/** pre-configure les paramètres des différentes parties de la fenêtre (par exemple, prépare les listes de caractéristiques/compétences */ /** pre-configure les paramètres des différentes parties de la fenêtre (par exemple, prépare les listes de caractéristiques/compétences */
@@ -380,7 +382,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
this.rollData = rollData this.rollData = rollData
this.rollOptions = { this.rollOptions = {
callbacks: [ callbacks: [
async r => await r.active.actor.appliquerAjoutExperience(r), async r => await r.active.actor.ajoutExperience(r),
async r => await r.active.actor.appliquerAppelMoral(r), async r => await r.active.actor.appliquerAppelMoral(r),
...(rollOptions.callbacks ?? []) ...(rollOptions.callbacks ?? [])
], ],
@@ -479,16 +481,13 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
RollBasicParts.loadSurprises(rollData, this.getSelectedType().code) RollBasicParts.loadSurprises(rollData, this.getSelectedType().code)
rollData.type.label = this.getSelectedType()?.title(rollData) rollData.type.label = this.getSelectedType()?.title(rollData)
const visibleRollParts = this.getActiveParts() this.getActiveParts().forEach(p => p.applyExternalImpacts(this.getActiveParts(), rollData))
visibleRollParts.forEach(p => p.applyExternalImpacts(visibleRollParts, rollData)) this.setSpecialComp(this.getActiveParts());
this.getActiveParts().forEach(p => p.prepareContext(rollData))
this.setSpecialComp(visibleRollParts);
visibleRollParts.forEach(p => p.prepareContext(rollData))
RollDialog.calculAjustement(rollData) RollDialog.calculAjustement(rollData)
const templates = visibleRollParts.map(p => p.toTemplateData()) const templates = this.getActiveParts().map(p => p.toTemplateData())
const context = await super._prepareContext() const context = await super._prepareContext()
return foundry.utils.mergeObject( return foundry.utils.mergeObject(
{ {
@@ -569,7 +568,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
} }
async defaultCallback(roll, rolled) { async defaultCallback(roll, rolled) {
await roll.active.actor.appliquerAjoutExperience(roll) await roll.active.actor.ajoutExperience(roll)
await roll.active.actor.appliquerAppelMoral(roll) await roll.active.actor.appliquerAppelMoral(roll)
} }

View File

@@ -1,4 +1,5 @@
import { Grammar } from "../grammar.js" import { Grammar } from "../grammar.js"
import { CARACS } from "../rdd-carac.js"
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js" import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
import { ROLL_TYPE_SORT } from "./roll-constants.mjs" import { ROLL_TYPE_SORT } from "./roll-constants.mjs"
import { RollPartCheckbox } from "./roll-part-checkbox.mjs" import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
@@ -20,7 +21,7 @@ export class RollPartAstrologique extends RollPartCheckbox {
} }
isJetChance(rollData) { isJetChance(rollData) {
return Grammar.includesLowerCaseNoAccent(rollData.current.carac.key, 'chance') return Grammar.includesLowerCaseNoAccent(rollData.current.carac.key, CARACS.CHANCE)
} }
$isUsingAstrologie() { $isUsingAstrologie() {

View File

@@ -35,7 +35,8 @@ export class RollPartAttaque extends RollPartSelect {
loadRefs(rollData) { loadRefs(rollData) {
const refs = this.getRefs(rollData) const refs = this.getRefs(rollData)
const attaques = rollData.active.actor.listAttaques() const attaques = rollData.active.actor.listActions()
.filter(it => !it.initOnly)
.sort(Misc.descending(it => it.comp?.system.niveau ?? -8)) .sort(Misc.descending(it => it.comp?.system.niveau ?? -8))
refs.all = attaques.map(it => RollPartAttaque.$extractAttaque(it, rollData)) refs.all = attaques.map(it => RollPartAttaque.$extractAttaque(it, rollData))
this.filterAttaquesInitiative(rollData) this.filterAttaquesInitiative(rollData)
@@ -186,7 +187,9 @@ export class RollPartAttaque extends RollPartSelect {
part.setDiff(rollData, { type: DIFF.DEFAUT }) part.setDiff(rollData, { type: DIFF.DEFAUT })
} }
else { else {
if (!rollData.type.appelChance){
part.setDiff(rollData, { type: DIFF.ATTAQUE, diff: current.initialDiff }) part.setDiff(rollData, { type: DIFF.ATTAQUE, diff: current.initialDiff })
}
current.initialDiff = undefined current.initialDiff = undefined
} }
break break

View File

@@ -41,7 +41,7 @@ export class RollPartCheckbox extends RollPart {
} }
getCheckboxLabelAjustement(rollData) { getCheckboxLabelAjustement(rollData) {
return `${this.getCheckboxIcon(rollData)} ${this.getRefs(rollData).label}` return `${this.getCheckboxIcon(rollData)} ${this.getCheckboxLabel(rollData)}`
} }
async _onRender(rollDialog, context, options) { async _onRender(rollDialog, context, options) {

View File

@@ -27,7 +27,7 @@ export class RollPartComp extends RollPartSelect {
const selected = this.getSelected(rollData) const selected = this.getSelected(rollData)
const all = this.$getActorComps(rollData) const all = this.$getActorComps(rollData)
const selectedComp = selected.key const selectedComp = selected.key
if (selected.forced && selectedComp) { if (selected.forced && selectedComp!= undefined ) {
refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selectedComp)) refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selectedComp))
if (refs.all.length == 0) { if (refs.all.length == 0) {
if (selected.key && selected.key.length > 0) { if (selected.key && selected.key.length > 0) {
@@ -47,9 +47,12 @@ export class RollPartComp extends RollPartSelect {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
const selectedCarac = RollPart.getSelectedPart(rollData, PART_CARAC) const selectedCarac = RollPart.getSelectedPart(rollData, PART_CARAC)
const selectedDiff = RollPart.getSelectedPart(rollData, PART_DIFF) const selectedDiff = RollPart.getSelectedPart(rollData, PART_DIFF)
if (!rollData.type.appelChance){
this.rollPartCarac.selectByKey(rollData, selectedCarac?.key ?? current.comp.system.defaut_carac) this.rollPartCarac.selectByKey(rollData, selectedCarac?.key ?? current.comp.system.defaut_carac)
this.rollPartDiff.setDiff(rollData, selectedDiff?.value ?? current.comp.system.default_diffLibre) this.rollPartDiff.setDiff(rollData, selectedDiff?.value ?? current.comp.system.default_diffLibre)
} }
}
} }
choices(refs) { return refs.comps } choices(refs) { return refs.comps }

View File

@@ -10,6 +10,11 @@ export class RollPartConditions extends RollPart {
settingMin() { return RollPart.settingKey(this, 'min') } settingMin() { return RollPart.settingKey(this, 'min') }
settingMax() { return RollPart.settingKey(this, 'max') } settingMax() { return RollPart.settingKey(this, 'max') }
visible(rollData) {
const current = this.getCurrent(rollData)
return !current.hide
}
onReady(rollParts) { onReady(rollParts) {
game.settings.register(SYSTEM_RDD, this.settingMin(), game.settings.register(SYSTEM_RDD, this.settingMin(),
{ {
@@ -36,6 +41,7 @@ export class RollPartConditions extends RollPart {
restore(rollData) { restore(rollData) {
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
current.value = this.getSaved(rollData)?.value ?? current.value ?? 0 current.value = this.getSaved(rollData)?.value ?? current.value ?? 0
current.hide = this.getSaved(rollData)?.hide
} }

View File

@@ -43,14 +43,13 @@ export class RollPartCuisine extends RollPartSelect {
const recettes = actor.items const recettes = actor.items
.filter(it => it.type == ITEM_TYPES.recettecuisine) .filter(it => it.type == ITEM_TYPES.recettecuisine)
.map(RollPartCuisine.$extractPreparationRecette) .map(it => RollPartCuisine.$extractPreparationRecette(refs.cuisine, it))
const ingredientsBruts = actor.items const ingredientsBruts = actor.items
.filter(it => it.getUtilisationCuisine() == 'brut') .filter(it => it.getUtilisationCuisine() == 'brut')
.map(RollPartCuisine.$extractPreparationBrut) .map(it => RollPartCuisine.$extractPreparationBrut(refs.cuisine, it))
refs.preparations = [RollPartCuisine.$preparationBasique(), ...recettes, ...ingredientsBruts] refs.preparations = [RollPartCuisine.$preparationBasique(refs.cuisine), ...recettes, ...ingredientsBruts]
refs.preparations.forEach(p => p.comp = refs.cuisine)
if (refs.preparations.length > 0) { if (refs.preparations.length > 0) {
this.$selectPreparation(rollData) this.$selectPreparation(rollData)
this.$restoreSavedOptions(rollData) this.$restoreSavedOptions(rollData)
@@ -73,7 +72,7 @@ export class RollPartCuisine extends RollPartSelect {
choices(refs) { return refs.preparations } choices(refs) { return refs.preparations }
static $preparationBasique() { static $preparationBasique(cuisine) {
return { return {
key: '', key: '',
label: "Improvisation du moment", label: "Improvisation du moment",
@@ -85,10 +84,12 @@ export class RollPartCuisine extends RollPartSelect {
proportionsMax: 50, proportionsMax: 50,
value: 0, value: 0,
fabriquer: false, fabriquer: false,
qualite: cuisine.system.niveau,
comp: cuisine,
} }
} }
static $extractPreparationRecette(recette) { static $extractPreparationRecette(cuisine, recette) {
const proportions = recette.system.sust ?? 1 const proportions = recette.system.sust ?? 1
return { return {
key: recette.id, key: recette.id,
@@ -102,10 +103,12 @@ export class RollPartCuisine extends RollPartSelect {
value: -recette.system.niveau, value: -recette.system.niveau,
recette: recette, recette: recette,
fabriquer: true, fabriquer: true,
qualite: recette.system.niveau,
comp: cuisine,
} }
} }
static $extractPreparationBrut(ingredient) { static $extractPreparationBrut(cuisine, ingredient) {
return { return {
key: ingredient.id, key: ingredient.id,
label: ingredient.name + ' cuisiné', label: ingredient.name + ' cuisiné',
@@ -118,6 +121,8 @@ export class RollPartCuisine extends RollPartSelect {
value: 0, value: 0,
ingredient: ingredient, ingredient: ingredient,
fabriquer: true, fabriquer: true,
qualite: cuisine.system.niveau,
comp: cuisine,
} }
} }

View File

@@ -131,7 +131,11 @@ export class RollPartDefense extends RollPartSelect {
switch (part.code) { switch (part.code) {
case PART_CARAC: return part.filterCaracs(rollData, refs.defenses.length > 0 ? [current.carac] : ['impossible']) case PART_CARAC: return part.filterCaracs(rollData, refs.defenses.length > 0 ? [current.carac] : ['impossible'])
case PART_COMP: return part.filterComps(rollData, refs.defenses.length > 0 ? [current.comp?.name] : ['impossible']) case PART_COMP: return part.filterComps(rollData, refs.defenses.length > 0 ? [current.comp?.name] : ['impossible'])
case PART_DIFF: return part.setDiff(rollData, this.getDiffDefense(rollData)) case PART_DIFF:
if (!rollData.type.appelChance) {
return part.setDiff(rollData, this.getDiffDefense(rollData))
}
return
case PART_SIGN: return part.setArme(rollData, this.getArmeDisparate(rollData), current.forceRequise) case PART_SIGN: return part.setArme(rollData, this.getArmeDisparate(rollData), current.forceRequise)
} }
} }

View File

@@ -37,7 +37,7 @@ export class RollPartDiff extends RollPart {
} }
const current = this.getCurrent(rollData) const current = this.getCurrent(rollData)
/* TODO: affiner les cas où afficher ou non. devrait s'afficher pour les jets basiques (même si pas d'opposant sélectionné)*/ /* TODO: affiner les cas où afficher ou non. devrait s'afficher pour les jets basiques (même si pas d'opposant sélectionné)*/
return Object.values(DIFF).includes(current.type) return (DIFF.AUCUN !=current.type) && Object.values(DIFF).includes(current.type)
} }
prepareContext(rollData) { prepareContext(rollData) {

View File

@@ -15,18 +15,32 @@ export class RollPartEncTotal extends RollPartCheckbox {
&& RdDItemCompetence.isMalusEncombrementTotal(rollData.current.comp?.key) && RdDItemCompetence.isMalusEncombrementTotal(rollData.current.comp?.key)
} }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
refs.malusEnc = - Math.floor(rollData.active.actor.getEncTotal())
const current = this.getCurrent(rollData)
current.value = refs.malusEnc
}
async _onRender(rollDialog, context, options) { async _onRender(rollDialog, context, options) {
super._onRender(rollDialog, context, options) super._onRender(rollDialog, context, options)
const inputMalusEnc = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="malusenc"]`) const inputMalusEnc = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="malusenc"]`)
inputMalusEnc?.addEventListener("change", e => { inputMalusEnc?.addEventListener("change", e => {
this.getCurrent(rollDialog.rollData).value = parseInt(e.currentTarget.value) const malusEnc = Math.floor(e.currentTarget.value)
const rollData = rollDialog.rollData
const refs = this.getRefs(rollData)
const current = this.getCurrent(rollData)
if (refs.malusEnc == current.value) {
current.value = malusEnc
}
refs.malusEnc = malusEnc
rollDialog.render() rollDialog.render()
}) })
} }
getCheckboxIcon(rollData) { return `<img src="${RDD_CONFIG.icons.surenc}">` } getCheckboxIcon(rollData) { return `<img src="${RDD_CONFIG.icons.surenc}">` }
getCheckboxLabel(rollData) { return "Enc. total" } getCheckboxLabel(rollData) { return "Enc. total" }
getCheckboxValue(rollData) { return - rollData.active.actor.getEncTotal() } getCheckboxValue(rollData) { return this.getCurrent(rollData).value }
} }

View File

@@ -28,7 +28,8 @@ export class RollPartSort extends RollPartSelect {
this.setCurrent(rollData, { this.setCurrent(rollData, {
key: saved.key, key: saved.key,
isReserve: saved.isReserve, isReserve: saved.isReserve,
ptreve: saved.ptreve ptreve: saved.ptreve,
value: saved.value,
}) })
} }
@@ -37,7 +38,8 @@ export class RollPartSort extends RollPartSelect {
this.setSaved(targetData, { this.setSaved(targetData, {
key: current.key, key: current.key,
isReserve: current.isReserve, isReserve: current.isReserve,
ptreve: current.ptreve ptreve: current.ptreve,
value: current.value,
}) })
} }
@@ -98,7 +100,7 @@ export class RollPartSort extends RollPartSelect {
const sort = { label: current.label, value: current.value } const sort = { label: current.label, value: current.value }
const reserve = current.isReserve ? [{ label: `Mise en réserve en ${this.getCoord(rollData)}` }] : [] const reserve = current.isReserve ? [{ label: `Mise en réserve en ${this.getCoord(rollData)}` }] : []
const bonusCase = current.bonusCase ? [{ label: `Bonus case +${current.bonusCase}%` }] : [] const bonusCase = current.bonusCase ? [{ label: `Bonus case +${current.bonusCase}%` }] : []
const reve = { label: `Rêve ${current.ptreve}` } const reve = { label: `Dépense de rêve ${current.ptreve}` }
return [sort, ...bonusCase, reve, ...reserve] return [sort, ...bonusCase, reve, ...reserve]
} }
return [] return []
@@ -106,9 +108,12 @@ export class RollPartSort extends RollPartSelect {
$selectSort(rollData, values) { $selectSort(rollData, values) {
const current = this.selectByKey(rollData, values.key) const current = this.selectByKey(rollData, values.key)
if (values.ptreve) { if (values.ptreve != undefined) {
current.ptreve = values.ptreve current.ptreve = values.ptreve
} }
if (current.isDiffVariable && values.value != undefined) {
current.value = values.value
}
if (values.isReserve != undefined) { if (values.isReserve != undefined) {
current.isReserve = values.isReserve current.isReserve = values.isReserve
} }

View File

@@ -0,0 +1,31 @@
import { CARACS } from "../rdd-carac.js"
import { DIFF, ROLL_TYPE_APPEL_CHANCE } from "./roll-constants.mjs"
import { RollType } from "./roll-type.mjs"
export class RollTypeAppelChance extends RollType {
get code() { return ROLL_TYPE_APPEL_CHANCE }
get name() { return `fait appel à la chance` }
get icon() { return `systems/foundryvtt-reve-de-dragon/assets/ui/chance.svg` }
get chatResultTemplate() { return `systems/foundryvtt-reve-de-dragon/templates/roll/result/chat-appel-chance.hbs` }
title(rollData) {
return this.name
}
setRollDataType(rollData) {
foundry.utils.mergeObject(rollData, {
selected: {
carac: { key: CARACS.CHANCE_ACTUELLE, forced: true },
diff: { value: 0, type: '' },
comp: { key: '', forced: true },
conditions: { hide: true }
}
})
super.setRollDataType(rollData)
}
onSelect(rollData) {
this.setDiffType(rollData, DIFF.AUCUN)
}
}

View File

@@ -9,7 +9,8 @@ export class RollTypeCuisine extends RollType {
get code() { return ROLL_TYPE_CUISINE } get code() { return ROLL_TYPE_CUISINE }
get name() { return `Cuisiner un plat` } get name() { return `Cuisiner un plat` }
visible(rollData) { return rollData.active.actor.isPersonnage() } visible(rollData) { return rollData.active.actor.isPersonnage()
&& rollData.active.actor.getCompetence('Cuisine') != undefined }
title(rollData) { title(rollData) {
const current = rollData.current[PART_CUISINE] const current = rollData.current[PART_CUISINE]
return current.recette ? `prépare une recette: ${current.label}` : `prépare: ${current.label}` return current.recette ? `prépare une recette: ${current.label}` : `prépare: ${current.label}`
@@ -21,9 +22,7 @@ export class RollTypeCuisine extends RollType {
getResult(rollData, impacts) { getResult(rollData, impacts) {
const current = rollData.current[PART_CUISINE] const current = rollData.current[PART_CUISINE]
const diff = -current.value const qualite = rollData.rolled.ptQualite + current.qualite
const cuisine = rollData.refs[PART_CUISINE].cuisine
const qualite = rollData.rolled.ptQualite + (rollData.rolled.isSuccess ? diff : Math.min(diff, cuisine.system.niveau))
const result = { const result = {
qualite: qualite, qualite: qualite,
@@ -49,6 +48,7 @@ export class RollTypeCuisine extends RollType {
} }
return result return result
} }
onApplyImpacts(roll, impacts) { onApplyImpacts(roll, impacts) {
if (roll.result.plat) { if (roll.result.plat) {
// le plat n'est pas créé immédiatement, il faut donc retrouver l'id // le plat n'est pas créé immédiatement, il faut donc retrouver l'id

View File

@@ -8,7 +8,10 @@ export class RollTypeJeu extends RollType {
get code() { return ROLL_TYPE_JEU } get code() { return ROLL_TYPE_JEU }
get name() { return `Jouer` } get name() { return `Jouer` }
visible(rollData) { return rollData.active.actor.isPersonnage() } visible(rollData) {
return rollData.active.actor.isPersonnage()
&& rollData.active.actor.getCompetence('Jeu') != undefined
}
title(rollData) { title(rollData) {
if (rollData.opponent) { if (rollData.opponent) {
return `joue contre` return `joue contre`

View File

@@ -0,0 +1,31 @@
import { CARACS } from "../rdd-carac.js"
import { DIFF, ROLL_TYPE_REVE_RESISTANCE } from "./roll-constants.mjs"
import { RollType } from "./roll-type.mjs"
export class RollTypeReveResistance extends RollType {
get code() { return ROLL_TYPE_REVE_RESISTANCE }
get name() { return `fait un jet de résistance` }
get icon() { return `systems/foundryvtt-reve-de-dragon/assets/ui/resistance.svg` }
get chatResultTemplate() { return `systems/foundryvtt-reve-de-dragon/templates/roll/result/chat-reve-resistance.hbs` }
title(rollData) {
return this.name
}
setRollDataType(rollData) {
foundry.utils.mergeObject(rollData, {
selected: {
carac: { key: CARACS.REVE_ACTUEL, forced: true },
diff: { value: -8, type: '' },
comp: { key: '', forced: true },
conditions: { hide: true }
}
})
super.setRollDataType(rollData)
}
onSelect(rollData) {
this.setDiffType(rollData, DIFF.DEFAUT)
}
}

View File

@@ -10,7 +10,7 @@ const listeReglesOptionnelles = [
{ group: 'Récupération', name: 'recuperation-reve', descr: "Récupérer le rêve pendant la nuit (les jets sont toujours faits pour les Rêves de Dragons)"}, { group: 'Récupération', name: 'recuperation-reve', descr: "Récupérer le rêve pendant la nuit (les jets sont toujours faits pour les Rêves de Dragons)"},
{ group: 'Récupération', name: 'recuperation-moral', descr: "Le moral revient vers 0 durant Château Dormant"}, { group: 'Récupération', name: 'recuperation-moral', descr: "Le moral revient vers 0 durant Château Dormant"},
{ group: 'Règles de combat', name: 'armes-equipees', descr: "Proposer uniquement les armes équipées au combat", default: false},
{ group: 'Règles de combat', name: 'localisation-aleatoire', descr: "Proposer une localisation aléatoire des blessures" }, { group: 'Règles de combat', name: 'localisation-aleatoire', descr: "Proposer une localisation aléatoire des blessures" },
{ group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" }, { group: 'Règles de combat', name: 'recul', descr: "Appliquer le recul en cas de particulière en force ou de charge" },
{ group: 'Règles de combat', name: 'acrobatie-pour-recul', descr: "L'acrobatie aide à ne pas chuter en cas de recul" , default: false }, { group: 'Règles de combat', name: 'acrobatie-pour-recul', descr: "L'acrobatie aide à ne pas chuter en cas de recul" , default: false },
@@ -25,6 +25,7 @@ const listeReglesOptionnelles = [
{ group: 'Affichage', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false }, { group: 'Affichage', name: 'afficher-colonnes-reussite', descr: "Afficher le nombre de colonnes de réussite ou d'échec", default: false },
{ group: 'Affichage', name: 'afficher-prix-joueurs', descr: "Afficher le prix de l'équipement des joueurs", uniquementJoueur: true}, { group: 'Affichage', name: 'afficher-prix-joueurs', descr: "Afficher le prix de l'équipement des joueurs", uniquementJoueur: true},
{ group: 'Affichage', name: 'afficher-table-source', descr: "Afficher la table d'origine des tirages aléatoires", default: false },
{ 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"},

View File

@@ -4,6 +4,7 @@ import { Grammar } from "../grammar.js";
import { RdDItem } from "../item.js"; import { RdDItem } from "../item.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDDice } from "../rdd-dice.js"; import { RdDDice } from "../rdd-dice.js";
import { ReglesOptionnelles } from "./regles-optionnelles.js";
const COMPENDIUM_SETTING_PREFIX = 'compendium-'; const COMPENDIUM_SETTING_PREFIX = 'compendium-';
@@ -289,24 +290,28 @@ export class CompendiumTableHelpers {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async tableRowToChatMessage(row, type, options = { showSource: true }) { static async tableRowToChatMessage(row, type, options = {}) {
if (options.showSource == undefined){
options.showSource = ReglesOptionnelles.isUsing('afficher-table-source')
}
if (!row) { if (!row) {
return; return
} }
const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table-roll.hbs', { const flavorContent = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-compendium-table-roll.hbs', {
roll: row.roll, roll: row.roll,
document: row.document, document: row.document,
typeName: Misc.typeName(type, row.document?.type ?? 'objet'), typeName: Misc.typeName(type, row.document?.type ?? 'objet'),
isGM: game.user.isGM, isGM: game.user.isGM,
options options: { showSource: options.showSource }
}); })
const messageData = { await ChatMessage.create(ChatUtility.adaptVisibility(
{
user: game.user.id, user: game.user.id,
rolls: [row.roll], rolls: [row.roll],
sound: CONFIG.sounds.dice, sound: CONFIG.sounds.dice,
content: flavorContent content: flavorContent
}; },
await ChatUtility.createChatWithRollMode(messageData) { rollMode: options.rollMode }))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -316,13 +321,14 @@ export class CompendiumTableHelpers {
typeName: typeName ?? Misc.typeName(type, subTypes[0]), typeName: typeName ?? Misc.typeName(type, subTypes[0]),
table, table,
isGM: game.user.isGM, isGM: game.user.isGM,
}); })
const messageData = { await ChatMessage.create(ChatUtility.adaptVisibility(
{
user: game.user.id, user: game.user.id,
whisper: [game.user], whisper: [game.user],
content: flavorContent content: flavorContent
}; }
await ChatUtility.createChatWithRollMode(messageData) ))
} }
} }

View File

@@ -107,7 +107,7 @@ export class AppAstrologie extends Application {
const detail = foundry.utils.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.lectures.forEach(lecture => lecture.actorName = game.actors.get(lecture.actorId).name ?? "Inconnu"); detail.lectures.forEach(lecture => lecture.actorName = game.actors.get(lecture.actorId)?.getAlias() ?? "Inconnu");
return detail; return detail;
} }

View File

@@ -8,7 +8,7 @@ export class DialogRepos extends Dialog {
if (!actor.isPersonnage()) { if (!actor.isPersonnage()) {
return return
} }
if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !actor.hasPlayerOwner) { if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !actor.isPersonnageJoueur()) {
foundry.utils.mergeObject(actor.system.sommeil, { foundry.utils.mergeObject(actor.system.sommeil, {
"nouveaujour": true, "nouveaujour": true,
"insomnie": EffetsDraconiques.isSujetInsomnie(actor), "insomnie": EffetsDraconiques.isSujetInsomnie(actor),

View File

@@ -22,7 +22,8 @@ export class DialogStress extends Dialog {
} }
constructor(dialogData, html) { constructor(dialogData, html) {
const options = { classes: ["DialogStress"], const options = {
classes: ["DialogStress"],
width: 400, width: 400,
height: 'fit-content', height: 'fit-content',
'z-index': 99999 'z-index': 99999
@@ -49,9 +50,12 @@ export class DialogStress extends Dialog {
const stress = Number(this.html.find("form.rdddialogstress input[name='stress']").val()); const stress = Number(this.html.find("form.rdddialogstress input[name='stress']").val());
const compteur = (this.html.find("form.rdddialogstress input[name='immediat']").prop("checked")) ? 'experience' : 'stress'; const compteur = (this.html.find("form.rdddialogstress input[name='immediat']").prop("checked")) ? 'experience' : 'stress';
await Promise.all(
this.dialogData.actors.filter(it => it.selected) this.dialogData.actors.filter(it => it.selected)
.map(it => game.actors.get(it.id)) .map(actor => game.actors.get(actor.id))
.forEach(async actor => await actor.distribuerStress(compteur, stress, motif)); .filter(actor => actor != undefined)
.map(actor => actor.distribuerStress(compteur, stress, motif))
)
} }
async onSelectActor(event) { async onSelectActor(event) {

View File

@@ -10,6 +10,16 @@ export class Targets {
return Targets.listTargets().length > 0; return Targets.listTargets().length > 0;
} }
static getTokenData( actor, tokenId, target = undefined) {
if ( target){
return Targets.extractTokenData(target)
}
const token = canvas.tokens.get(tokenId);
return token == undefined
? Targets.buildActorTokenData(tokenId, actor)
: Targets.extractTokenData(token);
}
static extractTokenData(target) { static extractTokenData(target) {
return { return {
id: target?.id, id: target?.id,
@@ -18,6 +28,7 @@ export class Targets {
} }
} }
static extractActorData(actor) { static extractActorData(actor) {
return { return {
id: actor.id, id: actor.id,
@@ -27,7 +38,7 @@ export class Targets {
} }
static buildActorTokenData(tokenId, actor) { static buildActorTokenData(tokenId, actor) {
return { id: tokenId, name: actor.name, img: actor.img ?? 'icons/svg/mystery-man.svg' }; return { id: tokenId, name: actor?.name?? "pas d'acteur", img: actor?.img ?? 'icons/svg/mystery-man.svg' };
} }
static isTargetEntite(target) { static isTargetEntite(target) {

View File

@@ -280,7 +280,7 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
async setNewTimestamp(newTimestamp) { async setNewTimestamp(newTimestamp) {
const oldTimestamp = this.timestamp; const oldTimestamp = this.timestamp;
await Promise.all(game.actors.map(async actor => await actor.onTimeChanging(oldTimestamp, newTimestamp))); await Promise.all(game.actors.map(actor => actor.onTimeChanging(oldTimestamp, newTimestamp)))
RdDTimestamp.setWorldTime(newTimestamp); RdDTimestamp.setWorldTime(newTimestamp);
if (oldTimestamp.indexDate + 1 == newTimestamp.indexDate && ReglesOptionnelles.isUsing("chateau-dormant-gardien")) { if (oldTimestamp.indexDate + 1 == newTimestamp.indexDate && ReglesOptionnelles.isUsing("chateau-dormant-gardien")) {
await DialogChateauDormant.create(); await DialogChateauDormant.create();
@@ -359,7 +359,7 @@ export class RdDCalendrier extends Application {
// Gestion expérience (si existante) // Gestion expérience (si existante)
request.competence = actor.getCompetence('Astrologie') request.competence = actor.getCompetence('Astrologie')
request.selectedCarac = actor.system.carac["vue"]; request.selectedCarac = actor.system.carac["vue"];
actor.appliquerAjoutExperience(request, 'hide'); actor.ajoutExperience(request, 'hide');
} }
} }
else { else {

View File

@@ -38,7 +38,7 @@ export class TMRRencontres {
const frequence = it => it.system.frequence[tmrType]; const frequence = it => it.system.frequence[tmrType];
const row = await this.table.getRandom(frequence, filtreMauvaise, forcedRoll); const row = await this.table.getRandom(frequence, filtreMauvaise, forcedRoll);
if (row) { if (row) {
await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item', { showSource: false }); await CompendiumTableHelpers.tableRowToChatMessage(row, 'Item', { showSource: false, rollMode: "gmroll" });
} }
return row?.document; return row?.document;

View File

@@ -90,21 +90,22 @@ export class Draconique {
*/ */
token(pixiTMR, linkData, coordTMR, type = undefined) { token(pixiTMR, linkData, coordTMR, type = undefined) {
const tooltip = this.tooltip(linkData); const tooltip = this.tooltip(linkData);
return this._createToken(pixiTMR, linkData, coordTMR, type, tooltip); return this._createToken(pixiTMR, linkData, coordTMR, type, tooltip)
} }
tokens(pixiTMR, linkData, coordTMR, type = undefined) { tokens(pixiTMR, linkData, coordTMR, code = undefined) {
const tooltip = this.tooltip(linkData); const tooltip = this.tooltip(linkData);
return [this._createToken(pixiTMR, linkData, coordTMR, type, tooltip)]; return [this._createToken(pixiTMR, linkData, coordTMR, code, tooltip)]
} }
_createToken(pixiTMR, linkData, coordTMR, type, tooltip) { _createToken(pixiTMR, linkData, coordTMR, code, tooltip) {
const token = { const token = {
sprite: this.createSprite(pixiTMR), sprite: this.createSprite(pixiTMR),
coordTMR: coordTMR, coordTMR: coordTMR,
tooltip: tooltip tooltip: tooltip,
code: code ?? this.code()
}; };
token[type ?? this.code()] = linkData; token[code ?? this.code()] = linkData;
return token; return token;
} }

View File

@@ -103,7 +103,7 @@ export class EffetsRencontre {
tete: context.rolled.isPart, tete: context.rolled.isPart,
poesie: await Poetique.getExtrait() poesie: await Poetique.getExtrait()
}) })
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(context.actor), whisper: ChatUtility.getOwners(context.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.hbs`, context) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.hbs`, context)
}); });
@@ -118,18 +118,18 @@ export class EffetsRencontre {
context.queues.push(await context.actor.ajouterQueue()); context.queues.push(await context.actor.ajouterQueue());
} }
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(context.actor), whisper: ChatUtility.getOwners(context.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.hbs`, context) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-reve-de-dragon.hbs`, context)
}); });
} }
static experience_particuliere = async (dialog, context) => { static experience_particuliere = async (dialog, context) => {
await context.actor.appliquerAjoutExperience(context) await context.actor.ajoutExperience(context)
} }
static regain_seuil = async (dialog, context) => { static regain_seuil = async (dialog, context) => {
await context.actor.regainPointDeSeuil() await context.actor.recuperationSeuilReve()
} }
static async $reinsertion(dialog, actor, filter) { static async $reinsertion(dialog, actor, filter) {

View File

@@ -27,13 +27,13 @@ export class PresentCites extends Draconique {
async _ajouterPresents(actor, tete) { async _ajouterPresents(actor, tete) {
let existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord); let existants = actor.items.filter(it => this.isCase(it)).map(it => it.system.coord);
if (existants.length > 0) { if (existants.length > 0) {
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(actor), whisper: ChatUtility.getOwners(actor),
content: "Vous avez encore des présents dans des cités, vous devrez tirer une autre tête pour remplacer celle ci!" content: "Vous avez encore des présents dans des cités, vous devrez tirer une autre tête pour remplacer celle ci!"
}) })
} }
else { else {
let cites = TMRUtility.filterTMR(it => it.type == 'cite'); let cites = TMRUtility.filterTMR(it => it.type == 'cite')
for (let tmr of cites) { for (let tmr of cites) {
await this.createCaseTmr(actor, 'Présent', tmr, tete.id); await this.createCaseTmr(actor, 'Présent', tmr, tete.id);
} }

View File

@@ -18,7 +18,7 @@ export class UrgenceDraconique extends Draconique {
if (coordSortsReserve.length == 0) { if (coordSortsReserve.length == 0) {
// La queue se transforme en idée fixe // La queue se transforme en idée fixe
const ideeFixe = await RdDRollTables.getIdeeFixe(); const ideeFixe = await RdDRollTables.getIdeeFixe();
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(actor), whisper: ChatUtility.getOwners(actor),
content: `En l'absence de sorts en réserve, l'urgence draconique de ${actor.name} se transforme en ${ideeFixe.name}` content: `En l'absence de sorts en réserve, l'urgence draconique de ${actor.name} se transforme en ${ideeFixe.name}`
}); });

View File

@@ -174,7 +174,7 @@ export class DialogFatigueVoyage extends Dialog {
.filter(it => it.selected) .filter(it => it.selected)
.forEach(async it => { .forEach(async it => {
const perteFatigue = fatigueBase + it.ajustement const perteFatigue = fatigueBase + it.ajustement
ChatMessage.create({ await ChatMessage.create({
whisper: ChatUtility.getOwners(it.actor), whisper: ChatUtility.getOwners(it.actor),
content: await renderTemplate( content: await renderTemplate(
'systems/foundryvtt-reve-de-dragon/templates/voyage/chat-fatigue_voyage.hbs', 'systems/foundryvtt-reve-de-dragon/templates/voyage/chat-fatigue_voyage.hbs',

View File

@@ -14,7 +14,7 @@
}, },
"devDependencies": { "devDependencies": {
"@eslint/js": "^9.8.0", "@eslint/js": "^9.8.0",
"@foundryvtt/foundryvtt-cli": "^1.0.3", "@foundryvtt/foundryvtt-cli": "^3.0.3",
"commander": "^11.1.0", "commander": "^11.1.0",
"eslint": "^9.9.0", "eslint": "^9.9.0",
"eslint-config-prettier": "^9.1.0", "eslint-config-prettier": "^9.1.0",

View File

@@ -8,7 +8,7 @@ items:
type: competencecreature type: competencecreature
sort: 100000 sort: 100000
flags: {} flags: {}
img: systems/foundryvtt-reve-de-dragon/icons/competence_course.webp img: systems/foundryvtt-reve-de-dragon/icons/creatures/glou_t.webp
effects: [] effects: []
folder: null folder: null
system: system:
@@ -422,7 +422,7 @@ prototypeToken:
negative: false negative: false
priority: 0 priority: 0
texture: texture:
src: icons/svg/mystery-man.svg src: systems/foundryvtt-reve-de-dragon/icons/creatures/glou_t.webp
tint: '#ffffff' tint: '#ffffff'
scaleX: 1 scaleX: 1
scaleY: 1 scaleY: 1

View File

@@ -299,7 +299,7 @@ prototypeToken:
negative: false negative: false
priority: 0 priority: 0
texture: texture:
src: systems/foundryvtt-reve-de-dragon/icons/creatures/sirene.svg src: systems/foundryvtt-reve-de-dragon/icons/creatures/sirene_t.webp
tint: '#ffffff' tint: '#ffffff'
scaleX: 1 scaleX: 1
scaleY: 1 scaleY: 1

View File

@@ -348,7 +348,7 @@ prototypeToken:
negative: false negative: false
priority: 0 priority: 0
texture: texture:
src: systems/foundryvtt-reve-de-dragon/icons/creatures/tigre-vert.svg src: systems/foundryvtt-reve-de-dragon/icons/creatures/tigre-vert_t.webp
tint: '#ffffff' tint: '#ffffff'
scaleX: 1 scaleX: 1
scaleY: 1 scaleY: 1

View File

@@ -215,7 +215,7 @@ prototypeToken:
negative: false negative: false
priority: 0 priority: 0
texture: texture:
src: systems/foundryvtt-reve-de-dragon/icons/creatures/chrasme_t.webp src: systems/foundryvtt-reve-de-dragon/icons/creatures/chrasme_t-old.webp
tint: '#d53434' tint: '#d53434'
scaleX: 0.8 scaleX: 0.8
scaleY: 0.8 scaleY: 0.8

View File

@@ -298,7 +298,7 @@ prototypeToken:
negative: false negative: false
priority: 0 priority: 0
texture: texture:
src: systems/foundryvtt-reve-de-dragon/icons/creatures/zyglute.svg src: systems/foundryvtt-reve-de-dragon/icons/creatures/zyglute_t.webp
tint: '#ffffff' tint: '#ffffff'
scaleX: 1 scaleX: 1
scaleY: 1 scaleY: 1

View File

@@ -2347,7 +2347,7 @@ items:
milieu: '' milieu: ''
environnement: [] environnement: []
resistance: 8 resistance: 8
categorie_parade: '' categorie_parade: dagues
dommages: 1 dommages: 1
mortalite: mortel mortalite: mortel
penetration: 0 penetration: 0
@@ -2395,7 +2395,7 @@ items:
milieu: '' milieu: ''
environnement: [] environnement: []
resistance: 7 resistance: 7
categorie_parade: '' categorie_parade: masses
dommages: 1 dommages: 1
mortalite: mortel mortalite: mortel
penetration: 0 penetration: 0
@@ -2443,7 +2443,7 @@ items:
milieu: '' milieu: ''
environnement: [] environnement: []
resistance: 8 resistance: 8
categorie_parade: '' categorie_parade: masses
dommages: 2 dommages: 2
mortalite: mortel mortalite: mortel
penetration: 0 penetration: 0
@@ -2611,7 +2611,7 @@ items:
milieu: '' milieu: ''
environnement: [] environnement: []
resistance: 6 resistance: 6
categorie_parade: '' categorie_parade: haches
dommages: 2 dommages: 2
mortalite: mortel mortalite: mortel
penetration: 0 penetration: 0

View File

@@ -2418,7 +2418,7 @@ items:
milieu: '' milieu: ''
environnement: [] environnement: []
resistance: 5 resistance: 5
categorie_parade: '' categorie_parade: lances
dommages: 2 dommages: 2
mortalite: mortel mortalite: mortel
penetration: 0 penetration: 0
@@ -2466,7 +2466,7 @@ items:
milieu: '' milieu: ''
environnement: [] environnement: []
resistance: 15 resistance: 15
categorie_parade: '' categorie_parade: boucliers
dommages: 0 dommages: 0
mortalite: mortel mortalite: mortel
penetration: 0 penetration: 0

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