Compare commits

...

89 Commits

Author SHA1 Message Date
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
fd96be439e Merge pull request '13.0.31 - Les choix multiples d'Illysis' (#796) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 1m57s
Reviewed-on: https, #796
2026-03-04 09:01:53 +01:00
238d99fa9b Fix: dommages armes 1/2 mains à deux mains 2026-03-03 18:14:58 +01:00
490de5882b Fix: valeurs par défaut après la sélection 2026-03-03 17:58:52 +01:00
4fc06a449c Merge pull request '13.0.30 - Le pansement d'Illysis' (#795) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 1m27s
Reviewed-on: https, #795
2026-02-18 00:43:46 +01:00
929d6af173 Saisie de valeurs négatives 2026-02-17 00:36:08 +01:00
e15ed9d05d Jet de compétence avec défauts
Utilisation de carac par défaut et difficulté par défaut à l'ouverture
de la fenêtre de jet depuis une compétence
2026-02-16 23:58:45 +01:00
3699bc19b8 Fix: soins d'un joueur à l'autre
Les données dans rollData ne pouvaient pas être serialisées
2026-02-06 13:42:27 +01:00
15510b99d8 Merge pull request 'feature/v13-corrections' (#794) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 2m45s
Reviewed-on: https, #794
2026-01-19 21:44:59 +01:00
fa30705989 Affichage de l'XP des sorts et caractéristiques 2026-01-17 03:45:42 +01:00
04f550dd21 Fix jet de résistance V2
sans cométence s'il n'y a pas de sélection
2026-01-16 08:47:51 +01:00
850cae3979 Attaques V2 depuis onglet combat 2026-01-16 08:47:50 +01:00
7b514d5159 Background arme inutilisable 2026-01-14 23:55:03 +01:00
d78ede4f59 Fix missing import 2026-01-14 23:47:01 +01:00
3de00fd001 Merge pull request 'Correction chat appel moral' (#793) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 2m28s
Reviewed-on: https, #793
2026-01-13 22:08:14 +01:00
1b340e526c Simplifications en cherchant bug rêve actuel
Parfois, le rêve actuel est ajouté dans les caractéristiques des
feuilles de personnage.

Simplifications pour essayer d'isoler le souci.
2026-01-10 23:07:25 +01:00
3f3bf293b1 Correction Fenêtre astrologie v13 2026-01-10 22:28:39 +01:00
80b4cde130 Status effect v13 2026-01-10 22:28:09 +01:00
74fecac47e Correction chat appel moral 2026-01-09 02:06:16 +01:00
f1ee8fb45b Merge pull request 'Fix: attaques à distance' (#792) from feature/v13-corrections into v13
Reviewed-on: https, #792
2026-01-07 14:44:21 +01:00
52a5084419 Fix: attaques à distance 2026-01-05 19:12:55 +01:00
8fdf49bfce Message d'information affiché une seule fois toutes les 24 heures
All checks were successful
Release Creation / build (release) Successful in 10m20s
2025-12-30 10:30:14 +01:00
f897a94e60 Merge pull request '## 13.0.27 - Les lunettes d'Illysis' (#791) from feature/v13-corrections into v13
Reviewed-on: https, #791
2025-12-30 10:19:45 +01:00
e6aed2d554 Amélioration des choix d'attaque 2025-12-30 01:30:19 +01:00
0dd671d8a5 Mise à jour d'images
- ajout d'un coffre
- ajout de tissu soie
- correction d'image pour utiliser le style classique
2025-12-30 01:30:15 +01:00
a5c4303012 Les conteneurs ouverts sont mis à jour 2025-12-30 01:29:31 +01:00
ad84e36d43 Suppression timestamp doublon 2025-12-30 01:25:29 +01:00
af9ecda30f fix changelog 2025-12-30 01:25:29 +01:00
7b1374dd2c Merge pull request 'Correction caracs créature' (#790) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 2m40s
Reviewed-on: https, #790
2025-12-21 21:38:56 +01:00
3b4ed13247 Caracs créature 2025-12-21 12:00:20 +01:00
298 changed files with 2791 additions and 2216 deletions

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><defs><radialGradient id="skoll-open-chest-gradient-2"><stop offset="0%" stop-color="#b8e986" stop-opacity="1"></stop><stop offset="100%" stop-color="#ffe0af" stop-opacity="1"></stop></radialGradient><linearGradient x1="0" x2="0" y1="0" y2="1" id="skoll-open-chest-gradient-5"><stop offset="0%" stop-color="#417505" stop-opacity="1"></stop><stop offset="100%" stop-color="#8b572a" stop-opacity="1"></stop></linearGradient></defs><g class="" transform="translate(1,0)" style=""><path d="M457.03 213.037 416.514 100.24C425 77.232 433.27 68.075 437.527 64.633c3.162-2.563 5.922-3.534 8.185-2.904 4.134 1.168 8.775 7.7 12.278 17.456 11.266 31.347 10.377 87.094-.96 133.85zm-324.287-17.9 312.804 34.84-43.82-122.1L145.558 79.34c2.593 36.102-1.913 79.913-12.817 115.796zM128.98 77.5l-45.06-5.02 37.03 103.123c7.773-32.06 10.625-68.357 8.03-98.102zm-27.52-50.31c-3.793 3.1-10.77 10.666-18.25 28.566L402.23 91.3c5.333-13.695 11.37-24.702 17.88-32.495L108.796 24.13c-2.573-.29-5.415 1.51-7.338 3.06zm280.63 283.338.61 169.352 66.352-53.63-.61-169.35zM366.163 487.9 46.62 452.306 46 278.396l319.553 35.594zM216.726 337.648a9.777 9.777 0 0 0 5.168-9.405c-.248-6.367-5.364-12.092-11.43-12.857h-.125c-6.14-.693-10.904 3.927-10.646 10.335a13.973 13.973 0 0 0 5.767 10.543l-2.17 25.073 17.57 2.005zm219.28-91.983-307.46-34.25v59.54l242.712 27.037zM58.31 263.13l54.34 6.058v-49.98z" fill="#fff" fill-opacity="1" transform="translate(25.6, 25.6) scale(0.9, 0.9) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -1,5 +1,109 @@
# 13.0 # 13.0
## 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
- les défauts de caractéristique/difficulté des compétences ne sont pris que si aucun autre choix n'est fait
- lors d'une attaque à deux mains avec une arme à une ou deux mains, les dommages à deux mains sont bien utilisés
## 13.0.30 - Le pansement d'Illysis
- les soins d'un joueur à l'autre fonctionne de nouveau
- la fenêtre de jet de compétence s'ouvre avec la caractéristique et la difficulté par défaut
- on peut saisir des valeurs négatives au clavier en sélectionnant les conditions/difficultés
## 13.0.29 - Le tricorne d'Illysis
- gestion des attaques avec jets V2 depuis l'onglet de combat
- les jets de résistance en mode V2 fonctionnent sans sélection de compétence
- affichage de l'expérience correspondant aux sorts pour aider à la création
- affichage de l'équivallent d'expérience des caractéristiques
## 13.0.28 - La quadrature d'Illysis
- Les ajustements de portée sont calculés pour les attaques à distance
- L'appel au moral dans le tchat ne déplace plus les boutons d'appel à la chance
- Correction d'apparence V13
- la fenêtre de choix des status utilisés est affichée correctement
- la fenêtre d'astrologie MJ est affichée correctement
## 13.0.27 - Les lunettes d'Illysis
- Les heures ne sont plus affichées en doublon sur les messages
- Les conteneurs ouverts sont mis à jour si leur contenu change
- Le style des icones d'objets est homogénéisé
- Ajout d'icônes: coffre, tissu de soie, parchemin
- Amélioration des choix d'actions de combat
- le choix d'initiative limite les attaques disponibles
- les compétences sont triées dans l'ordre décroissant
## 13.0.26 - La ménagerie d'Illysis
- Correction: on peut de nouveau modifier les caractéristiques des créatures
## 13.0.24 - Le grand oubli d'Illysis ## 13.0.24 - Le grand oubli d'Illysis
- ajout d'un bouton pour supprimer les anciens messages du tchat - ajout d'un bouton pour supprimer les anciens messages du tchat

View File

@@ -893,7 +893,7 @@ body {
max-width: 1.4rem; max-width: 1.4rem;
max-height: 1.4rem; max-height: 1.4rem;
border: 1px; border: 1px;
background: center / contain no-repeat url("../../icons/templates/icone_parchement_vierge.webp"); background: center / contain no-repeat url("../icons/templates/icone_parchement_vierge.webp");
} }
.system-foundryvtt-reve-de-dragon .sheet-header .header-compteurs { .system-foundryvtt-reve-de-dragon .sheet-header .header-compteurs {
width: calc(60% - 110px - 1rem); width: calc(60% - 110px - 1rem);
@@ -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;
@@ -1210,6 +1188,10 @@ body {
color: rgba(173, 36, 26, 0.9); color: rgba(173, 36, 26, 0.9);
text-shadow: 1px 1px 4px #3c3c3c; text-shadow: 1px 1px 4px #3c3c3c;
} }
.system-foundryvtt-reve-de-dragon .rdd-dialog.status-effects li {
display: flex;
flex-direction: row;
}
.system-foundryvtt-reve-de-dragon .rdd-dialog-select img.select-img { .system-foundryvtt-reve-de-dragon .rdd-dialog-select img.select-img {
-webkit-box-flex: 0; -webkit-box-flex: 0;
-ms-flex: 0 0 48px; -ms-flex: 0 0 48px;
@@ -1522,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 {
@@ -1734,25 +1727,121 @@ body {
.system-foundryvtt-reve-de-dragon form.app-personnage-aleatoire h2 { .system-foundryvtt-reve-de-dragon form.app-personnage-aleatoire h2 {
min-width: 30rem; min-width: 30rem;
} }
.system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.theme-astral { .system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.theme-astral {
width: 14rem; width: 14rem;
margin: 0.4rem; margin: 0.4rem;
} }
.system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.horloge-roue { .system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-roue {
position: relative; position: relative;
left: calc(50% - 6.5rem); left: calc(50% - 6.5rem);
width: 13rem; width: 13rem;
height: 13rem; height: 13rem;
} }
.system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.horloge-roue div.horloge-heure { .system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-roue div.horloge-heure {
position: absolute; position: absolute;
width: 1.8rem; width: 1.8rem;
height: 1.8rem; height: 1.8rem;
} }
.system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.horloge-roue div.horloge-heure img.horloge-heure-img { .system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-roue div.horloge-heure img.horloge-heure-img {
width: 2rem; width: 2rem;
height: 2rem; height: 2rem;
} }
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-01 {
top: calc(50% - 1rem + 0 * 41%);
left: calc(50% - 1rem + -1 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-02 {
top: calc(50% - 1rem + -0.5 * 41%);
left: calc(50% - 1rem + -0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-03 {
top: calc(50% - 1rem + -0.8660254 * 41%);
left: calc(50% - 1rem + -0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-04 {
top: calc(50% - 1rem + -1 * 41%);
left: calc(50% - 1rem + 0 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-05 {
top: calc(50% - 1rem + -0.8660254 * 41%);
left: calc(50% - 1rem + 0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-06 {
top: calc(50% - 1rem + -0.5 * 41%);
left: calc(50% - 1rem + 0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-07 {
top: calc(50% - 1rem + 0 * 41%);
left: calc(50% - 1rem + 1 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-08 {
top: calc(50% - 1rem + 0.5 * 41%);
left: calc(50% - 1rem + 0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-09 {
top: calc(50% - 1rem + 0.8660254 * 41%);
left: calc(50% - 1rem + 0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-10 {
top: calc(50% - 1rem + 1 * 41%);
left: calc(50% - 1rem + 0 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-11 {
top: calc(50% - 1rem + 0.8660254 * 41%);
left: calc(50% - 1rem + -0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-12 {
top: calc(50% - 1rem + 0.5 * 41%);
left: calc(50% - 1rem + -0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-01 {
top: calc(50% - 0.4rem + 0 * 28%);
left: calc(50% - 0.4rem + -1 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-02 {
top: calc(50% - 0.4rem + -0.5 * 28%);
left: calc(50% - 0.4rem + -0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-03 {
top: calc(50% - 0.4rem + -0.8660254 * 28%);
left: calc(50% - 0.4rem + -0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-04 {
top: calc(50% - 0.4rem + -1 * 28%);
left: calc(50% - 0.4rem + 0 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-05 {
top: calc(50% - 0.4rem + -0.8660254 * 28%);
left: calc(50% - 0.4rem + 0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-06 {
top: calc(50% - 0.4rem + -0.5 * 28%);
left: calc(50% - 0.4rem + 0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-07 {
top: calc(50% - 0.4rem + 0 * 28%);
left: calc(50% - 0.4rem + 1 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-08 {
top: calc(50% - 0.4rem + 0.5 * 28%);
left: calc(50% - 0.4rem + 0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-09 {
top: calc(50% - 0.4rem + 0.8660254 * 28%);
left: calc(50% - 0.4rem + 0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-10 {
top: calc(50% - 0.4rem + 1 * 28%);
left: calc(50% - 0.4rem + 0 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-11 {
top: calc(50% - 0.4rem + 0.8660254 * 28%);
left: calc(50% - 0.4rem + -0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-12 {
top: calc(50% - 0.4rem + 0.5 * 28%);
left: calc(50% - 0.4rem + -0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .window-app .window-content, .system-foundryvtt-reve-de-dragon .window-app .window-content,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body, .system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body,
.system-foundryvtt-reve-de-dragon .application .window-content { .system-foundryvtt-reve-de-dragon .application .window-content {
@@ -2279,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;
@@ -2398,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;
} }
@@ -2597,102 +2681,6 @@ body {
top: calc(50% - 0.7rem + 0.5 * 38%); top: calc(50% - 0.7rem + 0.5 * 38%);
left: calc(50% - 0.7rem + -0.8660254 * 41%); left: calc(50% - 0.7rem + -0.8660254 * 41%);
} }
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-01 {
top: calc(50% - 1rem + 0 * 41%);
left: calc(50% - 1rem + -1 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-02 {
top: calc(50% - 1rem + -0.5 * 41%);
left: calc(50% - 1rem + -0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-03 {
top: calc(50% - 1rem + -0.8660254 * 41%);
left: calc(50% - 1rem + -0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-04 {
top: calc(50% - 1rem + -1 * 41%);
left: calc(50% - 1rem + 0 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-05 {
top: calc(50% - 1rem + -0.8660254 * 41%);
left: calc(50% - 1rem + 0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-06 {
top: calc(50% - 1rem + -0.5 * 41%);
left: calc(50% - 1rem + 0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-07 {
top: calc(50% - 1rem + 0 * 41%);
left: calc(50% - 1rem + 1 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-08 {
top: calc(50% - 1rem + 0.5 * 41%);
left: calc(50% - 1rem + 0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-09 {
top: calc(50% - 1rem + 0.8660254 * 41%);
left: calc(50% - 1rem + 0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-10 {
top: calc(50% - 1rem + 1 * 41%);
left: calc(50% - 1rem + 0 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-11 {
top: calc(50% - 1rem + 0.8660254 * 41%);
left: calc(50% - 1rem + -0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-12 {
top: calc(50% - 1rem + 0.5 * 41%);
left: calc(50% - 1rem + -0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-01 {
top: calc(50% - 0.4rem + 0 * 28%);
left: calc(50% - 0.4rem + -1 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-02 {
top: calc(50% - 0.4rem + -0.5 * 28%);
left: calc(50% - 0.4rem + -0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-03 {
top: calc(50% - 0.4rem + -0.8660254 * 28%);
left: calc(50% - 0.4rem + -0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-04 {
top: calc(50% - 0.4rem + -1 * 28%);
left: calc(50% - 0.4rem + 0 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-05 {
top: calc(50% - 0.4rem + -0.8660254 * 28%);
left: calc(50% - 0.4rem + 0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-06 {
top: calc(50% - 0.4rem + -0.5 * 28%);
left: calc(50% - 0.4rem + 0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-07 {
top: calc(50% - 0.4rem + 0 * 28%);
left: calc(50% - 0.4rem + 1 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-08 {
top: calc(50% - 0.4rem + 0.5 * 28%);
left: calc(50% - 0.4rem + 0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-09 {
top: calc(50% - 0.4rem + 0.8660254 * 28%);
left: calc(50% - 0.4rem + 0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-10 {
top: calc(50% - 0.4rem + 1 * 28%);
left: calc(50% - 0.4rem + 0 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-11 {
top: calc(50% - 0.4rem + 0.8660254 * 28%);
left: calc(50% - 0.4rem + -0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-12 {
top: calc(50% - 0.4rem + 0.5 * 28%);
left: calc(50% - 0.4rem + -0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-boutons-heure .calendar-btn:is(.calendar-lyre, .calendar-vaisseau) img { .system-foundryvtt-reve-de-dragon .calendar-boutons-heure .calendar-btn:is(.calendar-lyre, .calendar-vaisseau) img {
color: hsla(0, 0%, 100%, 0.5); color: hsla(0, 0%, 100%, 0.5);
border: none; border: none;

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
icons/objets/coffre.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
icons/objets/parchemin.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 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

@@ -136,7 +136,7 @@
max-height: 1.4rem; max-height: 1.4rem;
border: 1px; border: 1px;
background: center / contain no-repeat background: center / contain no-repeat
url("../../icons/templates/icone_parchement_vierge.webp"); url("../icons/templates/icone_parchement_vierge.webp");
} }
.sheet-header .header-compteurs { .sheet-header .header-compteurs {
@@ -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 {
@@ -484,7 +462,10 @@
color: rgba(173, 36, 26, 0.9); color: rgba(173, 36, 26, 0.9);
text-shadow: 1px 1px 4px rgba(60, 60, 60, 1); text-shadow: 1px 1px 4px rgba(60, 60, 60, 1);
} }
.rdd-dialog.status-effects li {
display: flex;
flex-direction: row;
}
.rdd-dialog-select img.select-img { .rdd-dialog-select img.select-img {
-webkit-box-flex: 0; -webkit-box-flex: 0;
-ms-flex: 0 0 48px; -ms-flex: 0 0 48px;
@@ -845,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;
@@ -1065,7 +1054,7 @@
min-width: 30rem; min-width: 30rem;
} }
} }
.app-calendar-astrologie { .rdd-calendar-astrologie {
div.theme-astral { div.theme-astral {
width: 14rem; width: 14rem;
margin: 0.4rem; margin: 0.4rem;
@@ -1085,6 +1074,105 @@
} }
} }
} }
div.horloge-heure.heure-01 {
top: calc(50% - 1rem + sin(-180deg) * 41%);
left: calc(50% - 1rem + cos(-180deg) * 41%);
}
div.horloge-heure.heure-02 {
top: calc(50% - 1rem + sin(-150deg) * 41%);
left: calc(50% - 1rem + cos(-150deg) * 41%);
}
div.horloge-heure.heure-03 {
top: calc(50% - 1rem + sin(-120deg) * 41%);
left: calc(50% - 1rem + cos(-120deg) * 41%);
}
div.horloge-heure.heure-04 {
top: calc(50% - 1rem + sin(-90deg) * 41%);
left: calc(50% - 1rem + cos(-90deg) * 41%);
}
div.horloge-heure.heure-05 {
top: calc(50% - 1rem + sin(-60deg) * 41%);
left: calc(50% - 1rem + cos(-60deg) * 41%);
}
div.horloge-heure.heure-06 {
top: calc(50% - 1rem + sin(-30deg) * 41%);
left: calc(50% - 1rem + cos(-30deg) * 41%);
}
div.horloge-heure.heure-07 {
top: calc(50% - 1rem + sin(-0deg) * 41%);
left: calc(50% - 1rem + cos(-0deg) * 41%);
}
div.horloge-heure.heure-08 {
top: calc(50% - 1rem + sin(30deg) * 41%);
left: calc(50% - 1rem + cos(30deg) * 41%);
}
div.horloge-heure.heure-09 {
top: calc(50% - 1rem + sin(60deg) * 41%);
left: calc(50% - 1rem + cos(60deg) * 41%);
}
div.horloge-heure.heure-10 {
top: calc(50% - 1rem + sin(90deg) * 41%);
left: calc(50% - 1rem + cos(90deg) * 41%);
}
div.horloge-heure.heure-11 {
top: calc(50% - 1rem + sin(120deg) * 41%);
left: calc(50% - 1rem + cos(120deg) * 41%);
}
div.horloge-heure.heure-12 {
top: calc(50% - 1rem + sin(150deg) * 41%);
left: calc(50% - 1rem + cos(150deg) * 41%);
}
div.horloge-ajustement.heure-01 {
top: calc(50% - 0.4rem + sin(180deg) * 28%);
left: calc(50% - 0.4rem + cos(180deg) * 28%);
}
div.horloge-ajustement.heure-02 {
top: calc(50% - 0.4rem + sin(-150deg) * 28%);
left: calc(50% - 0.4rem + cos(-150deg) * 28%);
}
div.horloge-ajustement.heure-03 {
top: calc(50% - 0.4rem + sin(-120deg) * 28%);
left: calc(50% - 0.4rem + cos(-120deg) * 28%);
}
div.horloge-ajustement.heure-04 {
top: calc(50% - 0.4rem + sin(-90deg) * 28%);
left: calc(50% - 0.4rem + cos(-90deg) * 28%);
}
div.horloge-ajustement.heure-05 {
top: calc(50% - 0.4rem + sin(-60deg) * 28%);
left: calc(50% - 0.4rem + cos(-60deg) * 28%);
}
div.horloge-ajustement.heure-06 {
top: calc(50% - 0.4rem + sin(-30deg) * 28%);
left: calc(50% - 0.4rem + cos(-30deg) * 28%);
}
div.horloge-ajustement.heure-07 {
top: calc(50% - 0.4rem + sin(0deg) * 28%);
left: calc(50% - 0.4rem + cos(0deg) * 28%);
}
div.horloge-ajustement.heure-08 {
top: calc(50% - 0.4rem + sin(30deg) * 28%);
left: calc(50% - 0.4rem + cos(30deg) * 28%);
}
div.horloge-ajustement.heure-09 {
top: calc(50% - 0.4rem + sin(60deg) * 28%);
left: calc(50% - 0.4rem + cos(60deg) * 28%);
}
div.horloge-ajustement.heure-10 {
top: calc(50% - 0.4rem + sin(90deg) * 28%);
left: calc(50% - 0.4rem + cos(90deg) * 28%);
}
div.horloge-ajustement.heure-11 {
top: calc(50% - 0.4rem + sin(120deg) * 28%);
left: calc(50% - 0.4rem + cos(120deg) * 28%);
}
div.horloge-ajustement.heure-12 {
top: calc(50% - 0.4rem + sin(150deg) * 28%);
left: calc(50% - 0.4rem + cos(150deg) * 28%);
}
} }
.window-app .window-content, .window-app .window-content,
@@ -1674,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 {
@@ -1809,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);
} }
@@ -2022,106 +2104,6 @@
} }
} }
.calendar-astrologie {
div.horloge-heure.heure-01 {
top: calc(50% - 1rem + sin(-180deg) * 41%);
left: calc(50% - 1rem + cos(-180deg) * 41%);
}
div.horloge-heure.heure-02 {
top: calc(50% - 1rem + sin(-150deg) * 41%);
left: calc(50% - 1rem + cos(-150deg) * 41%);
}
div.horloge-heure.heure-03 {
top: calc(50% - 1rem + sin(-120deg) * 41%);
left: calc(50% - 1rem + cos(-120deg) * 41%);
}
div.horloge-heure.heure-04 {
top: calc(50% - 1rem + sin(-90deg) * 41%);
left: calc(50% - 1rem + cos(-90deg) * 41%);
}
div.horloge-heure.heure-05 {
top: calc(50% - 1rem + sin(-60deg) * 41%);
left: calc(50% - 1rem + cos(-60deg) * 41%);
}
div.horloge-heure.heure-06 {
top: calc(50% - 1rem + sin(-30deg) * 41%);
left: calc(50% - 1rem + cos(-30deg) * 41%);
}
div.horloge-heure.heure-07 {
top: calc(50% - 1rem + sin(-0deg) * 41%);
left: calc(50% - 1rem + cos(-0deg) * 41%);
}
div.horloge-heure.heure-08 {
top: calc(50% - 1rem + sin(30deg) * 41%);
left: calc(50% - 1rem + cos(30deg) * 41%);
}
div.horloge-heure.heure-09 {
top: calc(50% - 1rem + sin(60deg) * 41%);
left: calc(50% - 1rem + cos(60deg) * 41%);
}
div.horloge-heure.heure-10 {
top: calc(50% - 1rem + sin(90deg) * 41%);
left: calc(50% - 1rem + cos(90deg) * 41%);
}
div.horloge-heure.heure-11 {
top: calc(50% - 1rem + sin(120deg) * 41%);
left: calc(50% - 1rem + cos(120deg) * 41%);
}
div.horloge-heure.heure-12 {
top: calc(50% - 1rem + sin(150deg) * 41%);
left: calc(50% - 1rem + cos(150deg) * 41%);
}
div.horloge-ajustement.heure-01 {
top: calc(50% - 0.4rem + sin(180deg) * 28%);
left: calc(50% - 0.4rem + cos(180deg) * 28%);
}
div.horloge-ajustement.heure-02 {
top: calc(50% - 0.4rem + sin(-150deg) * 28%);
left: calc(50% - 0.4rem + cos(-150deg) * 28%);
}
div.horloge-ajustement.heure-03 {
top: calc(50% - 0.4rem + sin(-120deg) * 28%);
left: calc(50% - 0.4rem + cos(-120deg) * 28%);
}
div.horloge-ajustement.heure-04 {
top: calc(50% - 0.4rem + sin(-90deg) * 28%);
left: calc(50% - 0.4rem + cos(-90deg) * 28%);
}
div.horloge-ajustement.heure-05 {
top: calc(50% - 0.4rem + sin(-60deg) * 28%);
left: calc(50% - 0.4rem + cos(-60deg) * 28%);
}
div.horloge-ajustement.heure-06 {
top: calc(50% - 0.4rem + sin(-30deg) * 28%);
left: calc(50% - 0.4rem + cos(-30deg) * 28%);
}
div.horloge-ajustement.heure-07 {
top: calc(50% - 0.4rem + sin(0deg) * 28%);
left: calc(50% - 0.4rem + cos(0deg) * 28%);
}
div.horloge-ajustement.heure-08 {
top: calc(50% - 0.4rem + sin(30deg) * 28%);
left: calc(50% - 0.4rem + cos(30deg) * 28%);
}
div.horloge-ajustement.heure-09 {
top: calc(50% - 0.4rem + sin(60deg) * 28%);
left: calc(50% - 0.4rem + cos(60deg) * 28%);
}
div.horloge-ajustement.heure-10 {
top: calc(50% - 0.4rem + sin(90deg) * 28%);
left: calc(50% - 0.4rem + cos(90deg) * 28%);
}
div.horloge-ajustement.heure-11 {
top: calc(50% - 0.4rem + sin(120deg) * 28%);
left: calc(50% - 0.4rem + cos(120deg) * 28%);
}
div.horloge-ajustement.heure-12 {
top: calc(50% - 0.4rem + sin(150deg) * 28%);
left: calc(50% - 0.4rem + cos(150deg) * 28%);
}
}
.calendar-boutons-heure { .calendar-boutons-heure {
.calendar-btn:is(.calendar-lyre, .calendar-vaisseau) img { .calendar-btn:is(.calendar-lyre, .calendar-vaisseau) img {
color: hsla(0, 0%, 100%, 0.5); color: hsla(0, 0%, 100%, 0.5);

View File

@@ -19,6 +19,7 @@ import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js"; import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js";
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js"; import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
import { MORAL } from "./moral/apprecier.mjs"; import { MORAL } from "./moral/apprecier.mjs";
import { RdDItemSort } from "./item-sort.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
/** /**
@@ -50,8 +51,9 @@ 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),
surEncombrementMessage: this.actor.isSurenc() ? "Sur-Encombrement!" : "", surEncombrementMessage: this.actor.isSurenc() ? "Sur-Encombrement!" : "",
malusArmure: this.actor.getMalusArmure() malusArmure: this.actor.getMalusArmure()
}) })
@@ -61,9 +63,13 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
if (formData.type == ACTOR_TYPES.personnage) { if (formData.type == ACTOR_TYPES.personnage) {
formData.options.mainsDirectrices = MAINS_DIRECTRICES; formData.options.mainsDirectrices = MAINS_DIRECTRICES;
formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie) formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie)
formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences); foundry.utils.mergeObject(formData.calc, {
formData.calc.competenceXPTotal = RdDItemCompetence.computeTotalXP(formData.competences); comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.competences),
formData.calc.fatigue = RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max); competenceXPTotal: RdDItemCompetence.computeTotalXP(formData.competences),
sortsXPTotal: RdDItemSort.computeTotalXP(this.actor.itemTypes[ITEM_TYPES.sort]),
fatigue: RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max)
})
formData.competences.forEach(item => { formData.competences.forEach(item => {
item.system.isHidden = this.options.recherche item.system.isHidden = this.options.recherche
@@ -210,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 => {
@@ -273,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";
@@ -48,39 +47,24 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
getCarac() { getCarac() {
return foundry.utils.mergeObject(this.system.carac, const carac = super.getCarac()
{ foundry.utils.mergeObject(carac, this.getCaracReveActuel())
'reve-actuel': this.getCaracReveActuel(), foundry.utils.mergeObject(carac, this.getCaracCompetenceCreature(), { overwrite: false })
'chance-actuelle': this.getCaracChanceActuelle() return carac
},
{ inplace: false })
}
getCaracChanceActuelle() {
return {
label: 'Chance actuelle',
value: this.getChanceActuel(),
type: "number"
};
}
getCaracReveActuel() {
return {
label: 'Rêve actuel',
value: this.getReveActuel(),
type: "number"
};
} }
getTaille() { return Misc.toInt(this.system.carac.taille?.value) } getTaille() { return Misc.toInt(this.system.carac.taille?.value) }
getConstitution() { return this.getReve() } getConstitution() { return this.getReve() }
getForce() { return this.getReve() } getForce() { return this.getReve() }
getAgilite() { return this.getForce() } getAgilite() { return this.getForce() }
getReve() { return Misc.toInt(this.system.carac.reve?.value) } getReve() { return Misc.toInt(this.system.carac.reve?.value) }
getChance() { return this.getReve() } getChance() { return this.getReve() }
getChanceActuel() { return this.getChance() }
getCaracChanceActuelle() { return { [CARACS.CHANCE_ACTUELLE]: { label: 'Chance actuelle', value: this.getChanceActuel(), type: "number" } } }
getReveActuel() { return this.getReve() } getReveActuel() { return this.getReve() }
getChanceActuel() { return this.getChance() } getCaracReveActuel() { return { [CARACS.REVE_ACTUEL]: { label: "Rêve Actuel", value: this.getReveActuel(), type: "number" } } }
getEnduranceMax() { return Math.max(1, this.getTaille() + this.getConstitution()) } getEnduranceMax() { return Math.max(1, this.getTaille() + this.getConstitution()) }
getEncombrementMax() { return (this.getForce() + this.getTaille()) / 2 } getEncombrementMax() { return (this.getForce() + this.getTaille()) / 2 }
@@ -160,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())
@@ -169,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)
@@ -184,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))} !` })
} }
} }
} }
@@ -257,21 +242,28 @@ export class RdDBaseActorReve extends RdDBaseActor {
return this.itemTypes[ITEM_TYPES.empoignade]; return this.itemTypes[ITEM_TYPES.empoignade];
} }
async updateCarac(caracName, to) {
const path = `system.carac.${caracName}.value`;
let updates = {};
updates[path] = Number.parseInt(to)
await this.update(updates, { noHook: true });
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async updateCreatureCompetence(idOrName, fieldName, value) { async updateCreatureCompetence(idOrName, fieldName, value) {
let competence = this.getCompetence(idOrName); let competence = this.getCompetence(idOrName);
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 })
} }
} }
} }
@@ -303,7 +295,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
createCallbackExperience() { createCallbackExperience() {
return { action: r => this.appliquerAjoutExperience(r) } return { action: r => this.ajoutExperience(r) }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -312,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) { }
@@ -324,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 },
@@ -379,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)) {
@@ -393,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 }
@@ -421,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: {
@@ -449,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: {
@@ -490,17 +500,15 @@ export class RdDBaseActorReve extends RdDBaseActor {
async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) { async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) {
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
const competence = this.getCompetence(idOrName); const competence = this.getCompetence(idOrName);
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: { allowed: options.arme ? ATTAQUE_ROLL_TYPES : DEFAULT_ROLL_TYPES }, type: { allowed: DEFAULT_ROLL_TYPES },
selected: { selected: {
carac: competence.type == ITEM_TYPES.competencecreature ? { key: competence.name } : undefined, carac: competence.type == ITEM_TYPES.competencecreature ? { key: competence.name } : undefined,
comp: { key: competence.name }, comp: { key: competence.name },
diff: { type: options.arme ? DIFF.ATTAQUE : DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 }, diff: { type: DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 },
attaque: options.arme ? { arme: { key: options.arme.id } } : undefined
} }
} }
return await RollDialog.create(rollData) return await RollDialog.create(rollData)
@@ -572,7 +580,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
type: { type: {
allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE
} }
}; }
return await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose }) return await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
} }
}) })
@@ -581,16 +589,18 @@ export class RdDBaseActorReve extends RdDBaseActor {
/** -------------------------------------------- /** --------------------------------------------
* @param {*} arme item d'arme/compétence de créature * @param {*} arme item d'arme/compétence de créature
* @param {*} categorieArme catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession * @param {*} maniement catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession
* @returns * @returns
*/ */
rollArme(arme, categorieArme = 'competence', token = undefined) { async rollArme(arme, maniement = 'competence', token = undefined) {
token = token ?? RdDUtility.getSelectedToken(this) token = token ?? RdDUtility.getSelectedToken(this)
const compToUse = RdDItemArme.getCompetenceArme(arme, categorieArme) const compToUse = RdDItemArme.getCompetenceArme(arme, maniement)
if (!RdDItemArme.isUtilisable(arme)) { if (!RdDItemArme.isUtilisable(arme)) {
ui.notifications.warn(`Arme inutilisable: ${arme.name} non équipée ou avec une résistance de 0 ou moins`) ui.notifications.warn(`Arme inutilisable: ${arme.name} non équipée ou avec une résistance de 0 ou moins`)
return return
} }
if (!Targets.hasTargets()) { if (!Targets.hasTargets()) {
RdDConfirm.confirmer({ RdDConfirm.confirmer({
settingConfirmer: "confirmer-combat-sans-cible", settingConfirmer: "confirmer-combat-sans-cible",
@@ -602,7 +612,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
onAction: async () => { onAction: async () => {
this.rollCompetence(compToUse, { tryTarget: false, arme: arme }) this.rollCompetence(compToUse, { tryTarget: false, arme: arme })
} }
}); })
return return
} }
@@ -612,11 +622,12 @@ export class RdDBaseActorReve extends RdDBaseActor {
return return
} }
const competence = this.getCompetence(compToUse) const comp = this.getCompetence(compToUse)
if (competence.isCompetencePossession()) { if (comp.isCompetencePossession()) {
return RdDPossession.onAttaquePossession(target, this, competence); // TODO: vérifier si c'est possible, sinon simplifier
return RdDPossession.onAttaquePossession(target, this, comp);
} }
RdDCombat.rddCombatTarget(target, this, token).attaque(competence, arme); RdDCombat.rddCombatTarget(target, this, token).attaque(comp, arme, maniement)
}) })
} }
@@ -624,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) }
@@ -663,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)
}); })
} }
} }
@@ -739,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

@@ -8,6 +8,7 @@ import { RdDItemBlessure } from "../item/blessure.js";
import { ChatUtility } from "../chat-utility.js"; import { ChatUtility } from "../chat-utility.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDBaseActor } from "./base-actor.js"; import { RdDBaseActor } from "./base-actor.js";
import { CARACS } from "../rdd-carac.js";
/** /**
* Classe de base pour les acteurs qui peuvent subir des blessures * Classe de base pour les acteurs qui peuvent subir des blessures
@@ -16,6 +17,14 @@ import { RdDBaseActor } from "./base-actor.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)
@@ -23,10 +32,18 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
this.system.attributs.encombrement.value = this.getEncombrementMax() this.system.attributs.encombrement.value = this.getEncombrementMax()
} }
getCarac() {
const carac = super.getCarac()
foundry.utils.mergeObject(carac, this.getCaracChanceActuelle())
foundry.utils.mergeObject(carac, this.getCaracVie())
return carac
}
getForce() { return Misc.toInt(this.system.carac.force?.value) } getForce() { return Misc.toInt(this.system.carac.force?.value) }
getConstitution() { return Misc.toInt(this.system.carac.constitution?.value) } getConstitution() { return Misc.toInt(this.system.carac.constitution?.value) }
getVolonte() { return Misc.toInt(this.system.carac.volonte?.value) } getVolonte() { return Misc.toInt(this.system.carac.volonte?.value) }
getCaracVie() { return { [CARACS.VIE]: { label: "Vie", value: this.getVieMax(), type: "number" } } }
getVieMax() { return Misc.toInt(this.system.sante.vie?.max) } getVieMax() { return Misc.toInt(this.system.sante.vie?.max) }
getEnduranceMax() { return Math.max(1, this.getTaille() + this.getConstitution()) } getEnduranceMax() { return Math.max(1, this.getTaille() + this.getConstitution()) }
getFatigueMax() { return this.getEnduranceMax() * 2 } getFatigueMax() { return this.getEnduranceMax() * 2 }
@@ -62,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,
@@ -115,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
}); })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -133,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
@@ -155,34 +186,39 @@ 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
} }
async onRollTachePremiersSoins(blessureId, rollData, soigneurId) { async callbackPremiersSoins(blessureId, rollData, soigneurId) {
await this.onRollTachePremiersSoins(blessureId,
rollData.v2 ? rollData.current.tache.tache : rollData.tache,
rollData.rolled.isETotal,
soigneurId)
}
async onRollTachePremiersSoins(blessureId, tache, isETotal, soigneurId) {
if (!this.isOwner) { if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({ return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id, tokenId: this.token?.id,
actorId: this.id, actorId: this.id,
method: 'onRollTachePremiersSoins', args: [blessureId, rollData, soigneurId] method: 'onRollTachePremiersSoins', args: [blessureId, tache, isETotal, soigneurId]
}) })
} }
const blessure = this.getItem(blessureId, 'blessure') const blessure = this.getItem(blessureId, 'blessure')
if (blessure && !blessure.system.premierssoins.done) { if (blessure && !blessure.system.premierssoins.done) {
const tache = rollData.v2 ? rollData.current.tache.tache : rollData.tache if (isETotal) {
if (rollData.rolled.isETotal) {
await blessure.update({ await blessure.update({
'system.difficulte': blessure.system.difficulte - 1, 'system.difficulte': blessure.system.difficulte - 1,
'system.premierssoins.tache': Math.max(0, tache.system.points_de_tache_courant) 'system.premierssoins.tache': Math.max(0, tache.system.points_de_tache_courant)
@@ -242,22 +278,14 @@ 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)
} }
async onUpdateItem(item, options, id) { async onUpdateItem(item, updates, options, id) {
await this.changeItemEffects(item); await this.changeItemEffects(item);
await super.onUpdateItem(item, options, id) await super.onUpdateItem(item, updates, options, id)
} }
async onDeleteItem(item, options, id) { async onDeleteItem(item, options, id) {
@@ -268,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
} }
} }
@@ -292,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;
}
} }
} }
const endActuelle = this.getEnduranceActuelle(); return RdDItemBlessure.prepareBlessure(gravite, options);
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 }) {
@@ -329,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()) {
@@ -340,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)
@@ -370,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)
}); })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -381,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);
@@ -396,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

@@ -12,6 +12,7 @@ import { SystemCompendiums } from "../settings/system-compendiums.js";
import { RdDItem } from "../item.js"; import { RdDItem } from "../item.js";
import { StatusEffects, STATUSES } from "../settings/status-effects.js"; import { StatusEffects, STATUSES } from "../settings/status-effects.js";
import { Apprecier } from "../moral/apprecier.mjs"; import { Apprecier } from "../moral/apprecier.mjs";
import { CARACS } from "../rdd-carac.js";
export class RdDBaseActor extends Actor { export class RdDBaseActor extends Actor {
@@ -48,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, options, id) => Misc.documentIfResponsible(item.parent)?.onUpdateItem(item, 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) {
@@ -92,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:
@@ -155,20 +140,30 @@ 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() {
return foundry.utils.duplicate(this.system.carac)
}
findCaracByName(name) { findCaracByName(name) {
name = Grammar.toLowerCaseNoAccent(name) name = Grammar.toLowerCaseNoAccent(name)
switch (name) { switch (name) {
case 'reve-actuel': case 'reve actuel': case 'reve actuel':
return this.system.carac.reve name = CARACS.REVE_ACTUEL
case 'chance-actuelle': case 'chance actuelle': break
return this.system.carac.chance case 'chance actuelle':
case 'vie': name = CARACS.CHANCE_ACTUELLE
return this.system.sante.vie break
} }
const carac = this.getCarac()
const carac = {}
foundry.utils.mergeObject(carac, this.system.carac, { overwrite: false })
foundry.utils.mergeObject(carac, this.getCaracCompetenceCreature(), { overwrite: false })
return RdDBaseActor.$findCaracByName(carac, name); return RdDBaseActor.$findCaracByName(carac, name);
} }
@@ -183,10 +178,18 @@ export class RdDBaseActor extends Actor {
getCaracByName(name) { getCaracByName(name) {
name = this.mapCarac(Grammar.toLowerCaseNoAccent(name)) ?? name name = this.mapCarac(Grammar.toLowerCaseNoAccent(name)) ?? name
switch (name) { switch (name) {
case 'reve-actuel': case 'reve actuel': case 'reve actuel':
return this.getCaracReveActuel(); name = CARACS.REVE_ACTUEL
case 'chance-actuelle': case 'chance-actuelle': break
return this.getCaracChanceActuelle(); case 'chanceactuelle':
name = CARACS.CHANCE_ACTUELLE
break
}
switch (name) {
case CARACS.REVE_ACTUEL:
return this.getCaracReveActuel()[CARACS.REVE_ACTUEL]
case CARACS.CHANCE_ACTUELLE:
return this.getCaracChanceActuelle()[CARACS.CHANCE_ACTUELLE]
} }
return this.findCaracByName(name); return this.findCaracByName(name);
} }
@@ -211,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()
@@ -223,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);
@@ -275,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)
} }
} }
} }
@@ -291,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)
} }
} }
@@ -316,21 +355,15 @@ 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) {
} }
async onUpdateItem(item, options, id) { async onUpdateItem(item, updates, options, id) {
const conteneur = item.findConteneur()
conteneur?.render(options.render)
} }
async onDeleteItem(item, options, id) { async onDeleteItem(item, options, id) {
@@ -339,15 +372,14 @@ export class RdDBaseActor extends Actor {
} }
} }
async _removeItemFromConteneur(item) { async _removeItemFromConteneur(item) {
const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id)) 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) }
} }
} }
@@ -371,7 +403,7 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async cleanupConteneurs() { async cleanupConteneurs() {
if (Misc.isOwnerPlayer(this)) { if (Misc.isOwnerPlayer(this)) {
let updates = this.itemTypes['conteneur'] let updates = this.itemTypes[ITEM_TYPES.conteneur]
.filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0) .filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0)
.map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } }); .map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } });
if (updates.length > 0) { if (updates.length > 0) {
@@ -382,7 +414,7 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
getFortune() { getFortune() {
return Monnaie.getFortune(this.itemTypes['monnaie']); return Monnaie.getFortune(this.itemTypes[ITEM_TYPES.monnaie]);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -418,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
}) })
@@ -462,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.`
}) })
@@ -516,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),
@@ -663,7 +695,7 @@ export class RdDBaseActor extends Actor {
if (srcId != destId && itemId != destId) { // déplacement de l'objet if (srcId != destId && itemId != destId) { // déplacement de l'objet
const src = this.getItem(srcId); const src = this.getItem(srcId);
const dest = this.getItem(destId); const dest = this.getItem(destId);
const cible = this.getContenantOrParent(dest); const cible = this.findConteneurOrParent(dest);
const [empilable, message] = item.isInventaireEmpilable(dest); const [empilable, message] = item.isInventaireEmpilable(dest);
if (empilable) { if (empilable) {
await dest.empiler(item) await dest.empiler(item)
@@ -685,15 +717,15 @@ export class RdDBaseActor extends Actor {
return result; return result;
} }
getContenantOrParent(dest) { findConteneurOrParent(dest) {
if (!dest || dest.isConteneur()) { if (!dest || dest.isConteneur()) {
return dest; return dest;
} }
return this.getContenant(dest); return this.findConteneur(dest)
} }
getContenant(item) { findConteneur(item) {
return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id)); return this.itemTypes[ITEM_TYPES.conteneur].find(it => it.system.contenu.includes(item.id));
} }
@@ -861,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") }
@@ -881,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

@@ -16,7 +16,7 @@ export class RdDTextEditor {
$(html).on("click", '.roll-text', async event => await RdDTextEditor.rollText(event)) $(html).on("click", '.roll-text', async event => await RdDTextEditor.rollText(event))
} }
static async enrichHTML(text, object, options = {showlink:true}) { static async enrichHTML(text, object, options = { showlink: true }) {
const context = { const context = {
text, text,
object, object,
@@ -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]
} }
@@ -215,11 +217,13 @@ export class ChatUtility {
static async onRenderChatMessage(chatMessage, html, data) { static async onRenderChatMessage(chatMessage, html, data) {
const rddTimestamp = chatMessage.getFlag(SYSTEM_RDD, 'rdd-timestamp') const rddTimestamp = chatMessage.getFlag(SYSTEM_RDD, 'rdd-timestamp')
if (rddTimestamp) { const heureRdD = $(html).find('header.message-header .heure-rdd')
if (rddTimestamp && heureRdD.length == 0) {
const messageTimestamp = $(html).find('header.message-header .message-timestamp');
const timestamp = new RdDTimestamp(rddTimestamp); const timestamp = new RdDTimestamp(rddTimestamp);
const timestampData = timestamp.toCalendrier(); const timestampData = timestamp.toCalendrier();
const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData); const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData);
$(html).find('header.message-header .message-timestamp').after(dateHeure) messageTimestamp.after(dateHeure)
} }
} }
@@ -238,25 +242,4 @@ export class ChatUtility {
const date = new Date(chatMessage.timestamp); const date = new Date(chatMessage.timestamp);
return date?.toISOString().substring(0, 10) return date?.toISOString().substring(0, 10)
} }
// async flush() {
// const question = game.i18n.localize("AreYouSure");
// const warning = game.i18n.localize("CHAT.FlushWarning");
// return foundry.applications.api.DialogV2.confirm({
// window: {title: "CHAT.FlushTitle"},
// content: `<p><strong>${question}</strong> ${warning}</p>`,
// position: {
// top: window.innerHeight - 150,
// left: window.innerWidth - 720
// },
// yes: {
// callback: async () => {
// await this.documentClass.deleteDocuments([], {deleteAll: true});
// const jumpToBottomElement = document.querySelector(".jump-to-bottom");
// jumpToBottomElement.hidden = true;
// }
// }
// });
// }
} }

View File

@@ -7,8 +7,6 @@ const fields = foundry.applications.fields
export class DialogFlushByDate { export class DialogFlushByDate {
static async init() { static async init() {
Hooks.on("renderChatMessageHTML", async (app, html, msg) => await ChatUtility.onRenderChatMessage(app, html, msg))
Hooks.on("createChatMessage", async (chatMessage, options, id) => await ChatUtility.onCreateChatMessage(chatMessage, options, id))
Hooks.once("renderChatLog", async () => await DialogFlushByDate.onFirstRenderChatLog()) Hooks.once("renderChatLog", async () => await DialogFlushByDate.onFirstRenderChatLog())
} }

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 suivant = game.actors.get(link.id) const newSuivants = actor.system.subacteurs.suivants.filter(link => game.actors.get(link.id) != undefined)
const prochainCoeur = link.prochainCoeur ?? 0; .map(link => {
const coeurCourant = link.coeur ?? 0; const suivant = game.actors.get(link.id)
const diff = prochainCoeur - coeurCourant const prochainCoeur = link.prochainCoeur ?? 0
if (diff < 0) { const coeurCourant = link.coeur ?? 0
await actor.moralIncDec(-4); const diff = prochainCoeur - coeurCourant
link.coeur = Math.max(0, coeurCourant - 1) if (diff < 0) {
link.prochainCoeur = link.coeur ajustMoral -= 4
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.` link.coeur = Math.max(0, coeurCourant - 1)
count++ 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.`
else if (diff > 0) { count++
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}.` if (diff > 0) {
link.prochainCoeur = link.coeur link.coeur = Math.min(prochainCoeur, 4)
count++ 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
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

@@ -13,7 +13,7 @@ export class Distance {
} }
return undefined return undefined
} }
switch (attaque.comp.type) { switch (attaque.comp?.type) {
case ITEM_TYPES.competence: return mapTypeAttaque(attaque.main) case ITEM_TYPES.competence: return mapTypeAttaque(attaque.main)
case ITEM_TYPES.competencecreature: return mapTypeAttaque(attaque.arme.system.categorie) case ITEM_TYPES.competencecreature: return mapTypeAttaque(attaque.arme.system.categorie)
} }
@@ -36,20 +36,19 @@ export class Distance {
} }
static distance(token, defenderToken) { static distance(token, defenderToken) {
if (token instanceof Token && defenderToken instanceof Token) { if (Distance.$isToken(token) && Distance.$isToken(defenderToken)) {
const ray = new foundry.canvas.geometry.Ray( const source = token.getCenterPoint()
token.getCenterPoint(), const target = defenderToken.getCenterPoint()
defenderToken.getCenterPoint() const measure = canvas.grid.measurePath([ source, target])
) return measure.distance
return Number(canvas.grid.measureDistances([{ ray }], { gridSpaces: false }))
} }
return -1 /* distance indéterminée */ return -1 /* distance indéterminée */
} }
static isVisible(token, defenderToken) { static isVisible(token, defenderToken) {
// TODO: regarder les StatusEffect aveuglé? // TODO: regarder les StatusEffect aveuglé?
if (token instanceof Token && defenderToken instanceof Token) { 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
} }
@@ -79,11 +78,11 @@ export class Distance {
} }
static ajustementMouvement(defenderToken) { static ajustementMouvement(defenderToken) {
if (defenderToken instanceof Token) { if (Distance.$isToken(defenderToken)) {
if (defenderToken.actor?.getSurprise(true) != '') return { msg: "immobile (surprise)", diff: 0 }; if (defenderToken.actor?.getSurprise(true) != '') return { msg: "immobile (surprise)", diff: 0 };
if (defenderToken.inCombat) return { msg: "en mouvement (combat)", diff: -4 }; if (defenderToken.inCombat) return { msg: "en combat", diff: -4 };
} }
return { msg: "à déterminer (0 immobile, -3 actif, -4 en mouvement, -5 en zig-zag)", diff: -3 }; return { msg: "à déterminer", diff: -3 };
} }
static diff(...ajustements) { static diff(...ajustements) {
@@ -116,4 +115,8 @@ export class Distance {
return undefined return undefined
} }
static $isToken(token) {
return token instanceof Token || token instanceof TokenDocument
}
} }

View File

@@ -7,7 +7,7 @@ import { TMRUtility } from "./tmr-utility.js";
export class DialogCreateSigneDraconique extends Dialog { export class DialogCreateSigneDraconique extends Dialog {
static async createSigneForActors() { static async createSigneForActors() {
const signe = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true}); const signe = await RdDItemSigneDraconique.randomSigneDraconique({ ephemere: true });
let dialogData = { let dialogData = {
signe: signe, signe: signe,
tmrs: TMRUtility.buildSelectionTypesTMR(signe.system.typesTMR), tmrs: TMRUtility.buildSelectionTypesTMR(signe.system.typesTMR),
@@ -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() {
@@ -81,7 +81,7 @@ export class DialogCreateSigneDraconique extends Dialog {
} }
async setSigneAleatoire() { async setSigneAleatoire() {
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true}); const newSigne = await RdDItemSigneDraconique.randomSigneDraconique({ ephemere: true });
this.html.find("[name='signe.name']").val(newSigne.name); this.html.find("[name='signe.name']").val(newSigne.name);
this.html.find("[name='signe.system.valeur.norm']").val(newSigne.system.valeur.norm); this.html.find("[name='signe.system.valeur.norm']").val(newSigne.system.valeur.norm);
@@ -92,7 +92,7 @@ export class DialogCreateSigneDraconique extends Dialog {
this.html.find("[name='signe.system.ephemere']").prop("checked", newSigne.system.ephemere); this.html.find("[name='signe.system.ephemere']").prop("checked", newSigne.system.ephemere);
this.dialogData.tmrs = TMRUtility.buildSelectionTypesTMR(newSigne.system.typesTMR); this.dialogData.tmrs = TMRUtility.buildSelectionTypesTMR(newSigne.system.typesTMR);
this.dialogData.tmrs.forEach(t => { this.dialogData.tmrs.forEach(t => {
this.html.find(`[data-tmr-name='${t.name}']`).prop( "checked", t.selected); this.html.find(`[data-tmr-name='${t.name}']`).prop("checked", t.selected);
}) })
this.setEphemere(newSigne.system.ephemere); this.setEphemere(newSigne.system.ephemere);
} }
@@ -113,7 +113,7 @@ export class DialogCreateSigneDraconique extends Dialog {
onSelectTmr(event) { onSelectTmr(event) {
const tmrName = this.html.find(event.currentTarget)?.data("tmr-name"); const tmrName = this.html.find(event.currentTarget)?.data("tmr-name");
const onTmr = this.dialogData.tmrs.find(it => it.name == tmrName); const onTmr = this.dialogData.tmrs.find(it => it.name == tmrName);
if (onTmr){ if (onTmr) {
onTmr.selected = event.currentTarget.checked; onTmr.selected = event.currentTarget.checked;
} }
} }

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;
@@ -136,7 +166,7 @@ export class RdDItemCompetence extends RdDItem {
return troncList; return troncList;
} }
} }
return []; return []
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@@ -16,6 +16,7 @@ import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
import { ItemAction } from "./item/item-actions.js"; import { ItemAction } from "./item/item-actions.js";
import { SANS_COMPETENCE } from "./item/base-items.js"; import { SANS_COMPETENCE } from "./item/base-items.js";
import { Apprecier } from "./moral/apprecier.mjs"; import { Apprecier } from "./moral/apprecier.mjs";
import { CARACS } from "./rdd-carac.js";
/** /**
* Extend the basic ItemSheet for RdD specific items * Extend the basic ItemSheet for RdD specific items
@@ -118,7 +119,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
this.item.type == ITEM_TYPES.meditation || this.item.type == ITEM_TYPES.meditation ||
this.item.type == ITEM_TYPES.oeuvre) { this.item.type == ITEM_TYPES.oeuvre) {
formData.caracList = foundry.utils.duplicate(game.model.Actor.personnage.carac) formData.caracList = foundry.utils.duplicate(game.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.model.Actor.personnage.reve.reve) formData.caracList[CARACS.REVE_ACTUEL] = foundry.utils.duplicate(game.model.Actor.personnage.reve.reve)
} }
if (this.item.type == ITEM_TYPES.arme) { if (this.item.type == ITEM_TYPES.arme) {
formData.competences = formData.competences.filter(it => it.isCompetenceArme()) formData.competences = formData.competences.filter(it => it.isCompetenceArme())

View File

@@ -41,6 +41,11 @@ export class RdDItemSort extends RdDItem {
return value ? value.replace('variable', 'var') : '' return value ? value.replace('variable', 'var') : ''
} }
static computeTotalXP(sorts) {
return sorts.map(sort => RdDItemSort.isDifficulteVariable(sort) ? 70 : -10 * Misc.toInt(sort.system.difficulte))
.reduce(Misc.sum(), 0)
}
static isSortOnCoord(sort, coord) { static isSortOnCoord(sort, coord) {
let tmr = TMRUtility.getTMR(coord) let tmr = TMRUtility.getTMR(coord)
const caseTMR = sort.system.caseTMR.toLowerCase(); const caseTMR = sort.system.caseTMR.toLowerCase();
@@ -148,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

@@ -81,10 +81,14 @@ export const defaultItemImg = {
souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp", souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp",
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp", tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
tete: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp", tete: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp",
monnaie:"systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp", monnaie: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
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)"
@@ -185,6 +211,13 @@ export class RdDItem extends Item {
isCompetencePersonnage() { return this.type == ITEM_TYPES.competence } isCompetencePersonnage() { return this.type == ITEM_TYPES.competence }
isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature } isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature }
isConteneur() { return this.type == ITEM_TYPES.conteneur } isConteneur() { return this.type == ITEM_TYPES.conteneur }
findConteneur() {
if (this.isInventaire('all') && this.parent) {
return this.parent.findConteneur(this)
}
return undefined
}
isMonnaie() { return this.type == ITEM_TYPES.monnaie } isMonnaie() { return this.type == ITEM_TYPES.monnaie }
isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; } isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; }
isService() { return this.type == ITEM_TYPES.service } isService() { return this.type == ITEM_TYPES.service }
@@ -594,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

@@ -1,4 +1,4 @@
import { ACTOR_TYPES } from "../constants.js" import { ACTOR_TYPES, ITEM_TYPES } from "../constants.js"
import { Misc } from "../misc.js" import { Misc } from "../misc.js"
import { RdDSheetUtility } from "../rdd-sheet-utility.js" import { RdDSheetUtility } from "../rdd-sheet-utility.js"
import { RdDUtility } from "../rdd-utility.js" import { RdDUtility } from "../rdd-utility.js"
@@ -11,86 +11,98 @@ import { RdDUtility } from "../rdd-utility.js"
const _SPACEHOLDER = { placeholder: true } const _SPACEHOLDER = { placeholder: true }
const _VENDRE = { const _VENDRE = {
code: 'item-vendre', label: 'Vendre ou donner', icon: it => 'fa-solid fa-comments-dollar', code: 'item-vendre', label: 'Vendre ou donner', icon: 'fa-solid fa-comments-dollar',
filter: it => Misc.toInt(it.system.quantite) > 0 || it.parent?.type == ACTOR_TYPES.commerce, filter: it => Misc.toInt(it.system.quantite) > 0 || it.parent?.type == ACTOR_TYPES.commerce,
action: (item, actor) => item.proposerVente() action: (item, actor) => item.proposerVente()
} }
const _ACHETER = { const _ACHETER = {
code: 'item-acheter', label: 'Acheter', icon: it => 'fa-regular fa-coins', code: 'item-acheter', label: 'Acheter', icon: 'fa-regular fa-coins',
filter: it => it.parent?.type == ACTOR_TYPES.commerce, filter: it => it.parent?.type == ACTOR_TYPES.commerce,
allowLimited: true, allowLimited: true,
action: (item, actor) => actor.vente(item) action: (item, actor) => actor.vente(item)
} }
const _MONTRER = { const _MONTRER = {
code: 'item-montrer', label: 'Montrer', icon: it => 'fa-solid fa-comment', code: 'item-montrer', label: 'Montrer', icon: 'fa-solid fa-comment',
allowLimited: true, allowLimited: true,
action: (item, actor) => item.postItemToChat() action: (item, actor) => item.postItemToChat()
} }
const _SPLIT = { const _SPLIT = {
code: 'item-split', label: 'Séparer le goupe', icon: it => '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)
} }
const _EDIT = { const _EDIT = {
code: 'item-edit', label: 'Editer', icon: it => 'fa-solid fa-edit', code: 'item-edit', label: it => it.type == ITEM_TYPES.conteneur ? 'Ouvrir' : 'Editer',
icon: 'fa-solid fa-edit',
action: (item, actor) => item.sheet.render(true) action: (item, actor) => item.sheet.render(true)
} }
const _DELETE = { const _DELETE = {
code: 'item-delete', label: 'Supprimer', icon: it => 'fa-solid fa-trash', code: 'item-delete', label: 'Supprimer', icon: 'fa-solid fa-trash',
optionsFilter: options => options.isOwner, optionsFilter: options => options.isOwner,
action: (item, actor) => RdDUtility.confirmActorItemDelete(item, actor) action: (item, actor) => RdDUtility.confirmActorItemDelete(item, actor)
} }
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)
} }
const _CUISINER = { const _CUISINER = {
code: 'item-cuisiner', label: 'Cuisiner', code: 'item-cuisiner', label: 'Cuisiner',
img: it => 'systems/foundryvtt-reve-de-dragon/assets/actions/cuisine.svg', img: 'systems/foundryvtt-reve-de-dragon/assets/actions/cuisine.svg',
// icon: it => 'fa-solid fa-spoon', 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: it => '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: it => '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: it => '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: it => '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)
} }
const _OUVRIR = { const _OUVRIR = {
code: 'item-edit', label: 'Ouvrir', icon: it => 'fa-solid fa-eye', code: 'item-edit', label: 'Ouvrir',
img: 'systems/foundryvtt-reve-de-dragon/assets/actions/ouvrir.svg',
action: (item, actor) => item.sheet.render(true) action: (item, actor) => item.sheet.render(true)
} }
const _LIRE = { const _LIRE = {
code: 'item-lire', label: 'Lire', icon: it => '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: it => '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: it => '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)
} }
@@ -116,25 +128,39 @@ 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))
} }
static label(action, item) {
static img(action, item) { if (action.placeholder) {
if (action.placeholder){
return "" return ""
} }
if (action?.img) { return ItemAction.getParam(action.label, item)
return `<img src="${action.img(item)}" />` }
static img(action, item) {
if (action.placeholder) {
return ""
} }
if (action?.icon) {
return `<i class="${action.icon(item)}"></i>` const img = ItemAction.getParam(action.img, item)
if (img) {
return `<img src="${img}" />`
}
const icon = ItemAction.getParam(action.icon, item)
if (icon) {
return `<i class="${icon}"></i>`
} }
return action.label return action.label
} }
static getParam(p, item) {
return typeof (p) == 'function' ? p(item) : p
}
static async onActionItem(event, actor, options) { static async onActionItem(event, actor, options) {
const code = $(event.currentTarget).data('code') const code = $(event.currentTarget).data('code')
const item = RdDSheetUtility.getItem(event, actor) const item = RdDSheetUtility.getItem(event, actor)

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

@@ -70,7 +70,7 @@ export class RdDBonus {
dmgParticuliere: RdDBonus._dmgParticuliere(rollData), dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
dmgSurprise: rollData.opponent?.surprise?.dmg ?? 0, dmgSurprise: rollData.opponent?.surprise?.dmg ?? 0,
mortalite: RdDBonus.mortalite(attaque.dmg?.mortalite, arme?.system.mortalite), mortalite: RdDBonus.mortalite(attaque.dmg?.mortalite, arme?.system.mortalite),
dmgActor: RdDBonus.bonusDmg(actor, attaque.carac.key, dmgArme, attaque.forceRequise), dmgActor: RdDBonus.bonusDmg(actor, attaque.carac?.key, dmgArme, attaque.forceRequise),
dmgForceInsuffisante: Math.min(0, actor.getForce() - (attaque.forceRequise ?? 0)), dmgForceInsuffisante: Math.min(0, actor.getForce() - (attaque.forceRequise ?? 0)),
dmgDiffLibre: ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(attaque.diff ?? 0) : 0 dmgDiffLibre: ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(attaque.diff ?? 0) : 0
} }

View File

@@ -61,7 +61,9 @@ export const CARACS = {
DEROBEE: 'derobee', DEROBEE: 'derobee',
CHANCE_ACTUELLE: 'chance-actuelle', CHANCE_ACTUELLE: 'chance-actuelle',
REVE_ACTUEL: 'reve-actuel', REVE_ACTUEL: 'reve-actuel',
VIE: 'vie'
} }
export const LIST_CARAC_PERSONNAGE = { export const LIST_CARAC_PERSONNAGE = {
[CARACS.TAILLE]: { code: CARACS.TAILLE, label: 'Taille', isCarac: true, path: 'system.carac.taille.value' }, [CARACS.TAILLE]: { code: CARACS.TAILLE, label: 'Taille', isCarac: true, path: 'system.carac.taille.value' },
[CARACS.APPARENCE]: { code: CARACS.APPARENCE, label: 'Apparence', isCarac: true, path: 'system.carac.apparence.value' }, [CARACS.APPARENCE]: { code: CARACS.APPARENCE, label: 'Apparence', isCarac: true, path: 'system.carac.apparence.value' },
@@ -166,10 +168,18 @@ export class RdDCarac {
const total = Object.values(carac ?? {}).filter(c => !c.derivee) const total = Object.values(carac ?? {}).filter(c => !c.derivee)
.map(it => parseInt(it.value)) .map(it => parseInt(it.value))
.reduce(Misc.sum(), 0); .reduce(Misc.sum(), 0);
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0); const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0)
return total + beauteSuperieur10; return total + beauteSuperieur10;
} }
static computeTotalXp(carac, beaute = undefined) {
const totalXp = Object.values(carac ?? {}).filter(c => !c.derivee)
.map(it => RdDCarac.getCaracXp(0, Misc.toInt(it.value)) + Misc.toInt(it.xp))
.reduce(Misc.sum(), 0);
const beauteXp = beaute > 10 ? RdDCarac.getCaracXp(10, beaute) : 0
return totalXp + beauteXp;
}
static levelUp(it) { static levelUp(it) {
it.xpNext = RdDCarac.getCaracNextXp(it.value); it.xpNext = RdDCarac.getCaracNextXp(it.value);
it.isLevelUp = (it.xp >= it.xpNext); it.isLevelUp = (it.xp >= it.xpNext);
@@ -182,12 +192,16 @@ export class RdDCarac {
/* -------------------------------------------- */ /* -------------------------------------------- */
static getCaracNextXp(value) { static getCaracNextXp(value) {
const nextValue = Number(value) + 1; value = Number(value);
const nextValue = value + 1;
// xp est le coût pour atteindre cette valeur, on regarde donc le coût de la valeur+1 // xp est le coût pour atteindre cette valeur, on regarde donc le coût de la valeur+1
return RdDCarac.getCaracXp(nextValue); return RdDCarac.getCaracXp(value, nextValue)
} }
static getCaracXp(targetValue) { static getCaracXp(from, to) {
return RdDCarac.getCaracDerivee(targetValue)?.xp ?? 200; return Array.from({ length: to - from },
(_, i) => from + i + 1)
.map(it => RdDCarac.getCaracDerivee(it)?.xp ?? 200)
.reduce(Misc.sum(), 0)
} }
} }

View File

@@ -63,6 +63,11 @@ export class RdDCombatManager extends Combat {
it.token.id == tokenId it.token.id == tokenId
) )
} }
static getRangInitiativeCombatant(actorId, tokenId) {
const combatant = RdDCombatManager.getCombatant(actorId, tokenId)
return combatant?.system.init?.rang
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async nextRound() { async nextRound() {
await this.finDeRound(); await this.finDeRound();
@@ -165,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)
@@ -194,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)
} }
} }
} }
@@ -302,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)
} }
@@ -383,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;
@@ -462,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);
@@ -514,8 +505,8 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
attaqueChanceuse(attackerRoll) { attaqueChanceuse(attackerRoll) {
ui.notifications.info("L'attaque est rejouée grâce à la chance") ui.notifications.info("L'attaque est rejouée grâce à la chance")
attackerRoll.essais.attaqueChance = true; attackerRoll.essais.attaqueChance = true
this.attaque(attackerRoll, attackerRoll.arme); this.attaque(attackerRoll, attackerRoll.arme)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -619,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()
}) })
@@ -634,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()
}) })
@@ -642,20 +633,31 @@ export class RdDCombat {
} }
} }
async attaqueV2() { async attaqueV2(options = undefined) {
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) { if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
return return
} }
await this.doRollAttaque({ const rollData = {
ids: { ids: {
actorId: this.attackerId, actorId: this.attackerId,
actorTokenId: this.attackerTokenId, actorTokenId: this.attackerTokenId,
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: {},
passeArme: foundry.utils.randomID(16), passeArme: foundry.utils.randomID(16),
}) }
if (options) {
rollData.selected = {
attaque: {
comp: { id: options.comp.id },
arme: { id: options.arme.id },
main: options.main
}
}
}
await this.doRollAttaque(rollData)
} }
async doRollAttaque(rollData, callbacks = []) { async doRollAttaque(rollData, callbacks = []) {
@@ -721,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)
@@ -736,12 +738,14 @@ export class RdDCombat {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async attaque(competence, arme) { async attaque(competence, arme, main) {
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) { if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
return return
} }
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
return this.attacker.rollCompetence(competence.name, { arme: arme }) return this.attaqueV2(
{ comp: competence, arme: arme, main: main }
)
} }
if (arme.system.cac == EMPOIGNADE) { if (arme.system.cac == EMPOIGNADE) {
RdDEmpoignade.onAttaqueEmpoignade(this.attacker, this.defender) RdDEmpoignade.onAttaqueEmpoignade(this.attacker, this.defender)
@@ -750,9 +754,9 @@ export class RdDCombat {
RdDEmpoignade.checkEmpoignadeEnCours(this.attacker) RdDEmpoignade.checkEmpoignadeEnCours(this.attacker)
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)
@@ -925,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),
@@ -992,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 }))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -1118,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 }))
} }
} }
@@ -1152,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 }))
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -1239,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() {
@@ -116,6 +104,7 @@ export class RdDCommands {
this.registerCommand({ this.registerCommand({
path: ["/xp", "carac"], func: (content, msg, params) => this.getCoutXpCarac(msg, params), path: ["/xp", "carac"], func: (content, msg, params) => this.getCoutXpCarac(msg, params),
descr: `Détermine le coût d'expérience pour augmenter une caractéristique. Exemples: descr: `Détermine le coût d'expérience pour augmenter une caractéristique. Exemples:
<br>/xp carac 12 15: coût pour passer de 12 15
<br>/xp carac 15: coût pour atteindre 15 (depuis 14)` <br>/xp carac 15: coût pour atteindre 15 (depuis 14)`
}); });
@@ -215,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()
@@ -228,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
@@ -367,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}]` })
} }
} }
@@ -440,13 +440,18 @@ export class RdDCommands {
/* -------------------------------------------- */ /* -------------------------------------------- */
getCoutXpCarac(msg, params) { getCoutXpCarac(msg, params) {
if (params && params.length == 1) { if (params) {
let to = Number(params[0]); if (params.length == 1) {
return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to)}`); const to = Number(params[0])
} return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to - 1, to)}`);
else { }
return false; if (params.length == 2) {
const from = Number(params[0]);
const to = Number(params[1]);
return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${from} à ${to}: ${RdDCarac.getCaracXp(from, to)}`);
}
} }
return false
} }
async creerSignesDraconiques() { async creerSignesDraconiques() {

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) {
(it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) || const empoignade = attacker.itemTypes[ITEM_TYPES.empoignade].find(it =>
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id) (it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) ||
) (it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
if (emp) { )
return foundry.utils.duplicate(emp); if (empoignade) {
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,30 +279,34 @@ 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)
await this.onAttaqueEmpoignadeValidee(attacker, defender) if (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)
const empDefenseur = defender.itemTypes[ITEM_TYPES.empoignade] if (defender) {
.find(it => it.system.empoignadeid == empoignade.system.empoignadeid); const empDefenseur = defender.itemTypes[ITEM_TYPES.empoignade]
await defender.updateEmbeddedDocuments('Item', [{ .find(it => it.system.empoignadeid == empoignade.system.empoignadeid);
_id: empDefenseur.id, await defender.updateEmbeddedDocuments('Item', [{
'system.immobilise': true _id: empDefenseur.id,
}]) 'system.immobilise': true
const rollData = { }])
mode: "immobilise", const rollData = {
empoignade, attacker, defender, mode: "immobilise",
isEmpoignade: true, empoignade, attacker, defender,
competence: attacker.getCompetenceCorpsACorps() isEmpoignade: true,
competence: attacker.getCompetenceCorpsACorps()
}
const msg = await ChatMessage.create({
whisper: ChatUtility.getOwners(attacker),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-immobilise.hbs`, rollData)
})
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
const msg = await ChatMessage.create({
whisper: ChatUtility.getOwners(attacker),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-immobilise.hbs`, rollData)
})
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -304,30 +323,30 @@ 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) {
RdDEmpoignade.$createEtatEmpoignade(rollData.empoignade)
}
if (rollData.rolled.isSuccess && isNouvelle) { rollData.empoignade.isSuccess = rollData.rolled.isSuccess;
RdDEmpoignade.$createEtatEmpoignade(rollData.empoignade) if (rollData.rolled.isPart) {
rollData.particuliere = "finesse";
}
let msg = await RdDRollResult.displayRollData(rollData, defender, 'chat-empoignade-resultat.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
} }
rollData.empoignade.isSuccess = rollData.rolled.isSuccess;
if (rollData.rolled.isPart) {
rollData.particuliere = "finesse";
}
let msg = await RdDRollResult.displayRollData(rollData, defender, 'chat-empoignade-resultat.hbs');
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,35 +408,40 @@ 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) {
await attacker.creerObjetParMJ(empoignade) // Creer l'empoignade sur attaquant et defenseur
await defender.creerObjetParMJ(empoignade) await attacker.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)]
const removeEmp = empoignade.system.pointsemp == 0
if (removeEmp) { if (attacker && defender) {
const emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid) const belligerants = [attacker, defender]
return await attacker.deleteEmbeddedDocuments('Item', [emp.id]) const removeEmp = empoignade.system.pointsemp == 0
}
else { if (removeEmp) {
await Promise.all( const emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
belligerants.map(async belligerant => { return await attacker.deleteEmbeddedDocuments('Item', [emp.id])
const emp = RdDEmpoignade.getEmpoignadeById(belligerant, empoignade.system.empoignadeid) }
return await belligerant.updateEmbeddedDocuments('Item', [{ else {
_id: emp.id, await Promise.all(
"system.pointsemp": empoignade.system.pointsemp, belligerants.map(async belligerant => {
"system.ausol": empoignade.system.ausol const emp = RdDEmpoignade.getEmpoignadeById(belligerant, empoignade.system.empoignadeid)
}]) return await belligerant.updateEmbeddedDocuments('Item', [{
})) _id: emp.id,
"system.pointsemp": empoignade.system.pointsemp,
"system.ausol": empoignade.system.ausol
}])
}))
}
} }
} }
@@ -425,19 +449,21 @@ 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)
const emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid) if (defender) {
await defender.deleteEmbeddedDocuments('Item', [emp.id]) const emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
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

@@ -101,7 +101,7 @@ export class RdDHotbar {
} }
/** Roll macro */ /** Roll macro */
static rollMacro(itemName, itemType, categorieArme = 'competence') { static rollMacro(itemName, itemType, maniement = 'competence') {
const speaker = ChatMessage.getSpeaker(); const speaker = ChatMessage.getSpeaker();
let actor; let actor;
if (speaker.token) actor = game.actors.tokens[speaker.token]; if (speaker.token) actor = game.actors.tokens[speaker.token];
@@ -117,10 +117,10 @@ export class RdDHotbar {
// Trigger the item roll // Trigger the item roll
switch (item.type) { switch (item.type) {
case ITEM_TYPES.arme: case ITEM_TYPES.arme:
return actor.rollArme(item, categorieArme); return actor.rollArme(item, maniement);
case ITEM_TYPES.competence: case ITEM_TYPES.competence:
if (item.isCorpsACorps()) { if (item.isCorpsACorps()) {
switch (categorieArme) { switch (maniement) {
case PUGILAT: case PUGILAT:
return actor.rollArme(RdDItemArme.pugilat(actor)); return actor.rollArme(RdDItemArme.pugilat(actor));
case EMPOIGNADE: case EMPOIGNADE:
@@ -130,7 +130,7 @@ export class RdDHotbar {
return actor.rollCompetence(item); return actor.rollCompetence(item);
case ITEM_TYPES.competencecreature: case ITEM_TYPES.competencecreature:
return item.system.iscombat return item.system.iscombat
? actor.rollArme(item, categorieArme) ? actor.rollArme(item, maniement)
: actor.rollCompetence(item); : actor.rollCompetence(item);
} }

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,
@@ -358,6 +360,15 @@ export class SystemReveDeDragon {
}, },
default: "aucun" default: "aucun"
}) })
/* -------------------------------------------- */
game.settings.register(SYSTEM_RDD, "info-msg-timeout", {
name: "Gestion du timeout d'affichage du message d'information",
scope: "world",
config: false,
type: Number,
default: 0
})
} }
async onReady() { async onReady() {
@@ -366,7 +377,17 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */ /* -------------------------------------------- */
game.system.rdd.calendrier = new RdDCalendrier() game.system.rdd.calendrier = new RdDCalendrier()
if (Misc.isFirstConnectedGM()) { if (Misc.isFirstConnectedGM()) {
new Migrations().migrate() try {
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)
@@ -388,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
}) })
} }
@@ -416,7 +437,16 @@ export class SystemReveDeDragon {
<br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs} <br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs}
<br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div> <br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div>
` }) ` })
// Try to fetch the welcome message from the github repo "welcome-message-ecryme.html" // Get last message display time
const lastDisplay = game.settings.get(SYSTEM_RDD, "info-msg-timeout") || 0
const now = Date.now()
const oneDayMs = 24 * 60 * 60 * 1000
if (now - lastDisplay < oneDayMs) {
return // Already displayed in the last 24 hours
}
// Update last display time
game.settings.set(SYSTEM_RDD, "info-msg-timeout", now)
// Try to fetch the welcome message from the github repo RDD_INFO_MESSAGE_URL
fetch(RDD_INFO_MESSAGE_URL) fetch(RDD_INFO_MESSAGE_URL)
.then(response => response.text()) .then(response => response.text())
.then(html => { .then(html => {

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

@@ -2,6 +2,7 @@ import { RdDRoll } from "./rdd-roll.js";
import { Targets } from "./targets.js"; import { Targets } from "./targets.js";
import { ITEM_TYPES } from "./constants.js"; import { ITEM_TYPES } from "./constants.js";
import { RdDRollResult } from "./rdd-roll-result.js"; import { RdDRollResult } from "./rdd-roll-result.js";
import { CARACS } from "./rdd-carac.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
/* On part du principe qu'une entité démarre tjs /* On part du principe qu'une entité démarre tjs
@@ -96,15 +97,14 @@ export class RdDPossession {
static selectCompetenceDraconicOuPossession(rollData, rollingActor) { static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
rollData.competence = rollingActor.getDraconicOuPossession().find(it => true); rollData.competence = rollingActor.getDraconicOuPossession().find(it => true);
if (rollingActor.isCreatureOuEntite()) { if (rollingActor.isCreatureOuEntite()) {
const carac = rollingActor.system.carac rollData.carac = rollingActor.system.carac
rollData.carac = carac rollData.competence.system.defaut_carac = CARACS.REVE
rollData.competence.system.defaut_carac = 'reve' rollData.selectedCarac = rollingActor.system.carac.reve
rollData.selectedCarac = carac.reve
} }
else { else {
rollData.forceCarac = { 'reve-actuel': { label: "Rêve Actuel", value: rollingActor.getReveActuel() } } rollData.forceCarac = rollingActor.getCaracReveActuel()
rollData.selectedCarac = rollData.forceCarac['reve-actuel'] rollData.selectedCarac = rollData.forceCarac[CARACS.REVE_ACTUEL]
rollData.competence.system.defaut_carac = 'reve-actuel' rollData.competence.system.defaut_carac = CARACS.REVE_ACTUEL
} }
} }

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

@@ -4,7 +4,7 @@ import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemSort } from "./item-sort.js"; import { RdDItemSort } from "./item-sort.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js"; import { RdDBonus } from "./rdd-bonus.js";
import { RdDCarac } from "./rdd-carac.js"; import { CARACS, RdDCarac } from "./rdd-carac.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js"; import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
@@ -65,7 +65,7 @@ export class RdDRoll extends Dialog {
} }
// Mini patch :Ajout du rêve actuel // Mini patch :Ajout du rêve actuel
if (actor.type == ACTOR_TYPES.personnage) { if (actor.type == ACTOR_TYPES.personnage) {
defaultRollData.carac["reve-actuel"] = actor.system.reve.reve defaultRollData.carac[CARACS.REVE_ACTUEL] = actor.system.reve.reve
} }
foundry.utils.mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false }); foundry.utils.mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false });

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

@@ -93,7 +93,7 @@ export class RdDSheetUtility {
static async renderItemBranch(actor, item) { static async renderItemBranch(actor, item) {
while (item) { while (item) {
await item.sheet?.render() await item.sheet?.render()
item = actor.getContenant(item) item = actor.findConteneur(item)
} }
} }
} }

View File

@@ -16,6 +16,7 @@ import { RdDDice } from "./rdd-dice.js";
import { RdDRencontre } from "./item/rencontre.js"; import { RdDRencontre } from "./item/rencontre.js";
import { ITEM_TYPES } from "./constants.js"; import { ITEM_TYPES } from "./constants.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { CARACS } from "./rdd-carac.js";
const TMR_DISPLAY_SIZE = { const TMR_DISPLAY_SIZE = {
code: 'tmr-display-size', code: 'tmr-display-size',
@@ -48,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)
} }
@@ -125,7 +126,7 @@ export class RdDTMRDialog extends Dialog {
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getCoordActor())); HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getCoordActor()));
this.html.find('form.tmr-dialog *').click(event => { this.html.find('form.tmr-dialog *').click(event => {
if (this.subdialog?.rendered){ if (this.subdialog?.rendered) {
this.subdialog?.bringToFront() this.subdialog?.bringToFront()
} }
}) })
@@ -137,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...
@@ -304,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())
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -500,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)
}); });
@@ -652,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;
@@ -685,12 +686,12 @@ export class RdDTMRDialog extends Dialog {
tmr: tmr, tmr: tmr,
canClose: false, canClose: false,
diffLibre: -7, diffLibre: -7,
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } }, forceCarac: this.actor.getCaracReveActuel(),
maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' } maitrise: { verbe: 'maîtriser', action: 'Maîtriser le fleuve' }
} }
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined, rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined
rollData.competence.system.defaut_carac = 'reve-actuel'; rollData.competence.system.defaut_carac = CARACS.REVE_ACTUEL
await this._rollMaitriseCaseHumide(rollData); await this._rollMaitriseCaseHumide(rollData)
} }
} }
@@ -707,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)
}); });
@@ -727,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
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -746,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
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -810,30 +811,30 @@ export class RdDTMRDialog extends Dialog {
tmr: tmr, tmr: tmr,
canClose: options.canClose ?? false, canClose: options.canClose ?? false,
diffLibre: options.difficulte ?? -7, diffLibre: options.difficulte ?? -7,
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.actor.getReveActuel() } }, forceCarac: this.actor.getCaracReveActuel(),
maitrise: { verbe: 'conquérir', action: options.action } maitrise: { verbe: 'conquérir', action: options.action }
}; }
rollData.competence.system.defaut_carac = 'reve-actuel'; rollData.competence.system.defaut_carac = CARACS.REVE_ACTUEL
await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options)); await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onResultatConquerir(rollData, options) { async _onResultatConquerir(rollData, options) {
if (rollData.rolled.isETotal) { if (rollData.rolled.isETotal) {
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)
}); })
if (rollData.rolled.isEchec) { if (rollData.rolled.isEchec) {
options.onConqueteEchec(rollData, options.effetDraconique); options.onConqueteEchec(rollData, options.effetDraconique)
} }
else { else {
await options.onConqueteReussie(rollData, options.effetDraconique); await options.onConqueteReussie(rollData, options.effetDraconique)
this.updateTokens(); this.updateTokens()
} }
} }
@@ -875,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,
@@ -891,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)
}); });
@@ -967,7 +968,7 @@ export class RdDTMRDialog extends Dialog {
const targetOddq = this.pixiTMR.computeEventOddq(event) const targetOddq = this.pixiTMR.computeEventOddq(event)
const targetCoord = TMRUtility.oddqToCoordTMR(targetOddq) const targetCoord = TMRUtility.oddqToCoordTMR(targetOddq)
if (targetCoord == COORD_TMR_INCONNU){ if (targetCoord == COORD_TMR_INCONNU) {
ui.notifications.error("Vous ne pouvez pas vous déplacer ici"); ui.notifications.error("Vous ne pouvez pas vous déplacer ici");
return return
} }
@@ -1136,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))
@@ -348,6 +350,7 @@ export class RdDUtility {
// Items // Items
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field)); Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
Handlebars.registerHelper('item-action-applies', (action, item, options) => ItemAction.applies(action, item, options)) Handlebars.registerHelper('item-action-applies', (action, item, options) => ItemAction.applies(action, item, options))
Handlebars.registerHelper('item-action-label', (action, item) => new Handlebars.SafeString(ItemAction.label(action, item)))
Handlebars.registerHelper('item-action-img', (action, item) => new Handlebars.SafeString(ItemAction.img(action, item))) Handlebars.registerHelper('item-action-img', (action, item) => new Handlebars.SafeString(ItemAction.img(action, item)))
Handlebars.registerHelper('item-name', (item) => item.nameDisplay) Handlebars.registerHelper('item-name', (item) => item.nameDisplay)
@@ -482,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())
}) })
@@ -679,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: '' }
@@ -688,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
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -749,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?
}); });
@@ -843,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) {
@@ -941,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()) {
@@ -954,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 });
} }
} }
}); });
@@ -994,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
}); });

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