Compare commits

..

86 Commits

Author SHA1 Message Date
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
ecb653c40c Fix link !
All checks were successful
Release Creation / build (release) Successful in 1m37s
2025-12-20 18:43:08 +01:00
03051218b6 Info message !
All checks were successful
Release Creation / build (release) Successful in 3m21s
2025-12-20 17:44:11 +01:00
88a1e35648 Info message ! 2025-12-20 17:42:47 +01:00
0525acde53 Merge pull request 'v13.0.24 - Le grand oubli d'Illysis' (#789) from feature/v13-corrections into v13
Reviewed-on: https, #789
2025-12-20 17:20:59 +01:00
bf2b7567ca Correction cuisiner
- icone de l'action différente de "manger"
- correction tooltip dans fenêtre de jet
- support d'images svg pour les item-actions
- prise en compte de la difficulté de préparation brute
2025-12-19 23:52:12 +01:00
c305f9712c Correction boutons de maladresses pour joueur 2025-12-19 03:02:35 +01:00
10085dc3f1 Correction enchantement 2025-12-19 02:00:08 +01:00
bd39c0f633 Correction message d'erreur sur Hook update/create
Les Hook d'update/create sont appelés pour tous les joueurs.
Le filtrage pour n'exécuter qu'une fois les modifications
supplémentaires se basait sur game.user.activeGM qui est
toujours défini, au lieu de le comparer au joueur courant
pour s'assurer de ne faire l'action que pour le premier
joueur connecté propriétaire du personnage.
2025-12-19 01:52:18 +01:00
a52d10a3b3 Bouton pour supprimer les anciens messages 2025-12-18 19:44:00 +01:00
9fd6d9026a Merge pull request 'feature/v13-corrections' (#788) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 3m0s
Reviewed-on: https, #788
2025-12-15 22:20:25 +01:00
9d1a1238a2 Suivi du rollMode pour les jets 2025-12-15 21:27:45 +01:00
0563286cca Correction de combat
- filtrage des parades selon l'attaque
- gestion des tactiques
2025-12-15 01:09:35 +01:00
dbe5d0b974 Correction: jet avec compétence 2025-12-15 01:09:35 +01:00
80cac2fadb Recherche des caractéristiques de créature
La recherche des caractéristiques de créatures cherche aussi
dans les caractéristiques de leurs compétences
2025-12-15 01:09:34 +01:00
d591c5c183 Statut inconscient pour les créatures 2025-12-15 01:09:34 +01:00
df9f8a9f5f Suppression de l'option "mode test roll V2"
Ce mode permettait de ne pas fermer la fenêtre de jet pour des tests
répétitifs, ce n'est plus nécessaire
2025-12-15 01:09:34 +01:00
67a085f884 Corrections soins des blessures V2 2025-12-15 01:09:34 +01:00
e33727ac8d Consommation part le consommateur
Pour afficher la fenêtre d'appréciation côté acheteur, et utiliser ses
dés
2025-12-15 01:09:34 +01:00
455beb2820 Merge pull request '13.0.22 - Les reflets d'Illysis' (#787) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 2m29s
Reviewed-on: https, #787
2025-12-13 18:17:15 +01:00
c4794cd276 La fenêtre d'appréciation doit se fermer
la fenêtre d'appréciation se ferme automatiquement
2025-12-13 02:54:24 +01:00
f6581c7b3b Changement de message de non appréciation
Quand l'appréciation ne donne pas de jet de moral, le message
donnant les raisons est ajouté dans le tchat
2025-12-13 02:45:07 +01:00
c61cc5da18 Amélioration des remoteActorCall 2025-12-13 02:43:58 +01:00
bb51d1c1d0 Correction erreur sur appel chance
cas particulier non reproduit, le savedRoll ne peut pas être dupliqué.
2025-12-13 02:31:42 +01:00
a5165a2909 Pas de tactiques pour les attaques à distance 2025-12-13 02:08:34 +01:00
75a50257ac Attaques à distance sans tokens
- correction d'attaques à distance depuis l'onglet combat sans token
sélectionné
2025-12-13 02:07:49 +01:00
31764e0118 Fermeture de la fenêtre de jet depuis un lien 2025-12-13 02:05:46 +01:00
2894905fc6 Fenêtre de jet V2 pour jet quelconque 2025-12-13 02:04:27 +01:00
d6a492eef2 Fix: aucune oeuvre connu
La fenêtre de jet se comporte correctement si le personnage
ne connait pas d'oeuvre
2025-12-13 01:09:00 +01:00
97cb730ab5 Fix: aucun jeu connu
La fenêtre de jet se comporte correctement si le personnage
ne sait pas jouer,
2025-12-13 01:09:00 +01:00
a4e614860a Fix: aucune méditation connue
Cas de haut-rêvant ne connaissant pas de méditations
2025-12-13 01:09:00 +01:00
8077656ea1 Fix erreurs dans console sur fenêtre TMR
ajout de mécanismes de sécurité pour éviter erreur rare (liée
à un état étrange après avoir été dans les TMR)
2025-12-13 01:09:00 +01:00
7ea1f36852 Corrections mise sort en réserve
La mise en réserve de sorts depuis la feuille de personne
ne marchait pas à cause de rêve variables
2025-12-13 01:08:59 +01:00
2c7fd32ae6 Fix typo 2025-12-13 01:08:59 +01:00
9574792963 Icones pour acteurs et scènes 2025-12-13 01:08:59 +01:00
2912b5ce9b Fix possession - defense 2025-12-13 01:08:59 +01:00
b939d9bebf Correction affichage colonnes réussite
affichage des colonnes de réussite/ajustement nécessaire
2025-12-13 01:08:59 +01:00
6907344be7 Résolution de soucis inter-types de jets V2
- diminution de la dépendance au token cible pour les attaques
- ne pas proposer l'attaque sur les jets "par défaut"
- filtrer les sous-parties inutiles (ie: sorts pour les attaques, etc)
2025-12-12 17:42:43 +01:00
3567885030 Police lisible dans les messages de tchat
Résout des problèmes de polices pas toujours cohérentes dans
les messages de tchat
2025-12-12 17:40:27 +01:00
15ce2588b8 Correction sur défense 2025-12-11 03:26:38 +01:00
30090872d4 Gestion défense à distance 2025-12-11 03:12:49 +01:00
4f4e00b298 Ajout: Information de distance 2025-12-11 03:12:49 +01:00
697247e931 Fix: protection sur actions sans acteur/propriété
Cas rencontré une fois, un jet de chance d'un autre
joueur, pouvait être tenté.

Cas plus étrange, un jet de chance alors que le jet sauvegardé
n'avait pas d'actorId
2025-12-11 03:12:48 +01:00
894161c0bf Fix: Encombrement décimal 2025-12-11 03:12:48 +01:00
6882b4819c Correction: ajout de notes 2025-12-11 03:12:48 +01:00
275c144ea2 Préparation v13.0.22 2025-12-11 03:12:48 +01:00
3c5cfbb609 Merge pull request 'v13.0.21 - La folie d'Illysis' (#786) from feature/v13-possession-v2 into v13
All checks were successful
Release Creation / build (release) Successful in 3m21s
Reviewed-on: https, #786
2025-12-08 20:23:57 +01:00
151 changed files with 2278 additions and 2340 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,449 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512.07 512" style="enable-background:new 0 0 512.07 512;" xml:space="preserve">
<style type="text/css">
.st0{display:none;}
.st1{display:inline;}
.st2{fill:#DCDCDC;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
</style>
<g id="icon_x5F_sidebar_x5F_chat" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M180,480.93c14-15.25,27.95-29.3,40.56-44.47c14.18-17.05,23.54-36.69,26.34-59.05
c1.66-13.29-0.67-25.98-5.04-38.48c-1.8-5.15-5.7-5.52-10.23-5.78c-18.92-1.08-37.99-1.21-56.71-3.83
c-40-5.59-76.63-19.99-107.18-47.16c-36.18-32.19-46.99-77.73-26.93-122.29c15.37-34.14,40.96-59.17,71.93-78.94
c47.68-30.44,100.22-45.65,156.55-49.23c41.61-2.64,81.81,2.91,120.81,17.42c26.15,9.73,48.71,24.87,66.74,46.2
c29.1,34.42,32.23,80.62,8.86,120.58c-23.61,40.37-58.93,67.06-100.58,86.28c-10.17,4.7-20.81,8.38-31.3,12.36
c-4.3,1.63-6.47,4.24-6.8,9.02c-2.04,29.43-14.23,54.78-32.77,77.05c-29.18,35.06-66,59.86-107.6,77.9
C184.67,479.39,182.56,480.01,180,480.93z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_rolltable" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M255.1,55.46c6.7,2.37,12.64,3.53,17.63,6.38c47.83,27.36,95.49,55,143.19,82.58
c1.76,1.02,3.5,2.14,5.06,3.43c4.67,3.85,4.73,8.08-0.19,11.57c-4.48,3.18-9.3,5.9-14.07,8.66
c-43.81,25.34-87.68,50.58-131.43,76.01c-12.79,7.43-25.19,8.02-38.18,0.44c-47.26-27.53-94.66-54.81-141.95-82.29
c-11.67-6.78-11.5-10.86,0.17-17.61c45.93-26.57,91.78-53.27,137.82-79.64C240.07,61.03,247.84,58.57,255.1,55.46z
M256.6,177.07c8.18-2.74,15.83-4.76,23.02-7.85c6.75-2.9,11.12-8.42,11.32-16.12c0.2-7.86-4.55-13.18-10.98-16.36
c-16.34-8.07-32.92-8.99-48.94,0.93c-13.18,8.17-13.33,23.46,0.28,30.9C238.94,172.75,248.01,174.3,256.6,177.07z
M139.44,174.49c10.51,0.36,20.31-1.78,28.43-8.85c7.92-6.9,8.07-17.96,0.6-25.36c-13.09-12.97-44.39-13.07-57.62-0.19
c-8.94,8.7-8.15,19.73,2.02,27.08C120.8,172.91,129.82,174.83,139.44,174.49z M371.05,174.5c13.13,0.01,20.45-1.93,27.72-7.04
c11.22-7.88,11.04-21.8-0.38-29.44c-14.58-9.76-37.05-9.78-51.54-0.06c-11.6,7.78-11.75,21.98-0.23,29.88
C354.29,173.1,362.88,175.12,371.05,174.5z M257.2,200.1c-10.74-0.21-20.43,1.8-28.51,8.53c-9.63,8.02-9.2,19.91,0.7,27.6
c13.81,10.71,40.59,10.4,54.05-0.63c9.82-8.05,9.29-21.21-1.19-28.54C274.59,201.7,265.94,199.86,257.2,200.1z M255.77,105.95
c10.86-0.08,20.49-2.25,28.35-9.28c8.51-7.61,8.52-17.75,0.3-25.54c-13.52-12.81-43.78-12.59-57.1,0.4
c-7.45,7.27-7.44,17.61,0.19,24.78C235.62,103.93,245.78,105.61,255.77,105.95z"/>
</g>
<g>
<path class="st2" d="M73.56,270.29c-0.01-23.47-0.01-46.95,0-70.42c0-2.24-0.04-4.5,0.09-6.73c0.55-9.08,4.45-11.43,12.3-7.03
c14.77,8.29,29.43,16.78,44.1,25.25c31.29,18.06,62.49,36.27,93.87,54.16c13.59,7.75,19.9,19.03,19.84,34.61
c-0.18,47.56-0.07,95.12-0.07,142.68c0,1.02,0,2.04-0.03,3.06c-0.37,10.88-4.46,13.26-13.91,7.81
c-46.51-26.8-93.02-53.6-139.43-80.56c-11.08-6.44-16.76-16.38-16.77-29.35C73.56,319.28,73.57,294.79,73.56,270.29z
M238.89,301.12c-1.04-15.22-9.94-29.1-25.87-37.67c-12.78-6.88-25.53,0.97-25.17,15.07c0.45,18,8.76,32.2,24.15,41.47
C226.27,328.58,238.87,320.93,238.89,301.12z M238.88,424.25c-0.03-14.84-11.77-33.85-24.91-40.35
c-13.82-6.83-27.24,1.36-26.24,16.4c1.14,17.22,9.44,30.68,24.03,39.63C226.22,448.8,238.92,441.17,238.88,424.25z
M78.36,336.56c-0.07,16.35,12.18,35.46,26.64,41.57c13.6,5.74,24.53-1.52,24.14-16.28c-0.47-17.75-9.44-30.82-23.63-40.54
c-5.85-4.01-12.62-5.05-19.12-1.43C80,323.43,78.2,329.62,78.36,336.56z M78.16,216.83c1.81,17.43,9.33,31.66,25.03,40.21
c13.84,7.55,26.4-0.25,25.96-15.46c-0.51-17.56-9.43-30.51-23.26-40.31c-5.78-4.1-12.64-5.27-19.16-1.76
C80.09,203.09,78.12,209.49,78.16,216.83z"/>
</g>
<g>
<path class="st2" d="M438.48,269.36c0,23.88-0.09,47.77,0.04,71.65c0.08,14.95-5.66,26.05-19.04,33.69
c-45.56,26.01-90.87,52.43-136.3,78.66c-1.93,1.11-4.02,2.03-6.14,2.72c-4.13,1.36-6.9-0.45-7.9-4.42
c-0.69-2.73-0.78-5.65-0.78-8.49c-0.04-48.18,0.04-96.35-0.07-144.53c-0.03-14.73,6.49-25.32,19.04-32.56
c44.18-25.53,88.36-51.07,132.54-76.6c1.24-0.71,2.5-1.39,3.75-2.08c11.32-6.2,14.8-4.14,14.84,9.08
C438.53,220.78,438.48,245.07,438.48,269.36z M273.14,421.22c0.05,19.9,12.39,27.34,26.79,18.9
c14.92-8.75,23.03-22.32,24.24-39.46c1.09-15.44-12.22-24.3-25.6-16.81C282.99,392.57,274.73,406.59,273.14,421.22z
M273.19,300.58c-0.25,19.57,10.43,26.62,25.43,19.95c14.02-6.23,26.59-26.94,25.75-42.41c-0.77-14.26-13.04-21.55-25.73-14.51
C283.1,272.22,275.12,286.19,273.19,300.58z M378.55,373.28c0.05-21.14-11.77-28.95-25.77-20.61
c-15.26,9.09-24.61,22.51-24.5,41.07c0.1,15.52,11.79,22.77,25.39,15.25C369.25,400.38,377.63,386.78,378.55,373.28z
M433.65,340.47c0.1-20.18-12.26-27.99-26.62-19.24c-14.51,8.85-23.33,22.09-24,39.66c-0.62,16.14,11.34,23.92,25.59,16.37
C424.57,368.82,431.83,354.54,433.65,340.47z M378.56,249.19c0.11-16.72-10.87-24.46-24.88-17.53
c-15.12,7.48-26.59,27.54-25.35,44.37c0.88,11.94,10.06,18.07,21.51,14.37C365.3,285.38,378.44,266.54,378.56,249.19z
M433.67,217.08c0.11-15.23-9.9-22.9-23.27-17.86c-16.2,6.12-29.92,29.74-27.12,46.71c1.73,10.53,10.4,15.95,20.67,12.93
C419.6,254.24,433.54,234.65,433.67,217.08z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_actor">
<g>
<g>
<g>
<path class="st2" d="M194.72,240.85c-18.71-10.84-37.43-21.65-56.1-32.56c-4.38-2.56-3.72-6.78-3.09-10.93
c4.53-29.87,16.49-56.68,33.54-81.37c22.53-32.64,51.22-59.09,83.04-82.38c1.94-1.42,4.08-2.55,6.44-4.01
c2.95,1.91,5.76,3.52,8.35,5.44c34.2,25.36,64.61,54.39,87.21,90.87c13.92,22.47,23.34,46.63,27.11,72.93
c0.74,5.19-0.6,8.42-5.19,11.05c-17.12,9.83-34.08,19.93-51.1,29.92c-0.35-0.42-0.7-0.84-1.06-1.26
c7.2-7.59,13.9-15.74,21.74-22.61c6.97-6.11,8.08-12.73,6.54-21.27c-5.03-27.96-18.41-51.68-36.13-73.32
c-14.99-18.3-32.86-33.43-51.91-47.27c-3.26-2.37-6.29-3.56-10-0.89c-28.94,20.8-54.74,44.63-72.73,75.88
c-9.25,16.07-15.58,33.21-17.65,51.81c-0.5,4.49,0.65,7.78,3.76,10.99c9.23,9.52,18.23,19.25,27.32,28.9L194.72,240.85z"/>
</g>
<g>
<path class="st2" d="M168.55,345.65c-12.76,3.01-23.81-2.22-35.94-5.83c-3.63,12.02-1.15,22.71,4.28,33.16
c-0.52,0.49-1.04,0.98-1.56,1.47c-7.28-3.95-14.57-7.89-22.66-12.28c-0.94,40.71,5.85,79.96,12.76,120.22
c-9.73,0-18.21,0-28.31,0c0-4.71-0.17-8.65,0.03-12.57c2.77-54.5,0.73-108.5-16.69-160.88c-1.7-5.12-1.02-8.86,2.98-12.56
c15.25-14.13,30.3-28.49,45.51-42.67c1.86-1.73,4.21-2.92,7.2-4.95c12.66,31.79,36.38,51.55,65.92,65.71
c-23.56,4.18-43.99-5.23-64.98-14.12C142.45,319.03,153.45,333.5,168.55,345.65z"/>
</g>
<g>
<path class="st2" d="M378.56,342.15c-11.2,1.29-21.2,6.91-34.38,4.02c17.38-13.12,29.62-28.02,35.34-49.86
c-22.86,11.18-44.29,22.27-69.86,17.87c29.22-14.58,53.47-34,65.19-66.51c3.09,2.11,5.44,3.31,7.29,5.04
c15.49,14.48,30.83,29.13,46.36,43.57c3.94,3.66,4.92,7.36,3.13,12.52c-12.8,37.05-17.33,75.43-17.57,114.4
c-0.11,17.53,0.54,35.07,0.78,52.6c0.02,1.77-0.35,3.55-0.66,6.4c-8.97,0-17.6,0-27.36,0c6.32-39.97,13.54-79.18,12.38-120.61
c-8.84,4.81-16.27,8.85-23.71,12.89c-0.49-0.48-0.97-0.96-1.46-1.44C378.33,363.41,381.6,353.68,378.56,342.15z"/>
</g>
<g>
<path class="st2" d="M207.81,179.57c3.71-5.83,8.78-8.93,15.2-8.75c5.91,0.17,10.65,3.14,13.82,8.68
c-3.37,5.93-8.7,7.74-14.45,7.81C216.53,187.39,211.48,185.04,207.81,179.57z"/>
</g>
<g>
<path class="st2" d="M277.66,179.72c3.23-6.12,7.85-9.04,14-9c6.15,0.04,10.67,3.08,13.58,8.58c-2.43,6.15-7.58,7.55-12.87,7.82
C286.5,187.42,281.29,185.46,277.66,179.72z"/>
</g>
<g>
<path class="st2" d="M194.81,240.77c0,0-0.08,0.08-0.08,0.08C194.72,240.85,194.81,240.77,194.81,240.77z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_scene" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M141.31,362.45c10.55-10.81,21.11-21.61,32.39-33.17c-4.23-4.4-7.78-8.52-11.78-12.13
c-4.39-3.96-5.23-7.87-1.64-12.78c2.36-3.24,4.31-6.78,7.52-11.92c29.68,29.65,58.51,58.45,88.28,88.2
c29.63-29.58,58.38-58.28,88.43-88.27c3.76,6.48,7.17,11.44,9.48,16.88c0.68,1.6-1.26,4.92-2.82,6.75
c-3.78,4.43-8.04,8.45-12.61,13.15c3.87,4.06,7.01,7.46,10.26,10.75c6.02,6.1,12.2,12.04,18.09,18.27
c1.5,1.58,2.14,3.98,2.19,6.78c-11.12-2.35-15.32-13.36-25.7-18.87c-4.53,5.37-9.27,11-14.4,17.08
c4.03,8.46,15.77,12.55,18.84,22.89c-0.64,0.7-1.28,1.4-1.92,2.1c-2.18-1.32-4.7-2.29-6.49-4.01
c-7.5-7.21-14.75-14.68-22.17-21.99c-1.69-1.67-3.67-3.05-6.41-5.3c-5.41,5.88-10.51,11.42-16,17.4
c1.57,1.94,2.93,3.92,4.6,5.61c7.3,7.42,14.75,14.69,22,22.16c1.66,1.71,2.69,4.01,3.13,6.87
c-10.84-2.35-15.01-13.32-25.2-18.68c-4.93,5.38-10.02,10.94-15.43,16.85c4.67,9.02,15.38,13.49,19.26,23.07
c-0.54,0.67-1.09,1.34-1.63,2.01c-2.14-1.31-4.59-2.29-6.35-3.98c-7.49-7.22-14.75-14.69-22.17-21.99
c-1.69-1.66-3.68-3.01-5.89-4.79c-3.8,3-7.23,5.71-11.03,8.71c-3.77-2.97-7.19-5.68-11.01-8.69c-2.19,1.75-4.19,3.08-5.87,4.74
c-7.42,7.3-14.69,14.75-22.16,22c-1.73,1.67-4.02,2.76-6.91,3.23c2.31-10.77,13.12-15.02,18.63-25.24
c-5.42-4.76-11.09-9.74-17.21-15.11c-8.81,4.1-12.9,15.32-22.79,18.83c-0.62-0.47-1.25-0.95-1.87-1.42
c1.25-2.13,2.15-4.6,3.81-6.33c7.21-7.5,14.68-14.75,21.99-22.17c1.67-1.7,3.05-3.67,5.27-6.37
c-5.69-5.59-11.06-10.87-16.79-16.51c-2.48,2-4.47,3.36-6.16,5.02c-7.42,7.3-14.69,14.75-22.16,22c-1.71,1.66-4,2.72-6.87,3.19
c2.16-10.9,13.44-14.89,18.41-25.47c-5.23-4.81-10.76-9.89-16.39-15.06c-9.69,4.24-13.75,16.43-24.15,19.15
C143.03,364.74,142.17,363.6,141.31,362.45z"/>
</g>
<g>
<path class="st2" d="M441,403.48c-16.69-27.59-33.44-55.13-50.04-82.77c-42.46-70.68-84.85-141.39-127.26-212.1
c-1.34-2.23-2.47-4.58-4.3-8.02c13.34-3.15,24.63-8.77,32.97-20.46c1.71,2.53,2.89,3.85,3.6,5.4
c28.28,61.55,56.51,123.12,84.77,184.68c19.15,41.72,38.37,83.41,57.51,125.14c1.18,2.58,1.92,5.36,2.86,8.04L441,403.48z"/>
</g>
<g>
<path class="st2" d="M217.61,82.38c2.39,3.13,3.85,4.73,4.95,6.53c4.59,7.48,8.69,15.3,13.71,22.47
c4.35,6.21,4.12,11.18,0.16,17.73c-47.28,78.28-94.26,156.74-141.31,235.16c-6.51,10.85-13.01,21.71-19.54,32.55
c-1.13,1.88-2.39,3.68-4.72,4.92C119.57,295.76,168.27,189.77,217.61,82.38z"/>
</g>
<g>
<path class="st2" d="M477.25,255.92c-10.87-10.64-21.54-21.09-32.91-32.23c-5.58,5.75-10.68,11.01-16.24,16.75
c1.84,2.26,3.31,4.39,5.1,6.21c7.43,7.56,15,15,22.43,22.56c2.12,2.16,4.52,4.52-0.17,8.58c-7.22-6.76-14.48-13.55-21.88-20.47
c-6.08,5.51-11.66,10.57-17.97,16.3c7.88,8.42,14.65,15.65,21.42,22.88c-0.62,0.85-1.25,1.7-1.87,2.56
c-2.14-1.03-4.53-1.72-6.36-3.13c-13.8-10.59-21.18-25.52-27.46-41.16c-5.78-14.38-8.33-11.03,4.45-23.75
c7.23-7.19,14.4-14.44,21.65-21.61c1.71-1.69,3.62-3.17,5.84-5.08c1.73,1.12,3.41,1.86,4.63,3.06
c13.32,13.21,26.59,26.48,39.81,39.79C479.85,249.34,482.22,251.73,477.25,255.92z"/>
</g>
<g>
<path class="st2" d="M68.55,223.56c-12.92,10.59-22.16,23.11-34.32,32.22c-0.78-0.53-1.57-1.06-2.35-1.59
c0.43-1.85,0.25-4.3,1.39-5.46c14.33-14.51,28.84-28.83,43.34-43.18c0.39-0.38,1.12-0.42,1.97-0.71
c0.75,0.34,1.86,0.54,2.53,1.2c10.88,10.75,21.84,21.43,32.39,32.51c1.47,1.54,1.83,5.55,0.94,7.69
c-4.29,10.36-8.17,21.11-14.15,30.47c-5.16,8.08-12.9,14.53-19.62,21.58c-0.65,0.69-2.18,0.54-5.2,1.2
c3.65-11.71,15.03-15.79,20.22-26.77c-5.23-4.62-10.83-9.57-16.64-14.7c-9.41,4.67-13.78,15.49-23.35,19.4
c-0.67-0.54-1.35-1.07-2.02-1.61c1.11-1.99,1.87-4.32,3.4-5.91c7.07-7.35,14.38-14.47,21.55-21.72c1.84-1.86,3.48-3.92,6.4-7.23
C79.61,235.25,74.35,229.69,68.55,223.56z"/>
</g>
<g>
<path class="st2" d="M256.05,428.1c7.93,7.53,16.37,15.55,24.7,23.47c-8.21,8.27-16.4,16.51-24.37,24.54
c-8.23-7.98-16.67-16.16-25.11-24.34C239.8,443.62,248.21,435.58,256.05,428.1z"/>
</g>
<g>
<path class="st2" d="M254.88,73.27c6.48-5.93,12.68-11.6,18.52-16.94C275.4,65.47,265.2,75.93,254.88,73.27z"/>
</g>
<g>
<path class="st2" d="M238.87,49.47c0.54-7.99,6.12-13.62,15.88-13.57c-4.81,4.98-9.61,9.96-14.42,14.93
C239.84,50.38,239.35,49.92,238.87,49.47z"/>
</g>
<g>
<polygon class="st2" points="441.11,403.38 441.22,403.67 441,403.48 "/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_item" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M86.57,379.95c0-48.58,0-96.33,0-143.79c5.64-2.82,112.01-3.19,119.52-0.33c0.25,2.68,0.79,5.83,0.8,8.98
c0.07,26.94,0.01,53.88,0.08,80.83c0.01,3.17,0.51,6.33,0.85,10.3c32.36,0,63.92,0,97.01,0c0-33.87,0-66.95,0-99.19
c6.41-3.36,112.58-3.86,119.48-1.35c2.55,5.28,2.8,137.43-0.09,144.56C312.19,379.95,199.8,379.95,86.57,379.95z"/>
</g>
<g>
<path class="st2" d="M351.95,96.52c0,37.52,0,74.24,0,111.87c-15.41,0-30.07,0-45.61,0c-0.81-5.04-1.56-9.72-2.59-16.15
c-31.78-0.12-63.35-0.24-95.41,0.16c-1.01,5.85-1.81,10.52-2.76,16c-15.49,0-30.54,0-46.27,0c-0.48-3.17-1.18-5.7-1.19-8.24
c-0.08-31.43-0.09-62.85-0.03-94.28c0.02-8.73,1.64-10.33,10.48-10.33c58.36-0.05,116.72-0.03,175.09,0.01
C346.04,95.56,348.42,96.09,351.95,96.52z"/>
</g>
<g>
<path class="st2" d="M132.51,208.42c-9.52,0-18.03,0-27.47,0c0-37.52,0-74.16,0-111.86c9.22,0,17.87,0,27.47,0
C132.51,133.9,132.51,170.54,132.51,208.42z"/>
</g>
<g>
<path class="st2" d="M378.57,96.39c10.31,0,18.82,0,29.12,0c0.27,37.43,0.14,74.07,0.08,111.82c-10.01,0-18.66,0-29.13,0
C378.39,170.99,378.51,134.35,378.57,96.39z"/>
</g>
<g>
<path class="st2" d="M107.03,407.31c99.7,0,198.42,0,297.14,0c0.31,0.74,0.62,1.47,0.93,2.21c-3.8,2.18-7.48,4.61-11.44,6.42
c-1.72,0.78-4.02,0.36-6.06,0.36c-87.72,0.01-175.44-0.01-263.17,0.06C117.35,416.37,111.13,415.25,107.03,407.31z"/>
</g>
<g>
<path class="st2" d="M280.03,311.38c-16.62,0-31.68,0-47.61,0c0-31.35,0-61.94,0-93.7c15.6-1.68,30.82-0.85,47.53-0.45
C280.76,248.97,280.56,279.53,280.03,311.38z M267.36,293.14c0.39-3.77,0.85-6.35,0.89-8.94c0.12-7.13-0.2-14.28,0.21-21.39
c0.17-2.85,1.14-6.13,2.88-8.31c8.15-10.27,8.56-19.5,0.67-27.25c-8.45-8.3-21.51-8.87-30.61-1.33
c-8.41,6.98-10.24,17.21-3.09,25.35c4.73,5.38,5.6,10.91,5.4,17.36c-0.17,5.7-0.14,11.42,0.05,17.12
c0.08,2.32,0.82,4.63,1.34,7.39C252.64,293.14,259.56,293.14,267.36,293.14z"/>
</g>
<g>
<path class="st2" d="M459.64,208.46c-9.05,0-17.17,0-26.05,0c-0.44-3.46-1.09-6.2-1.09-8.93c-0.07-31.16-0.05-62.33-0.04-93.49
c0-1.22,0.07-2.44,0.15-3.66c0.3-4.41,2.7-6.57,7.1-6.7c4.5-0.13,6.66,2.09,7.24,6.46c4.34,32.91,8.76,65.81,13.07,98.73
C460.3,202.98,459.83,205.2,459.64,208.46z"/>
</g>
<g>
<path class="st2" d="M77.56,97.23c0,36.74,0,73.41,0,111.08c-8.48,0-16.35,0-25.02,0c-0.25-2.71-0.9-5.08-0.6-7.34
c4.21-32.52,8.49-65.04,12.9-97.53C65.84,96.02,68.83,94.5,77.56,97.23z"/>
</g>
<g>
<path class="st2" d="M451.71,362.72c0-42.84,0-84.74,0-127.72c3.45-0.21,6.42-0.39,10.08-0.61c0.46,3.5,1.09,6.04,1.1,8.58
c0.06,34.46-0.08,68.92,0.12,103.38C463.06,354.24,458.99,358.62,451.71,362.72z"/>
</g>
<g>
<path class="st2" d="M50.26,234.87c2.86,0,5.32,0,7.56,0c2.47,5.02,3.24,118.46,0.9,126.79c-5.37-3.13-9.67-6.58-9.66-13.41
c0.02-35.65-0.01-71.31,0.05-106.96C49.12,239.34,49.79,237.4,50.26,234.87z"/>
</g>
<g>
<path class="st2" d="M51.56,390.71c7.99,7.72,15.99,15.44,25.01,24.15c-9.12,2.16-16.82,2.02-24.49,0.42
c-1.03-0.21-2.41-2.03-2.45-3.14c-0.23-6.78-0.11-13.57-0.11-20.36C50.2,391.43,50.88,391.07,51.56,390.71z"/>
</g>
<g>
<path class="st2" d="M436.46,413.79c8.05-7.65,16.1-15.3,24.15-22.95c0.61,0.34,1.23,0.69,1.84,1.03
c0,6.76,0.19,13.52-0.17,20.26c-0.07,1.29-2.24,3.46-3.53,3.53c-7.16,0.35-14.35,0.17-21.53,0.17
C436.96,415.15,436.71,414.47,436.46,413.79z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_fight" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M98.54,121.71c7.19,0.33,14.38,0.67,22.81,1.06c1.18-7.93,2.28-15.34,3.38-22.75
c0.65-0.23,1.3-0.46,1.95-0.69c70.17,84.04,140.34,168.07,211.57,253.38c-9.84,8.24-18.85,15.78-28.82,24.13
C238.18,291.6,167.84,207.47,97.5,123.34C97.85,122.8,98.2,122.26,98.54,121.71z"/>
</g>
<g>
<path class="st2" d="M74.25,462.04c-10.75-7.58-20.15-14.21-30.69-21.64C87.39,378.65,130.68,317.64,175,255.19
c8.95,10.7,16.69,19.95,24.95,29.82C158.02,344.06,116.54,402.48,74.25,462.04z"/>
</g>
<g>
<path class="st2" d="M425.22,103.01c0.37,2.17,1.08,4.12,0.96,6.02c-1.52,23.89-10.41,44.55-26.71,62.21
c-17.85,19.34-40.04,31.93-63.81,42.21c-1.98,0.86-4.11,1.36-7.64,2.49c1.24-4.12,1.91-6.97,2.94-9.69
c6.52-17.26,11.93-34.75,11.33-53.5c-0.09-2.84-0.01-5.86-0.93-8.47c-2.37-6.7,0.06-11.13,5.24-15.36
c8.52-6.96,16.52-14.54,24.94-21.63c1.91-1.61,4.59-3.05,6.99-3.2c14.23-0.85,28.48-1.32,42.72-1.86
C422.24,102.2,423.23,102.61,425.22,103.01z"/>
</g>
<g>
<path class="st2" d="M291.85,453.14c-4.87-5.91-8.93-10.84-14.08-17.09c41.71-34.89,82.71-69.18,124.58-104.2
c4.79,5.78,8.96,10.8,14.01,16.89C374.53,383.82,333.55,418.17,291.85,453.14z"/>
</g>
<g>
<path class="st2" d="M273.79,115.61c10.76,7.57,20.25,14.24,30.73,21.61c-17.52,24.77-34.23,48.41-51.86,73.34
c-8.76-10.27-16.69-19.55-25.21-29.54C242.84,159.29,257.83,138.14,273.79,115.61z"/>
</g>
<g>
<path class="st2" d="M310.02,250.99c3.13-1.7,6.08-3.97,9.41-5.02c21.89-6.92,42.92-15.68,62.36-28.02
c29.04-18.43,51.93-42.06,63.17-75.38c4.67-13.85,6.52-28.16,6.18-42.77c-0.05-2.01-0.01-4.02-0.01-6.78
c3.9-2.17,7.86-4.37,12.69-7.05c1.31,3.33,2.56,5.61,3.12,8.05c3.1,13.52,1.31,26.78-2.57,39.85
c-16.18,54.48-81.45,113.08-140.32,120.1c-4.27,0.51-8.65,0.07-12.98,0.07C310.71,253.03,310.37,252.01,310.02,250.99z"/>
</g>
<g>
<path class="st2" d="M389.79,472.78c-11.28-13.51-21.9-26.23-33.01-39.54c8.13-9.93,17.68-16.81,28.3-24.44
c11.08,13.21,21.71,25.89,33.02,39.37C409.83,457.64,400.05,464.37,389.79,472.78z"/>
</g>
<g>
<path class="st2" d="M321.15,118.13c-11.98-8.39-23.18-16.22-35.16-24.61c4.46-12.23,8.63-23.66,13.37-36.67
c17.45,12.36,33.25,23.54,50.46,35.73C339.82,101.49,330.87,109.47,321.15,118.13z"/>
</g>
<g>
<path class="st2" d="M98.58,95.77c-7.12-0.81-13.28-1.35-19.35-2.36c-1.23-0.2-2.8-2.02-3.15-3.37
c-2.23-8.67-4.18-17.41-6.14-26.14c-0.15-0.68,0.35-1.51,0.74-2.98c1.89,0.47,3.64,0.68,5.2,1.33
c6.2,2.59,12.29,5.47,18.53,7.94c4.9,1.94,7.04,5.25,6.33,10.43C100.13,85.01,99.49,89.39,98.58,95.77z"/>
</g>
<g>
<path class="st2" d="M263.6,72.75c-4.58-8.72-9.17-17.44-14.34-27.29c9.64-1.5,17.2,0.6,26.32,3.04
c-3.26,8.72-6.26,16.73-9.26,24.75C265.41,73.08,264.5,72.92,263.6,72.75z"/>
</g>
<g>
<path class="st2" d="M328.1,39.22c10.42,7.7,21.69,12.69,29.96,23.17C349.73,64.21,326.41,46.59,328.1,39.22z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_compendium" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M172.73,49.37c21.98,0,43.98,0,66.87,0c0,137.52,0,274.28,0,412.73c-22.56,0.64-44.71,0.55-66.23,0.05
C170.22,455.66,169.78,57.56,172.73,49.37z M200.52,429.88c3.18-7.29,2.79-312.57-0.29-318.12c-6.66,0-13.58,0-20.13,0
c-3.18,7.31-2.79,312.56,0.29,318.12C187.06,429.88,193.98,429.88,200.52,429.88z M210.72,299.22
c-3.15,7.38-2.74,125.16,0.33,130.65c6.67,0,13.59,0,21.35,0c0-43.84,0-86.81,0-130.65
C224.64,299.22,217.72,299.22,210.72,299.22z"/>
</g>
<g>
<path class="st2" d="M145.38,142.76c0,85.62,0,170.31,0,256.67c-17.42,1.03-34.25,0.66-51.8,0.12
c-0.49-3.88-1.14-6.62-1.14-9.36c-0.05-79.17-0.06-158.34-0.03-237.52c0-9.54,1.47-10.94,11.07-11
c11.02-0.07,22.04-0.07,33.06,0.03C139.11,141.74,141.67,142.3,145.38,142.76z"/>
</g>
<g>
<path class="st2" d="M363.52,456.03c-12.7,2.35-23.74,4.39-35.68,6.6c-1.26-4.11-2.57-7.24-3.16-10.5
c-10.85-60.07-21.6-120.15-32.38-180.23c-7.75-43.2-15.53-86.4-23.26-129.6c-0.49-2.72-0.59-5.51-1-9.55
c12.13-2.2,23.57-4.27,36.31-6.58C324.11,236.33,343.65,345.24,363.52,456.03z"/>
</g>
<g>
<path class="st2" d="M30.77,95.93c12.29,0,23.52,0,35.63,0c0.49,3.12,1.29,5.83,1.29,8.53c0.07,53.47,0.07,106.95,0.02,160.42
c0,2.37-0.57,4.75-0.98,8c-11.97,0-23.53,0-35.96,0C30.77,213.88,30.77,155.54,30.77,95.93z"/>
</g>
<g>
<path class="st2" d="M367.58,238.23c7-3.03,12.81-5.54,20.08-8.69c31.66,74.22,62.88,147.39,94.52,221.55
c-7.17,3.14-12.98,5.68-20.06,8.77C430.48,385.69,399.26,312.48,367.58,238.23z"/>
</g>
<g>
<path class="st2" d="M65.98,461.62c-11.43,0-22.81,0-35.96,0c-0.23-38.48-0.1-76.1-0.08-114.56c13.02,0,24.42,0,35.56,0
C68.27,352.44,68.8,453.4,65.98,461.62z"/>
</g>
<g>
<path class="st2" d="M145.31,461.62c-17.64,0-34.34,0-51.98,0c0-12.22,0-23.59,0-34.65c5.83-2.99,44.82-3.3,51.98-0.36
C145.31,437.66,145.31,449.07,145.31,461.62z"/>
</g>
<g>
<path class="st2" d="M66.94,299.04c0,7.68,0,14,0,20c-5.68,3.23-28.48,3.6-36.48,0.32c0-5.15-0.23-10.92,0.17-16.64
c0.09-1.3,2.32-3.48,3.61-3.52C44.72,298.91,55.21,299.04,66.94,299.04z"/>
</g>
<g>
<path class="st2" d="M344.77,183.51c1.37-6.24,13.25-11.41,18.86-8.56C361.93,179.91,351.56,184.78,344.77,183.51z"/>
</g>
<g>
<path class="st2" d="M376.69,203.79c-1.47,1.58-2.66,3.99-4.46,4.57c-4.85,1.58-9.26,6.71-16.33,2.77
c5.69-6.11,12.27-7.7,18.8-9.41C375.37,202.41,376.03,203.1,376.69,203.79z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_settings" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M167.35,468.66c-13.39-1.77-50.61-24-55.69-33.14c1.08-1.73,2.27-3.8,3.62-5.75
c9.08-13.11,15.46-27.19,17.17-43.32c2.08-19.66-8.6-38.21-26.93-45.65c-18.45-7.49-36.8-5.28-55.13,0.52
c-2.27,0.72-4.61,1.24-7.95,2.13c-8.74-20.07-13.97-40.42-16.04-62.21c3.72-1,6.27-1.51,8.71-2.36
c10.15-3.55,20.93-5.98,30.28-11.03c32.02-17.29,37.2-51.45,11.57-77.58c-7.69-7.84-18.02-13.11-27.21-19.46
c-1.8-1.24-3.88-2.08-6.88-3.65c7.46-20.81,19.04-38.63,32.65-56.07c2.6,1.58,4.49,2.63,6.28,3.83
c12.84,8.66,26.44,15.16,42.16,16.87c27.62,3.01,49.81-16.05,50.75-43.89c0.44-12.98-0.7-25.69-5.26-37.95
c-0.57-1.52-0.94-3.13-1.27-4.72c-0.16-0.77-0.03-1.6-0.03-3.56c19.48-9.06,40.19-13.46,62.14-15.74
c1.02,3.75,1.82,6.21,2.34,8.72c3.47,16.64,9.06,32.26,21.51,44.52c15.73,15.49,38.24,17.59,56.71,5.52
c12.09-7.9,21.07-18.51,27.72-31.22c1.77-3.4,3.56-6.79,5.82-11.11c21.09,7.8,39.67,18.42,56.8,32.93
c-1.64,2.8-2.68,4.95-4.05,6.86C388.21,94.64,382,108.15,380,123.56c-3.04,23.55,11.24,44.26,34.61,49.71
c15.81,3.69,31.2,1.62,46.42-3.22c2.48-0.79,5-1.42,8.46-2.39c8.98,19.98,13.9,40.42,16.18,62.37c-3.8,0.94-6.46,1.76-9.18,2.25
c-16.65,3.01-31.7,9.36-43.86,21.42c-17.55,17.41-17.87,44.76-1.08,62.94c9.09,9.85,19.19,18.29,31.47,23.91
c1.97,0.9,3.73,2.29,6.35,3.94c-7.98,20.35-18.77,38.4-32.84,55.12c-3.06-1.75-5.24-2.79-7.18-4.15
c-11.9-8.34-24.87-13.72-39.36-15.81c-25.9-3.73-48.07,12.39-52.41,38.17c-2.51,14.96-0.26,29.24,4.49,43.36
c0.89,2.64,1.57,5.34,2.63,8.96c-20.39,9.22-41.13,13.92-63.52,15.93c-1.27-5.66-2.36-10.56-3.47-15.47
c-2.68-11.93-7.48-22.97-15.18-32.45c-19.22-23.66-48.23-25.35-70.63-3.31c-8,7.87-13.67,18.12-20.35,27.33
C170.02,464.25,168.74,466.5,167.35,468.66z M255.86,400.9c76.17,1.14,145.09-60.6,145.17-144.58
c0.07-81.43-64.18-146.3-147.02-145.43c-80.82,0.84-143.17,67.24-143.11,145.2C110.95,336.29,175.57,400.89,255.86,400.9z"/>
</g>
<g>
<path class="st2" d="M255.9,375.07c-66.32-0.01-119.05-52.79-119.18-119.01c-0.12-60.41,46.51-119.03,119.17-119.37
c66.88-0.31,119,51.98,119.5,119.66C375.87,322.28,322.28,375.08,255.9,375.07z M256.32,367.82
c61.81,0.01,112.28-50.05,111.82-111.65c-0.45-60.76-47.78-111.81-111.76-112.13c-63.11-0.31-112.37,51.07-112.41,112.06
C143.95,318.19,193.87,367.82,256.32,367.82z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_journal" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M448.42,92.12c-17.01,7.17-36.38,3.32-52.81,13.34c13.35,7.59,25.04,14.25,36.73,20.9
c-0.07,0.7-0.15,1.39-0.22,2.09c-10.32,2.08-20.63,4.16-30.95,6.23c-0.13,0.63-0.27,1.25-0.4,1.88
c14.07,8.7,28.14,17.4,42.66,26.38c-0.79,3.42-1.29,6.39-2.17,9.24c-9.51,30.75-25.84,57.54-47.17,81.49
c-28.41,31.88-43.98,69.29-47.66,111.76c-0.21,2.39-0.8,4.75-1.37,8.08c-3.69,0.38-7.21,1.06-10.74,1.07
c-52.87,0.07-105.74-0.15-158.6,0.15c-23.87,0.13-41.44,11.18-51.15,33.28c-13.04,29.65,8.96,66.89,45.53,62.06
c6.73-0.89,13.59-0.76,20.39-1.1c0.18,0.69,0.36,1.39,0.54,2.08c-1.95,1.11-3.78,2.8-5.87,3.23
c-13.93,2.87-27.83,6.21-41.92,7.89c-9.63,1.15-19.71,0.93-29.3-0.54c-25.73-3.96-39.5-20.96-46.09-44.94
c-7.68-27.98-4.86-55.9,1.11-83.65c2.48-11.54,6.41-22.77,9.52-34.19c1.48-5.44,4.92-7.99,10.38-8.84
c14.32-2.22,28.6-4.7,42.88-7.15c2.31-0.4,4.55-1.17,8.35-2.18c-12.43-12.92-23.92-24.85-35.68-37.07
c10.82-18.72,21.31-36.6,31.53-54.63c10.13-17.88,18.72-36.44,25.46-57.28c-4.1-0.52-6.79-1.1-9.48-1.17
c-19.98-0.48-39.99-0.43-59.95-1.38c-24.37-1.15-41.44-13.86-51.3-35.78c-9.41-20.93-7.08-40.88,7.01-59.34
c19.06-24.97,49.5-32.54,79.33-22.79c21.47,7.01,43.03,8.54,65.03,9.07c24.68,0.59,49.38,1.73,74.03,1.02
c37.08-1.07,74.08-3.17,111.05-7.28c35.35-3.93,63.98,16.8,71.28,52.84C448.69,88.4,448.42,90.05,448.42,92.12z M159.2,70.78
c0-1.99,0.18-2.66-0.04-3.16c-0.48-1.12-1.19-2.13-1.74-3.22c-6.25-12.36-16.75-18.76-29.81-22.21
c-18.28-4.83-36.2-6.22-53.53,3.12c-21.82,11.76-31.94,33.41-26.21,55.84c5.97,23.41,24.48,37.29,49.57,37.18
c17.77-0.08,24.02-8.04,17.19-24.49c-5.04-12.13-12.63-23.2-19.09-34.74c-1.22-2.18-2.46-4.34-4.73-8.33
C114.8,70.78,137.01,70.78,159.2,70.78z M125.86,137.58c1.23,0.84,1.72,1.47,2.22,1.47c10.98,0.11,21.98,0.38,32.94-0.05
c1.75-0.07,4.42-3.12,4.9-5.2c3.31-14.42,3.93-28.99,1.39-43.67c-1-5.82-3.9-8.4-9.91-8.3c-12.83,0.22-25.67,0.01-38.51,0.11
c-2.02,0.02-4.04,0.76-6.94,1.34C121.1,101.11,132.77,117.32,125.86,137.58z"/>
</g>
<g>
<path class="st2" d="M437.3,403.69c-12.05,6.13-24.1,12.27-36.16,18.4c0.06,0.71,0.11,1.41,0.17,2.12
c24.23,2.92,48.45,5.83,72.88,8.77c0.85,2.39,1.74,4.21,2.15,6.14c4.1,19.37-9.24,40.07-28.6,44.05
c-5.16,1.06-10.51,1.63-15.78,1.64c-68.14,0.11-136.27,0.08-204.41,0.06c-2.4,0-4.79-0.23-9.27-0.46
c10.87-12.42,17.06-25.54,17.43-40.56c0.37-14.77-2.14-29.17-10.26-43.31c3.8-0.56,6.28-1.23,8.77-1.24
c60.59-0.06,121.18-0.1,181.76,0.05c7,0.02,13.99,1.22,20.99,1.88C437.07,402.06,437.18,402.88,437.3,403.69z"/>
</g>
<g>
<path class="st2" d="M208.78,442.37c-2.84,0.3-5.59,0.73-8.35,0.86c-11.77,0.56-23.55,0.9-35.32,1.59
c-11.74,0.69-20.7-11.09-17.7-23.56c2.84-11.78,14.12-20.41,27.04-20.71C193.39,400.09,213.19,416.86,208.78,442.37z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_music" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M261.65,225.6c0.7,2.64,1.55,5.26,2.07,7.94c1.62,8.25,2.65,8.79,11.01,8.46c15-0.58,29.14,2.2,41.74,11.16
c14.6,10.37,19.64,25.5,21.71,42.14c2.78,22.32-10.19,36.76-25.52,49.9c-0.44,0.37-1.09,0.54-1.67,0.69
c-0.37,0.09-0.8-0.03-1.59-0.08c-3.15-4.92-2.8-9.59,0.96-14.33c6.14-7.74,11.54-15.89,12.05-26.24
c1.24-25.02-14.28-44.09-39.26-47.94c-4.59-0.71-9.31-0.53-15-0.81c0.44,4.72,0.51,7.73,1.03,10.66
c8.8,49.42,17.66,98.83,26.47,148.26c1.07,6.03,2.01,12.08,2.81,18.15c1.93,14.59-2.85,26.51-14.6,35.46
c-18.51,14.1-39.18,15.5-60.44,8.72c-16.02-5.1-25.76-22.74-22.74-38.34c3.49-18.02,17.24-29.36,35.42-29.2
c17.96,0.16,31.41,11.98,34.49,30.27c0.42,2.52,1.01,5.02,1.49,7.33c10.2,0.4,17.08-7.88,15.5-18.5
c-3.27-22-6.51-44.01-10.45-65.89c-5.72-31.73-12.04-63.35-18.15-95.01c-0.4-2.07-1.27-4.05-2.29-7.23
c-7.24,4.84-12.49,9.93-15.47,17.08c-5.54,13.32-3.63,26.35,1.74,39.25c1.25,3.01,1.98,6.23,2.95,9.35
c-0.69,0.48-1.39,0.96-2.08,1.44c-1.98-1.63-4.28-2.98-5.89-4.92c-14.99-18.11-14.14-48.78,1.75-66.18
c2.06-2.26,4.06-4.69,6.52-6.45c5.79-4.17,9.56-8.69,8.28-16.73c-0.43-2.71,3.11-6.04,4.83-9.09
C260.1,225.14,260.88,225.37,261.65,225.6z"/>
</g>
<g>
<path class="st2" d="M242.98,129.77c-0.54-2.18-1.24-3.66-1.24-5.15c0.06-27.65,5.24-53.97,20.63-77.55
c0.78-1.19,1.62-2.36,2.52-3.47c15.38-18.96,34.82-17.62,45.72,4.2c15.14,30.31,13.51,60.55-6.91,87.73
c-13.67,18.2-29.81,34.59-45.42,51.26c-18.14,19.38-36.83,38.27-50.39,61.34c-4.74,8.07-9.5,16.33-12.73,25.07
c-8.46,22.81-4.26,43.77,11.57,62.22c9.81,11.44,22.06,19.31,36.6,23.44c5.39,1.53,7.9,4.61,6.35,11.29
c-2.86,0-5.84,0.44-8.66-0.07c-31-5.57-50.06-25.12-60.87-53.46c-11.63-30.51-8.06-59.85,11.23-86
c15.34-20.81,32.18-40.57,49.3-59.97c15.92-18.03,33.27-34.79,49.64-52.44c11.16-12.03,12.87-27,10.85-42.48
c-1.06-8.1-5.98-13.73-14.13-16.01c-7.39-2.07-12.75,1.54-17.1,6.79c-2.57,3.1-5.27,6.57-6.35,10.32
c-3.64,12.7-7.02,25.51-9.61,38.46C252.62,122.04,249,126,242.98,129.77z"/>
</g>
</g>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><defs><radialGradient id="darkzaitzev-hooded-figure-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="darkzaitzev-hooded-figure-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="M355.102 21.097c-33.682.164-64.173 18.585-74.615 50.5 21.357-.79 23.203 53.922 23.203 53.922l41.619 6.262c-13.41 12.963-50.025 5.967-50.025 5.967-17.14 19.182-33.124 40.966-47.758 57.578-15.952 18.127-35.2 38.103-57.018 60.086-6.79 6.823 41.594-9.821 34.342-2.604-24.567 12.751-42.297 16.097-61.764 32.069-31.312 25.674-62.853 60.71-81.146 79.431-7.711 7.91-44.362 37.674 20.469 34.74 2.404 7.52-1.621 9.456-7.493 15.293-4.327 4.303-18.082.283-22.263 2.828-22.172 35.055-17.246 37.975-27.43 58.047-4.252 11.635 41.68-14.404 64.305-34.18 13.974-7.58 25.147-21.652 35.002-17.202 43.11 18.984 129.826 35.53 141.328 27.619 18.368-12.646-10.321-46.343 3.832-97.912 23.47 5.817 43.825 13.657 66.767 11.459-1.581 49.307 3.56 55.306-3.888 104.777l59.129 21.127 1.91-13.809-33.815-22.478c14.568-50.659 16.809-72.578 15.227-121.719-.16-5.372-45.168-24.325-74.492-33.133l18.593-30.412c30.393-44.788 124.141-62.055 127.932-88.258-13.02-19.676 3.022-27.384-25.092-21.912-6.295 1.318-13.771 24.346-18.023 27.213-7.843 5.276-40.655 24.477-51.951 18.377-1.9-1.026 7.246-33.441 6.85-44.78-.116-3.205-1.19-6.625-2.866-10.001.185-.64 15.24-52.482 54.809-94.016-43.978 25.134-65.332 79.925-65.354 79.98-2.207-2.134-4.476-3.983-6.639-5.423-1.916-14.7-4.819-73.02 68.598-78.776-21.427-21.177-47.704-30.78-72.283-30.66z" fill="#fff" fill-opacity="1" transform="translate(512, 0) scale(-1, 1) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -1,449 +1 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 24.1.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 512.07 512" style="enable-background:new 0 0 512.07 512;" xml:space="preserve">
<style type="text/css">
.st0{display:none;}
.st1{display:inline;}
.st2{fill:#DCDCDC;stroke:#000000;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;}
</style>
<g id="icon_x5F_sidebar_x5F_chat" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M180,480.93c14-15.25,27.95-29.3,40.56-44.47c14.18-17.05,23.54-36.69,26.34-59.05
c1.66-13.29-0.67-25.98-5.04-38.48c-1.8-5.15-5.7-5.52-10.23-5.78c-18.92-1.08-37.99-1.21-56.71-3.83
c-40-5.59-76.63-19.99-107.18-47.16c-36.18-32.19-46.99-77.73-26.93-122.29c15.37-34.14,40.96-59.17,71.93-78.94
c47.68-30.44,100.22-45.65,156.55-49.23c41.61-2.64,81.81,2.91,120.81,17.42c26.15,9.73,48.71,24.87,66.74,46.2
c29.1,34.42,32.23,80.62,8.86,120.58c-23.61,40.37-58.93,67.06-100.58,86.28c-10.17,4.7-20.81,8.38-31.3,12.36
c-4.3,1.63-6.47,4.24-6.8,9.02c-2.04,29.43-14.23,54.78-32.77,77.05c-29.18,35.06-66,59.86-107.6,77.9
C184.67,479.39,182.56,480.01,180,480.93z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_rolltable" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M255.1,55.46c6.7,2.37,12.64,3.53,17.63,6.38c47.83,27.36,95.49,55,143.19,82.58
c1.76,1.02,3.5,2.14,5.06,3.43c4.67,3.85,4.73,8.08-0.19,11.57c-4.48,3.18-9.3,5.9-14.07,8.66
c-43.81,25.34-87.68,50.58-131.43,76.01c-12.79,7.43-25.19,8.02-38.18,0.44c-47.26-27.53-94.66-54.81-141.95-82.29
c-11.67-6.78-11.5-10.86,0.17-17.61c45.93-26.57,91.78-53.27,137.82-79.64C240.07,61.03,247.84,58.57,255.1,55.46z
M256.6,177.07c8.18-2.74,15.83-4.76,23.02-7.85c6.75-2.9,11.12-8.42,11.32-16.12c0.2-7.86-4.55-13.18-10.98-16.36
c-16.34-8.07-32.92-8.99-48.94,0.93c-13.18,8.17-13.33,23.46,0.28,30.9C238.94,172.75,248.01,174.3,256.6,177.07z
M139.44,174.49c10.51,0.36,20.31-1.78,28.43-8.85c7.92-6.9,8.07-17.96,0.6-25.36c-13.09-12.97-44.39-13.07-57.62-0.19
c-8.94,8.7-8.15,19.73,2.02,27.08C120.8,172.91,129.82,174.83,139.44,174.49z M371.05,174.5c13.13,0.01,20.45-1.93,27.72-7.04
c11.22-7.88,11.04-21.8-0.38-29.44c-14.58-9.76-37.05-9.78-51.54-0.06c-11.6,7.78-11.75,21.98-0.23,29.88
C354.29,173.1,362.88,175.12,371.05,174.5z M257.2,200.1c-10.74-0.21-20.43,1.8-28.51,8.53c-9.63,8.02-9.2,19.91,0.7,27.6
c13.81,10.71,40.59,10.4,54.05-0.63c9.82-8.05,9.29-21.21-1.19-28.54C274.59,201.7,265.94,199.86,257.2,200.1z M255.77,105.95
c10.86-0.08,20.49-2.25,28.35-9.28c8.51-7.61,8.52-17.75,0.3-25.54c-13.52-12.81-43.78-12.59-57.1,0.4
c-7.45,7.27-7.44,17.61,0.19,24.78C235.62,103.93,245.78,105.61,255.77,105.95z"/>
</g>
<g>
<path class="st2" d="M73.56,270.29c-0.01-23.47-0.01-46.95,0-70.42c0-2.24-0.04-4.5,0.09-6.73c0.55-9.08,4.45-11.43,12.3-7.03
c14.77,8.29,29.43,16.78,44.1,25.25c31.29,18.06,62.49,36.27,93.87,54.16c13.59,7.75,19.9,19.03,19.84,34.61
c-0.18,47.56-0.07,95.12-0.07,142.68c0,1.02,0,2.04-0.03,3.06c-0.37,10.88-4.46,13.26-13.91,7.81
c-46.51-26.8-93.02-53.6-139.43-80.56c-11.08-6.44-16.76-16.38-16.77-29.35C73.56,319.28,73.57,294.79,73.56,270.29z
M238.89,301.12c-1.04-15.22-9.94-29.1-25.87-37.67c-12.78-6.88-25.53,0.97-25.17,15.07c0.45,18,8.76,32.2,24.15,41.47
C226.27,328.58,238.87,320.93,238.89,301.12z M238.88,424.25c-0.03-14.84-11.77-33.85-24.91-40.35
c-13.82-6.83-27.24,1.36-26.24,16.4c1.14,17.22,9.44,30.68,24.03,39.63C226.22,448.8,238.92,441.17,238.88,424.25z
M78.36,336.56c-0.07,16.35,12.18,35.46,26.64,41.57c13.6,5.74,24.53-1.52,24.14-16.28c-0.47-17.75-9.44-30.82-23.63-40.54
c-5.85-4.01-12.62-5.05-19.12-1.43C80,323.43,78.2,329.62,78.36,336.56z M78.16,216.83c1.81,17.43,9.33,31.66,25.03,40.21
c13.84,7.55,26.4-0.25,25.96-15.46c-0.51-17.56-9.43-30.51-23.26-40.31c-5.78-4.1-12.64-5.27-19.16-1.76
C80.09,203.09,78.12,209.49,78.16,216.83z"/>
</g>
<g>
<path class="st2" d="M438.48,269.36c0,23.88-0.09,47.77,0.04,71.65c0.08,14.95-5.66,26.05-19.04,33.69
c-45.56,26.01-90.87,52.43-136.3,78.66c-1.93,1.11-4.02,2.03-6.14,2.72c-4.13,1.36-6.9-0.45-7.9-4.42
c-0.69-2.73-0.78-5.65-0.78-8.49c-0.04-48.18,0.04-96.35-0.07-144.53c-0.03-14.73,6.49-25.32,19.04-32.56
c44.18-25.53,88.36-51.07,132.54-76.6c1.24-0.71,2.5-1.39,3.75-2.08c11.32-6.2,14.8-4.14,14.84,9.08
C438.53,220.78,438.48,245.07,438.48,269.36z M273.14,421.22c0.05,19.9,12.39,27.34,26.79,18.9
c14.92-8.75,23.03-22.32,24.24-39.46c1.09-15.44-12.22-24.3-25.6-16.81C282.99,392.57,274.73,406.59,273.14,421.22z
M273.19,300.58c-0.25,19.57,10.43,26.62,25.43,19.95c14.02-6.23,26.59-26.94,25.75-42.41c-0.77-14.26-13.04-21.55-25.73-14.51
C283.1,272.22,275.12,286.19,273.19,300.58z M378.55,373.28c0.05-21.14-11.77-28.95-25.77-20.61
c-15.26,9.09-24.61,22.51-24.5,41.07c0.1,15.52,11.79,22.77,25.39,15.25C369.25,400.38,377.63,386.78,378.55,373.28z
M433.65,340.47c0.1-20.18-12.26-27.99-26.62-19.24c-14.51,8.85-23.33,22.09-24,39.66c-0.62,16.14,11.34,23.92,25.59,16.37
C424.57,368.82,431.83,354.54,433.65,340.47z M378.56,249.19c0.11-16.72-10.87-24.46-24.88-17.53
c-15.12,7.48-26.59,27.54-25.35,44.37c0.88,11.94,10.06,18.07,21.51,14.37C365.3,285.38,378.44,266.54,378.56,249.19z
M433.67,217.08c0.11-15.23-9.9-22.9-23.27-17.86c-16.2,6.12-29.92,29.74-27.12,46.71c1.73,10.53,10.4,15.95,20.67,12.93
C419.6,254.24,433.54,234.65,433.67,217.08z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_actor" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M194.72,240.85c-18.71-10.84-37.43-21.65-56.1-32.56c-4.38-2.56-3.72-6.78-3.09-10.93
c4.53-29.87,16.49-56.68,33.54-81.37c22.53-32.64,51.22-59.09,83.04-82.38c1.94-1.42,4.08-2.55,6.44-4.01
c2.95,1.91,5.76,3.52,8.35,5.44c34.2,25.36,64.61,54.39,87.21,90.87c13.92,22.47,23.34,46.63,27.11,72.93
c0.74,5.19-0.6,8.42-5.19,11.05c-17.12,9.83-34.08,19.93-51.1,29.92c-0.35-0.42-0.7-0.84-1.06-1.26
c7.2-7.59,13.9-15.74,21.74-22.61c6.97-6.11,8.08-12.73,6.54-21.27c-5.03-27.96-18.41-51.68-36.13-73.32
c-14.99-18.3-32.86-33.43-51.91-47.27c-3.26-2.37-6.29-3.56-10-0.89c-28.94,20.8-54.74,44.63-72.73,75.88
c-9.25,16.07-15.58,33.21-17.65,51.81c-0.5,4.49,0.65,7.78,3.76,10.99c9.23,9.52,18.23,19.25,27.32,28.9L194.72,240.85z"/>
</g>
<g>
<path class="st2" d="M168.55,345.65c-12.76,3.01-23.81-2.22-35.94-5.83c-3.63,12.02-1.15,22.71,4.28,33.16
c-0.52,0.49-1.04,0.98-1.56,1.47c-7.28-3.95-14.57-7.89-22.66-12.28c-0.94,40.71,5.85,79.96,12.76,120.22
c-9.73,0-18.21,0-28.31,0c0-4.71-0.17-8.65,0.03-12.57c2.77-54.5,0.73-108.5-16.69-160.88c-1.7-5.12-1.02-8.86,2.98-12.56
c15.25-14.13,30.3-28.49,45.51-42.67c1.86-1.73,4.21-2.92,7.2-4.95c12.66,31.79,36.38,51.55,65.92,65.71
c-23.56,4.18-43.99-5.23-64.98-14.12C142.45,319.03,153.45,333.5,168.55,345.65z"/>
</g>
<g>
<path class="st2" d="M378.56,342.15c-11.2,1.29-21.2,6.91-34.38,4.02c17.38-13.12,29.62-28.02,35.34-49.86
c-22.86,11.18-44.29,22.27-69.86,17.87c29.22-14.58,53.47-34,65.19-66.51c3.09,2.11,5.44,3.31,7.29,5.04
c15.49,14.48,30.83,29.13,46.36,43.57c3.94,3.66,4.92,7.36,3.13,12.52c-12.8,37.05-17.33,75.43-17.57,114.4
c-0.11,17.53,0.54,35.07,0.78,52.6c0.02,1.77-0.35,3.55-0.66,6.4c-8.97,0-17.6,0-27.36,0c6.32-39.97,13.54-79.18,12.38-120.61
c-8.84,4.81-16.27,8.85-23.71,12.89c-0.49-0.48-0.97-0.96-1.46-1.44C378.33,363.41,381.6,353.68,378.56,342.15z"/>
</g>
<g>
<path class="st2" d="M207.81,179.57c3.71-5.83,8.78-8.93,15.2-8.75c5.91,0.17,10.65,3.14,13.82,8.68
c-3.37,5.93-8.7,7.74-14.45,7.81C216.53,187.39,211.48,185.04,207.81,179.57z"/>
</g>
<g>
<path class="st2" d="M277.66,179.72c3.23-6.12,7.85-9.04,14-9c6.15,0.04,10.67,3.08,13.58,8.58c-2.43,6.15-7.58,7.55-12.87,7.82
C286.5,187.42,281.29,185.46,277.66,179.72z"/>
</g>
<g>
<path class="st2" d="M194.81,240.77c0,0-0.08,0.08-0.08,0.08C194.72,240.85,194.81,240.77,194.81,240.77z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_scene">
<g>
<g>
<g>
<path class="st2" d="M141.31,362.45c10.55-10.81,21.11-21.61,32.39-33.17c-4.23-4.4-7.78-8.52-11.78-12.13
c-4.39-3.96-5.23-7.87-1.64-12.78c2.36-3.24,4.31-6.78,7.52-11.92c29.68,29.65,58.51,58.45,88.28,88.2
c29.63-29.58,58.38-58.28,88.43-88.27c3.76,6.48,7.17,11.44,9.48,16.88c0.68,1.6-1.26,4.92-2.82,6.75
c-3.78,4.43-8.04,8.45-12.61,13.15c3.87,4.06,7.01,7.46,10.26,10.75c6.02,6.1,12.2,12.04,18.09,18.27
c1.5,1.58,2.14,3.98,2.19,6.78c-11.12-2.35-15.32-13.36-25.7-18.87c-4.53,5.37-9.27,11-14.4,17.08
c4.03,8.46,15.77,12.55,18.84,22.89c-0.64,0.7-1.28,1.4-1.92,2.1c-2.18-1.32-4.7-2.29-6.49-4.01
c-7.5-7.21-14.75-14.68-22.17-21.99c-1.69-1.67-3.67-3.05-6.41-5.3c-5.41,5.88-10.51,11.42-16,17.4
c1.57,1.94,2.93,3.92,4.6,5.61c7.3,7.42,14.75,14.69,22,22.16c1.66,1.71,2.69,4.01,3.13,6.87
c-10.84-2.35-15.01-13.32-25.2-18.68c-4.93,5.38-10.02,10.94-15.43,16.85c4.67,9.02,15.38,13.49,19.26,23.07
c-0.54,0.67-1.09,1.34-1.63,2.01c-2.14-1.31-4.59-2.29-6.35-3.98c-7.49-7.22-14.75-14.69-22.17-21.99
c-1.69-1.66-3.68-3.01-5.89-4.79c-3.8,3-7.23,5.71-11.03,8.71c-3.77-2.97-7.19-5.68-11.01-8.69c-2.19,1.75-4.19,3.08-5.87,4.74
c-7.42,7.3-14.69,14.75-22.16,22c-1.73,1.67-4.02,2.76-6.91,3.23c2.31-10.77,13.12-15.02,18.63-25.24
c-5.42-4.76-11.09-9.74-17.21-15.11c-8.81,4.1-12.9,15.32-22.79,18.83c-0.62-0.47-1.25-0.95-1.87-1.42
c1.25-2.13,2.15-4.6,3.81-6.33c7.21-7.5,14.68-14.75,21.99-22.17c1.67-1.7,3.05-3.67,5.27-6.37
c-5.69-5.59-11.06-10.87-16.79-16.51c-2.48,2-4.47,3.36-6.16,5.02c-7.42,7.3-14.69,14.75-22.16,22c-1.71,1.66-4,2.72-6.87,3.19
c2.16-10.9,13.44-14.89,18.41-25.47c-5.23-4.81-10.76-9.89-16.39-15.06c-9.69,4.24-13.75,16.43-24.15,19.15
C143.03,364.74,142.17,363.6,141.31,362.45z"/>
</g>
<g>
<path class="st2" d="M441,403.48c-16.69-27.59-33.44-55.13-50.04-82.77c-42.46-70.68-84.85-141.39-127.26-212.1
c-1.34-2.23-2.47-4.58-4.3-8.02c13.34-3.15,24.63-8.77,32.97-20.46c1.71,2.53,2.89,3.85,3.6,5.4
c28.28,61.55,56.51,123.12,84.77,184.68c19.15,41.72,38.37,83.41,57.51,125.14c1.18,2.58,1.92,5.36,2.86,8.04L441,403.48z"/>
</g>
<g>
<path class="st2" d="M217.61,82.38c2.39,3.13,3.85,4.73,4.95,6.53c4.59,7.48,8.69,15.3,13.71,22.47
c4.35,6.21,4.12,11.18,0.16,17.73c-47.28,78.28-94.26,156.74-141.31,235.16c-6.51,10.85-13.01,21.71-19.54,32.55
c-1.13,1.88-2.39,3.68-4.72,4.92C119.57,295.76,168.27,189.77,217.61,82.38z"/>
</g>
<g>
<path class="st2" d="M477.25,255.92c-10.87-10.64-21.54-21.09-32.91-32.23c-5.58,5.75-10.68,11.01-16.24,16.75
c1.84,2.26,3.31,4.39,5.1,6.21c7.43,7.56,15,15,22.43,22.56c2.12,2.16,4.52,4.52-0.17,8.58c-7.22-6.76-14.48-13.55-21.88-20.47
c-6.08,5.51-11.66,10.57-17.97,16.3c7.88,8.42,14.65,15.65,21.42,22.88c-0.62,0.85-1.25,1.7-1.87,2.56
c-2.14-1.03-4.53-1.72-6.36-3.13c-13.8-10.59-21.18-25.52-27.46-41.16c-5.78-14.38-8.33-11.03,4.45-23.75
c7.23-7.19,14.4-14.44,21.65-21.61c1.71-1.69,3.62-3.17,5.84-5.08c1.73,1.12,3.41,1.86,4.63,3.06
c13.32,13.21,26.59,26.48,39.81,39.79C479.85,249.34,482.22,251.73,477.25,255.92z"/>
</g>
<g>
<path class="st2" d="M68.55,223.56c-12.92,10.59-22.16,23.11-34.32,32.22c-0.78-0.53-1.57-1.06-2.35-1.59
c0.43-1.85,0.25-4.3,1.39-5.46c14.33-14.51,28.84-28.83,43.34-43.18c0.39-0.38,1.12-0.42,1.97-0.71
c0.75,0.34,1.86,0.54,2.53,1.2c10.88,10.75,21.84,21.43,32.39,32.51c1.47,1.54,1.83,5.55,0.94,7.69
c-4.29,10.36-8.17,21.11-14.15,30.47c-5.16,8.08-12.9,14.53-19.62,21.58c-0.65,0.69-2.18,0.54-5.2,1.2
c3.65-11.71,15.03-15.79,20.22-26.77c-5.23-4.62-10.83-9.57-16.64-14.7c-9.41,4.67-13.78,15.49-23.35,19.4
c-0.67-0.54-1.35-1.07-2.02-1.61c1.11-1.99,1.87-4.32,3.4-5.91c7.07-7.35,14.38-14.47,21.55-21.72c1.84-1.86,3.48-3.92,6.4-7.23
C79.61,235.25,74.35,229.69,68.55,223.56z"/>
</g>
<g>
<path class="st2" d="M256.05,428.1c7.93,7.53,16.37,15.55,24.7,23.47c-8.21,8.27-16.4,16.51-24.37,24.54
c-8.23-7.98-16.67-16.16-25.11-24.34C239.8,443.62,248.21,435.58,256.05,428.1z"/>
</g>
<g>
<path class="st2" d="M254.88,73.27c6.48-5.93,12.68-11.6,18.52-16.94C275.4,65.47,265.2,75.93,254.88,73.27z"/>
</g>
<g>
<path class="st2" d="M238.87,49.47c0.54-7.99,6.12-13.62,15.88-13.57c-4.81,4.98-9.61,9.96-14.42,14.93
C239.84,50.38,239.35,49.92,238.87,49.47z"/>
</g>
<g>
<polygon class="st2" points="441.11,403.38 441.22,403.67 441,403.48 "/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_item" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M86.57,379.95c0-48.58,0-96.33,0-143.79c5.64-2.82,112.01-3.19,119.52-0.33c0.25,2.68,0.79,5.83,0.8,8.98
c0.07,26.94,0.01,53.88,0.08,80.83c0.01,3.17,0.51,6.33,0.85,10.3c32.36,0,63.92,0,97.01,0c0-33.87,0-66.95,0-99.19
c6.41-3.36,112.58-3.86,119.48-1.35c2.55,5.28,2.8,137.43-0.09,144.56C312.19,379.95,199.8,379.95,86.57,379.95z"/>
</g>
<g>
<path class="st2" d="M351.95,96.52c0,37.52,0,74.24,0,111.87c-15.41,0-30.07,0-45.61,0c-0.81-5.04-1.56-9.72-2.59-16.15
c-31.78-0.12-63.35-0.24-95.41,0.16c-1.01,5.85-1.81,10.52-2.76,16c-15.49,0-30.54,0-46.27,0c-0.48-3.17-1.18-5.7-1.19-8.24
c-0.08-31.43-0.09-62.85-0.03-94.28c0.02-8.73,1.64-10.33,10.48-10.33c58.36-0.05,116.72-0.03,175.09,0.01
C346.04,95.56,348.42,96.09,351.95,96.52z"/>
</g>
<g>
<path class="st2" d="M132.51,208.42c-9.52,0-18.03,0-27.47,0c0-37.52,0-74.16,0-111.86c9.22,0,17.87,0,27.47,0
C132.51,133.9,132.51,170.54,132.51,208.42z"/>
</g>
<g>
<path class="st2" d="M378.57,96.39c10.31,0,18.82,0,29.12,0c0.27,37.43,0.14,74.07,0.08,111.82c-10.01,0-18.66,0-29.13,0
C378.39,170.99,378.51,134.35,378.57,96.39z"/>
</g>
<g>
<path class="st2" d="M107.03,407.31c99.7,0,198.42,0,297.14,0c0.31,0.74,0.62,1.47,0.93,2.21c-3.8,2.18-7.48,4.61-11.44,6.42
c-1.72,0.78-4.02,0.36-6.06,0.36c-87.72,0.01-175.44-0.01-263.17,0.06C117.35,416.37,111.13,415.25,107.03,407.31z"/>
</g>
<g>
<path class="st2" d="M280.03,311.38c-16.62,0-31.68,0-47.61,0c0-31.35,0-61.94,0-93.7c15.6-1.68,30.82-0.85,47.53-0.45
C280.76,248.97,280.56,279.53,280.03,311.38z M267.36,293.14c0.39-3.77,0.85-6.35,0.89-8.94c0.12-7.13-0.2-14.28,0.21-21.39
c0.17-2.85,1.14-6.13,2.88-8.31c8.15-10.27,8.56-19.5,0.67-27.25c-8.45-8.3-21.51-8.87-30.61-1.33
c-8.41,6.98-10.24,17.21-3.09,25.35c4.73,5.38,5.6,10.91,5.4,17.36c-0.17,5.7-0.14,11.42,0.05,17.12
c0.08,2.32,0.82,4.63,1.34,7.39C252.64,293.14,259.56,293.14,267.36,293.14z"/>
</g>
<g>
<path class="st2" d="M459.64,208.46c-9.05,0-17.17,0-26.05,0c-0.44-3.46-1.09-6.2-1.09-8.93c-0.07-31.16-0.05-62.33-0.04-93.49
c0-1.22,0.07-2.44,0.15-3.66c0.3-4.41,2.7-6.57,7.1-6.7c4.5-0.13,6.66,2.09,7.24,6.46c4.34,32.91,8.76,65.81,13.07,98.73
C460.3,202.98,459.83,205.2,459.64,208.46z"/>
</g>
<g>
<path class="st2" d="M77.56,97.23c0,36.74,0,73.41,0,111.08c-8.48,0-16.35,0-25.02,0c-0.25-2.71-0.9-5.08-0.6-7.34
c4.21-32.52,8.49-65.04,12.9-97.53C65.84,96.02,68.83,94.5,77.56,97.23z"/>
</g>
<g>
<path class="st2" d="M451.71,362.72c0-42.84,0-84.74,0-127.72c3.45-0.21,6.42-0.39,10.08-0.61c0.46,3.5,1.09,6.04,1.1,8.58
c0.06,34.46-0.08,68.92,0.12,103.38C463.06,354.24,458.99,358.62,451.71,362.72z"/>
</g>
<g>
<path class="st2" d="M50.26,234.87c2.86,0,5.32,0,7.56,0c2.47,5.02,3.24,118.46,0.9,126.79c-5.37-3.13-9.67-6.58-9.66-13.41
c0.02-35.65-0.01-71.31,0.05-106.96C49.12,239.34,49.79,237.4,50.26,234.87z"/>
</g>
<g>
<path class="st2" d="M51.56,390.71c7.99,7.72,15.99,15.44,25.01,24.15c-9.12,2.16-16.82,2.02-24.49,0.42
c-1.03-0.21-2.41-2.03-2.45-3.14c-0.23-6.78-0.11-13.57-0.11-20.36C50.2,391.43,50.88,391.07,51.56,390.71z"/>
</g>
<g>
<path class="st2" d="M436.46,413.79c8.05-7.65,16.1-15.3,24.15-22.95c0.61,0.34,1.23,0.69,1.84,1.03
c0,6.76,0.19,13.52-0.17,20.26c-0.07,1.29-2.24,3.46-3.53,3.53c-7.16,0.35-14.35,0.17-21.53,0.17
C436.96,415.15,436.71,414.47,436.46,413.79z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_fight" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M98.54,121.71c7.19,0.33,14.38,0.67,22.81,1.06c1.18-7.93,2.28-15.34,3.38-22.75
c0.65-0.23,1.3-0.46,1.95-0.69c70.17,84.04,140.34,168.07,211.57,253.38c-9.84,8.24-18.85,15.78-28.82,24.13
C238.18,291.6,167.84,207.47,97.5,123.34C97.85,122.8,98.2,122.26,98.54,121.71z"/>
</g>
<g>
<path class="st2" d="M74.25,462.04c-10.75-7.58-20.15-14.21-30.69-21.64C87.39,378.65,130.68,317.64,175,255.19
c8.95,10.7,16.69,19.95,24.95,29.82C158.02,344.06,116.54,402.48,74.25,462.04z"/>
</g>
<g>
<path class="st2" d="M425.22,103.01c0.37,2.17,1.08,4.12,0.96,6.02c-1.52,23.89-10.41,44.55-26.71,62.21
c-17.85,19.34-40.04,31.93-63.81,42.21c-1.98,0.86-4.11,1.36-7.64,2.49c1.24-4.12,1.91-6.97,2.94-9.69
c6.52-17.26,11.93-34.75,11.33-53.5c-0.09-2.84-0.01-5.86-0.93-8.47c-2.37-6.7,0.06-11.13,5.24-15.36
c8.52-6.96,16.52-14.54,24.94-21.63c1.91-1.61,4.59-3.05,6.99-3.2c14.23-0.85,28.48-1.32,42.72-1.86
C422.24,102.2,423.23,102.61,425.22,103.01z"/>
</g>
<g>
<path class="st2" d="M291.85,453.14c-4.87-5.91-8.93-10.84-14.08-17.09c41.71-34.89,82.71-69.18,124.58-104.2
c4.79,5.78,8.96,10.8,14.01,16.89C374.53,383.82,333.55,418.17,291.85,453.14z"/>
</g>
<g>
<path class="st2" d="M273.79,115.61c10.76,7.57,20.25,14.24,30.73,21.61c-17.52,24.77-34.23,48.41-51.86,73.34
c-8.76-10.27-16.69-19.55-25.21-29.54C242.84,159.29,257.83,138.14,273.79,115.61z"/>
</g>
<g>
<path class="st2" d="M310.02,250.99c3.13-1.7,6.08-3.97,9.41-5.02c21.89-6.92,42.92-15.68,62.36-28.02
c29.04-18.43,51.93-42.06,63.17-75.38c4.67-13.85,6.52-28.16,6.18-42.77c-0.05-2.01-0.01-4.02-0.01-6.78
c3.9-2.17,7.86-4.37,12.69-7.05c1.31,3.33,2.56,5.61,3.12,8.05c3.1,13.52,1.31,26.78-2.57,39.85
c-16.18,54.48-81.45,113.08-140.32,120.1c-4.27,0.51-8.65,0.07-12.98,0.07C310.71,253.03,310.37,252.01,310.02,250.99z"/>
</g>
<g>
<path class="st2" d="M389.79,472.78c-11.28-13.51-21.9-26.23-33.01-39.54c8.13-9.93,17.68-16.81,28.3-24.44
c11.08,13.21,21.71,25.89,33.02,39.37C409.83,457.64,400.05,464.37,389.79,472.78z"/>
</g>
<g>
<path class="st2" d="M321.15,118.13c-11.98-8.39-23.18-16.22-35.16-24.61c4.46-12.23,8.63-23.66,13.37-36.67
c17.45,12.36,33.25,23.54,50.46,35.73C339.82,101.49,330.87,109.47,321.15,118.13z"/>
</g>
<g>
<path class="st2" d="M98.58,95.77c-7.12-0.81-13.28-1.35-19.35-2.36c-1.23-0.2-2.8-2.02-3.15-3.37
c-2.23-8.67-4.18-17.41-6.14-26.14c-0.15-0.68,0.35-1.51,0.74-2.98c1.89,0.47,3.64,0.68,5.2,1.33
c6.2,2.59,12.29,5.47,18.53,7.94c4.9,1.94,7.04,5.25,6.33,10.43C100.13,85.01,99.49,89.39,98.58,95.77z"/>
</g>
<g>
<path class="st2" d="M263.6,72.75c-4.58-8.72-9.17-17.44-14.34-27.29c9.64-1.5,17.2,0.6,26.32,3.04
c-3.26,8.72-6.26,16.73-9.26,24.75C265.41,73.08,264.5,72.92,263.6,72.75z"/>
</g>
<g>
<path class="st2" d="M328.1,39.22c10.42,7.7,21.69,12.69,29.96,23.17C349.73,64.21,326.41,46.59,328.1,39.22z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_compendium" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M172.73,49.37c21.98,0,43.98,0,66.87,0c0,137.52,0,274.28,0,412.73c-22.56,0.64-44.71,0.55-66.23,0.05
C170.22,455.66,169.78,57.56,172.73,49.37z M200.52,429.88c3.18-7.29,2.79-312.57-0.29-318.12c-6.66,0-13.58,0-20.13,0
c-3.18,7.31-2.79,312.56,0.29,318.12C187.06,429.88,193.98,429.88,200.52,429.88z M210.72,299.22
c-3.15,7.38-2.74,125.16,0.33,130.65c6.67,0,13.59,0,21.35,0c0-43.84,0-86.81,0-130.65
C224.64,299.22,217.72,299.22,210.72,299.22z"/>
</g>
<g>
<path class="st2" d="M145.38,142.76c0,85.62,0,170.31,0,256.67c-17.42,1.03-34.25,0.66-51.8,0.12
c-0.49-3.88-1.14-6.62-1.14-9.36c-0.05-79.17-0.06-158.34-0.03-237.52c0-9.54,1.47-10.94,11.07-11
c11.02-0.07,22.04-0.07,33.06,0.03C139.11,141.74,141.67,142.3,145.38,142.76z"/>
</g>
<g>
<path class="st2" d="M363.52,456.03c-12.7,2.35-23.74,4.39-35.68,6.6c-1.26-4.11-2.57-7.24-3.16-10.5
c-10.85-60.07-21.6-120.15-32.38-180.23c-7.75-43.2-15.53-86.4-23.26-129.6c-0.49-2.72-0.59-5.51-1-9.55
c12.13-2.2,23.57-4.27,36.31-6.58C324.11,236.33,343.65,345.24,363.52,456.03z"/>
</g>
<g>
<path class="st2" d="M30.77,95.93c12.29,0,23.52,0,35.63,0c0.49,3.12,1.29,5.83,1.29,8.53c0.07,53.47,0.07,106.95,0.02,160.42
c0,2.37-0.57,4.75-0.98,8c-11.97,0-23.53,0-35.96,0C30.77,213.88,30.77,155.54,30.77,95.93z"/>
</g>
<g>
<path class="st2" d="M367.58,238.23c7-3.03,12.81-5.54,20.08-8.69c31.66,74.22,62.88,147.39,94.52,221.55
c-7.17,3.14-12.98,5.68-20.06,8.77C430.48,385.69,399.26,312.48,367.58,238.23z"/>
</g>
<g>
<path class="st2" d="M65.98,461.62c-11.43,0-22.81,0-35.96,0c-0.23-38.48-0.1-76.1-0.08-114.56c13.02,0,24.42,0,35.56,0
C68.27,352.44,68.8,453.4,65.98,461.62z"/>
</g>
<g>
<path class="st2" d="M145.31,461.62c-17.64,0-34.34,0-51.98,0c0-12.22,0-23.59,0-34.65c5.83-2.99,44.82-3.3,51.98-0.36
C145.31,437.66,145.31,449.07,145.31,461.62z"/>
</g>
<g>
<path class="st2" d="M66.94,299.04c0,7.68,0,14,0,20c-5.68,3.23-28.48,3.6-36.48,0.32c0-5.15-0.23-10.92,0.17-16.64
c0.09-1.3,2.32-3.48,3.61-3.52C44.72,298.91,55.21,299.04,66.94,299.04z"/>
</g>
<g>
<path class="st2" d="M344.77,183.51c1.37-6.24,13.25-11.41,18.86-8.56C361.93,179.91,351.56,184.78,344.77,183.51z"/>
</g>
<g>
<path class="st2" d="M376.69,203.79c-1.47,1.58-2.66,3.99-4.46,4.57c-4.85,1.58-9.26,6.71-16.33,2.77
c5.69-6.11,12.27-7.7,18.8-9.41C375.37,202.41,376.03,203.1,376.69,203.79z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_settings" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M167.35,468.66c-13.39-1.77-50.61-24-55.69-33.14c1.08-1.73,2.27-3.8,3.62-5.75
c9.08-13.11,15.46-27.19,17.17-43.32c2.08-19.66-8.6-38.21-26.93-45.65c-18.45-7.49-36.8-5.28-55.13,0.52
c-2.27,0.72-4.61,1.24-7.95,2.13c-8.74-20.07-13.97-40.42-16.04-62.21c3.72-1,6.27-1.51,8.71-2.36
c10.15-3.55,20.93-5.98,30.28-11.03c32.02-17.29,37.2-51.45,11.57-77.58c-7.69-7.84-18.02-13.11-27.21-19.46
c-1.8-1.24-3.88-2.08-6.88-3.65c7.46-20.81,19.04-38.63,32.65-56.07c2.6,1.58,4.49,2.63,6.28,3.83
c12.84,8.66,26.44,15.16,42.16,16.87c27.62,3.01,49.81-16.05,50.75-43.89c0.44-12.98-0.7-25.69-5.26-37.95
c-0.57-1.52-0.94-3.13-1.27-4.72c-0.16-0.77-0.03-1.6-0.03-3.56c19.48-9.06,40.19-13.46,62.14-15.74
c1.02,3.75,1.82,6.21,2.34,8.72c3.47,16.64,9.06,32.26,21.51,44.52c15.73,15.49,38.24,17.59,56.71,5.52
c12.09-7.9,21.07-18.51,27.72-31.22c1.77-3.4,3.56-6.79,5.82-11.11c21.09,7.8,39.67,18.42,56.8,32.93
c-1.64,2.8-2.68,4.95-4.05,6.86C388.21,94.64,382,108.15,380,123.56c-3.04,23.55,11.24,44.26,34.61,49.71
c15.81,3.69,31.2,1.62,46.42-3.22c2.48-0.79,5-1.42,8.46-2.39c8.98,19.98,13.9,40.42,16.18,62.37c-3.8,0.94-6.46,1.76-9.18,2.25
c-16.65,3.01-31.7,9.36-43.86,21.42c-17.55,17.41-17.87,44.76-1.08,62.94c9.09,9.85,19.19,18.29,31.47,23.91
c1.97,0.9,3.73,2.29,6.35,3.94c-7.98,20.35-18.77,38.4-32.84,55.12c-3.06-1.75-5.24-2.79-7.18-4.15
c-11.9-8.34-24.87-13.72-39.36-15.81c-25.9-3.73-48.07,12.39-52.41,38.17c-2.51,14.96-0.26,29.24,4.49,43.36
c0.89,2.64,1.57,5.34,2.63,8.96c-20.39,9.22-41.13,13.92-63.52,15.93c-1.27-5.66-2.36-10.56-3.47-15.47
c-2.68-11.93-7.48-22.97-15.18-32.45c-19.22-23.66-48.23-25.35-70.63-3.31c-8,7.87-13.67,18.12-20.35,27.33
C170.02,464.25,168.74,466.5,167.35,468.66z M255.86,400.9c76.17,1.14,145.09-60.6,145.17-144.58
c0.07-81.43-64.18-146.3-147.02-145.43c-80.82,0.84-143.17,67.24-143.11,145.2C110.95,336.29,175.57,400.89,255.86,400.9z"/>
</g>
<g>
<path class="st2" d="M255.9,375.07c-66.32-0.01-119.05-52.79-119.18-119.01c-0.12-60.41,46.51-119.03,119.17-119.37
c66.88-0.31,119,51.98,119.5,119.66C375.87,322.28,322.28,375.08,255.9,375.07z M256.32,367.82
c61.81,0.01,112.28-50.05,111.82-111.65c-0.45-60.76-47.78-111.81-111.76-112.13c-63.11-0.31-112.37,51.07-112.41,112.06
C143.95,318.19,193.87,367.82,256.32,367.82z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_journal" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M448.42,92.12c-17.01,7.17-36.38,3.32-52.81,13.34c13.35,7.59,25.04,14.25,36.73,20.9
c-0.07,0.7-0.15,1.39-0.22,2.09c-10.32,2.08-20.63,4.16-30.95,6.23c-0.13,0.63-0.27,1.25-0.4,1.88
c14.07,8.7,28.14,17.4,42.66,26.38c-0.79,3.42-1.29,6.39-2.17,9.24c-9.51,30.75-25.84,57.54-47.17,81.49
c-28.41,31.88-43.98,69.29-47.66,111.76c-0.21,2.39-0.8,4.75-1.37,8.08c-3.69,0.38-7.21,1.06-10.74,1.07
c-52.87,0.07-105.74-0.15-158.6,0.15c-23.87,0.13-41.44,11.18-51.15,33.28c-13.04,29.65,8.96,66.89,45.53,62.06
c6.73-0.89,13.59-0.76,20.39-1.1c0.18,0.69,0.36,1.39,0.54,2.08c-1.95,1.11-3.78,2.8-5.87,3.23
c-13.93,2.87-27.83,6.21-41.92,7.89c-9.63,1.15-19.71,0.93-29.3-0.54c-25.73-3.96-39.5-20.96-46.09-44.94
c-7.68-27.98-4.86-55.9,1.11-83.65c2.48-11.54,6.41-22.77,9.52-34.19c1.48-5.44,4.92-7.99,10.38-8.84
c14.32-2.22,28.6-4.7,42.88-7.15c2.31-0.4,4.55-1.17,8.35-2.18c-12.43-12.92-23.92-24.85-35.68-37.07
c10.82-18.72,21.31-36.6,31.53-54.63c10.13-17.88,18.72-36.44,25.46-57.28c-4.1-0.52-6.79-1.1-9.48-1.17
c-19.98-0.48-39.99-0.43-59.95-1.38c-24.37-1.15-41.44-13.86-51.3-35.78c-9.41-20.93-7.08-40.88,7.01-59.34
c19.06-24.97,49.5-32.54,79.33-22.79c21.47,7.01,43.03,8.54,65.03,9.07c24.68,0.59,49.38,1.73,74.03,1.02
c37.08-1.07,74.08-3.17,111.05-7.28c35.35-3.93,63.98,16.8,71.28,52.84C448.69,88.4,448.42,90.05,448.42,92.12z M159.2,70.78
c0-1.99,0.18-2.66-0.04-3.16c-0.48-1.12-1.19-2.13-1.74-3.22c-6.25-12.36-16.75-18.76-29.81-22.21
c-18.28-4.83-36.2-6.22-53.53,3.12c-21.82,11.76-31.94,33.41-26.21,55.84c5.97,23.41,24.48,37.29,49.57,37.18
c17.77-0.08,24.02-8.04,17.19-24.49c-5.04-12.13-12.63-23.2-19.09-34.74c-1.22-2.18-2.46-4.34-4.73-8.33
C114.8,70.78,137.01,70.78,159.2,70.78z M125.86,137.58c1.23,0.84,1.72,1.47,2.22,1.47c10.98,0.11,21.98,0.38,32.94-0.05
c1.75-0.07,4.42-3.12,4.9-5.2c3.31-14.42,3.93-28.99,1.39-43.67c-1-5.82-3.9-8.4-9.91-8.3c-12.83,0.22-25.67,0.01-38.51,0.11
c-2.02,0.02-4.04,0.76-6.94,1.34C121.1,101.11,132.77,117.32,125.86,137.58z"/>
</g>
<g>
<path class="st2" d="M437.3,403.69c-12.05,6.13-24.1,12.27-36.16,18.4c0.06,0.71,0.11,1.41,0.17,2.12
c24.23,2.92,48.45,5.83,72.88,8.77c0.85,2.39,1.74,4.21,2.15,6.14c4.1,19.37-9.24,40.07-28.6,44.05
c-5.16,1.06-10.51,1.63-15.78,1.64c-68.14,0.11-136.27,0.08-204.41,0.06c-2.4,0-4.79-0.23-9.27-0.46
c10.87-12.42,17.06-25.54,17.43-40.56c0.37-14.77-2.14-29.17-10.26-43.31c3.8-0.56,6.28-1.23,8.77-1.24
c60.59-0.06,121.18-0.1,181.76,0.05c7,0.02,13.99,1.22,20.99,1.88C437.07,402.06,437.18,402.88,437.3,403.69z"/>
</g>
<g>
<path class="st2" d="M208.78,442.37c-2.84,0.3-5.59,0.73-8.35,0.86c-11.77,0.56-23.55,0.9-35.32,1.59
c-11.74,0.69-20.7-11.09-17.7-23.56c2.84-11.78,14.12-20.41,27.04-20.71C193.39,400.09,213.19,416.86,208.78,442.37z"/>
</g>
</g>
</g>
</g>
<g id="icon_x5F_sidebar_x5F_music" class="st0">
<g class="st1">
<g>
<g>
<path class="st2" d="M261.65,225.6c0.7,2.64,1.55,5.26,2.07,7.94c1.62,8.25,2.65,8.79,11.01,8.46c15-0.58,29.14,2.2,41.74,11.16
c14.6,10.37,19.64,25.5,21.71,42.14c2.78,22.32-10.19,36.76-25.52,49.9c-0.44,0.37-1.09,0.54-1.67,0.69
c-0.37,0.09-0.8-0.03-1.59-0.08c-3.15-4.92-2.8-9.59,0.96-14.33c6.14-7.74,11.54-15.89,12.05-26.24
c1.24-25.02-14.28-44.09-39.26-47.94c-4.59-0.71-9.31-0.53-15-0.81c0.44,4.72,0.51,7.73,1.03,10.66
c8.8,49.42,17.66,98.83,26.47,148.26c1.07,6.03,2.01,12.08,2.81,18.15c1.93,14.59-2.85,26.51-14.6,35.46
c-18.51,14.1-39.18,15.5-60.44,8.72c-16.02-5.1-25.76-22.74-22.74-38.34c3.49-18.02,17.24-29.36,35.42-29.2
c17.96,0.16,31.41,11.98,34.49,30.27c0.42,2.52,1.01,5.02,1.49,7.33c10.2,0.4,17.08-7.88,15.5-18.5
c-3.27-22-6.51-44.01-10.45-65.89c-5.72-31.73-12.04-63.35-18.15-95.01c-0.4-2.07-1.27-4.05-2.29-7.23
c-7.24,4.84-12.49,9.93-15.47,17.08c-5.54,13.32-3.63,26.35,1.74,39.25c1.25,3.01,1.98,6.23,2.95,9.35
c-0.69,0.48-1.39,0.96-2.08,1.44c-1.98-1.63-4.28-2.98-5.89-4.92c-14.99-18.11-14.14-48.78,1.75-66.18
c2.06-2.26,4.06-4.69,6.52-6.45c5.79-4.17,9.56-8.69,8.28-16.73c-0.43-2.71,3.11-6.04,4.83-9.09
C260.1,225.14,260.88,225.37,261.65,225.6z"/>
</g>
<g>
<path class="st2" d="M242.98,129.77c-0.54-2.18-1.24-3.66-1.24-5.15c0.06-27.65,5.24-53.97,20.63-77.55
c0.78-1.19,1.62-2.36,2.52-3.47c15.38-18.96,34.82-17.62,45.72,4.2c15.14,30.31,13.51,60.55-6.91,87.73
c-13.67,18.2-29.81,34.59-45.42,51.26c-18.14,19.38-36.83,38.27-50.39,61.34c-4.74,8.07-9.5,16.33-12.73,25.07
c-8.46,22.81-4.26,43.77,11.57,62.22c9.81,11.44,22.06,19.31,36.6,23.44c5.39,1.53,7.9,4.61,6.35,11.29
c-2.86,0-5.84,0.44-8.66-0.07c-31-5.57-50.06-25.12-60.87-53.46c-11.63-30.51-8.06-59.85,11.23-86
c15.34-20.81,32.18-40.57,49.3-59.97c15.92-18.03,33.27-34.79,49.64-52.44c11.16-12.03,12.87-27,10.85-42.48
c-1.06-8.1-5.98-13.73-14.13-16.01c-7.39-2.07-12.75,1.54-17.1,6.79c-2.57,3.1-5.27,6.57-6.35,10.32
c-3.64,12.7-7.02,25.51-9.61,38.46C252.62,122.04,249,126,242.98,129.77z"/>
</g>
</g>
</g>
</g>
</svg>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><defs><radialGradient id="lorc-treasure-map-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="lorc-treasure-map-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="M227.4 34.7c-10.1 0-20.2.2-30.2.5l6.1 65.6-61.1-62.5c-31.3 2.5-62.5 6.6-93.8 12.5l34.2 28.4-48-.6c35.1 100.2 6.9 182.6-.3 292.1L130 476.5c10-1.3 19.9-2.4 29.6-3.3l21.5-42.2 18.6 28.8 41.5-33.5.8 43c82.9-.2 157.7 9.1 235.7 7.9-28.2-73-31.2-143.6-31.9-209.2l-33.3-19.1 32.7-33.9c-.4-21.3-1.3-42-3.6-61.9l-57.4.7 50.2-41.7c-3.8-15.5-9-30.4-16.1-44.7l-29.5-23.9C335 38 281.2 34.6 227.4 34.7zm58.7 37c10.6 24.75 21.1 49.5 31.7 74.3 7.5-10.5 14.9-21 22.4-31.5 16 27.2 32 54.3 48 81.5l-16.2 9.5-33.3-56.7-42.5 59.4-15.2-10.9 24-33.5-21.9-51.5-24.6 40.1 12 22.6-16.5 8.8-18.3-34.5-24.8 58.2-17.2-7.4 32.5-76.2 7.7-18c4.8 9.2 9.6 18.3 14.5 27.4 12.5-20.6 25.1-41.11 37.7-61.6zM91.2 128c6.72 1.6 13.4 3.4 19.2 5.3-2.1 5.9-4.1 11.8-6.2 17.6-5.79-1.6-11.72-3.4-16.9-4.7 1.39-6 2.62-12.1 3.9-18.2zm37.9 13.4c6.3 3.8 12 7.2 17 12.8L132.6 167c-4-3.7-8.6-7-12.8-9.4zm28.7 32.3c2.1 7.4 2.1 15.7 1.6 22.5l-18.5-2.4c.1-5.1.3-10-1-14.5zm-21.2 35.7 17.2 7.1c-3.3 6.6-5.1 12.7-8.6 17.8l-16.3-9c2.6-5.4 5.6-10.8 7.7-15.9zm-16.5 34.1 17.7 6.1c-1.5 5.4-3 11.2-3.6 16.2l-18.6-2c1.3-7.5 2.1-14 4.5-20.3zm207.8 17.4c8.5 1 14.6 3 21.7 7.1l-9.8 16c-4.1-2.8-9.4-3.8-13.5-4.5zm-21.2 1.5c1.1 6.1 2.5 12.2 3.9 18.3-5.9 1.3-11.7 3.3-16.5 5.1l-6.8-17.4c6.7-2.4 13.5-4.7 19.4-6zm-37.9 15.9 11 15.1c-5.6 4-11.8 7.8-16.8 10.6l-8.9-16.4c5.1-2.9 10.6-6.3 14.7-9.3zM135.3 281c1.5 4.7 4.2 9.2 6.9 12.1l-13.8 12.6c-5.5-5.7-9.5-13.5-11.2-20.1zm230.3 3.3c3.5 6.4 6.8 12.7 8.7 19.1l-17.8 5.6c-2-5.4-4.3-10.8-6.8-14.8zm-127.4 10.9 6.9 17.3c-6.4 2.7-12.9 4.8-18.6 6.5l-5-18c5.9-1.6 11.3-3.8 16.7-5.8zm-83.8 6.2c5.3 1.7 10.8 3.4 15.7 4.2-1.2 6.1-2 12.3-2.8 18.5-7-1-14.5-3.3-20.5-5.7zm50 3.5 2.8 18.5c-7.2 1.3-13.4 1.6-19.8 1.9l-.4-18.7c5.9-.2 11.6-.8 17.4-1.7zm174.5 18c1 6.4 1.6 12.9 2.2 19.3l-18.7 1.5c-.4-6-.9-11.9-2-17.8zm-67.6 30.8c18.9 3.5 44.9 16.2 68.9 33.9 7.4-9.9 14.4-20.4 21.3-31.1l30.1 12.9c-4.7 12.3-15 25.6-28.6 37.2 17 16.2 30.9 34.5 37 53-13.8-18.1-31.1-31.8-50.3-42.8-23.4 15.8-52.7 25.9-79.6 20.4 22.9-4.4 40.6-16.6 55.8-32.6-16.5-7.5-33.8-13.9-51.3-20.1z" 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>

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

View File

@@ -1,5 +1,108 @@
# 13.0
## 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
- ajout d'un bouton pour supprimer les anciens messages du tchat
- correction de messages d'erreur 'User ... lacks permission' / 'Active Effect ... does not exist'
- les joueurs peuvent affecter leurs enchantements aux objets enchantables de leur équipement
- correction des boutons pour lancer les maladresses
- utilisation des tables de compendium
- correction des droits pour mise à jour du message
- correction de la cuisine
- reprise de l'image de cuisine dans l'équipement
- prise en compte de la difficulté pour préparer la nourriture brute
## 13.0.23 - Le marché d'Illysis
- Améliorations
- lors de la consommation suite à un achat, les jets d'appréciation/éthylisme
sont faits par l'acheteur. Du coup, c'est lui qui lance le jet d'appréciation
(pour un service ou un plat de qualité), et ses dés sont utilisés avec dice-so-nice
- les créatures ont le statut Inconscient quand leur endurance est à 0
- Fenêtre de jets V2
- les soins de blessures sont correctement appliqués
- correction d'affichage jet sans compétence/avec compétence
- correction de la prise en compte des tactiques
- correction du filtrage des défenses selon l'attaque
- lorsque le mode de visibilité des jets général est changé, les fenêtres de jets suivent ce changement
## 13.0.22 - Les reflets d'Illysis
- Améliorations
- Changements d'icones pour les Acteurs et Scènes
- Corrections diverses
- l'encombrement total est affiché avec deux décimales
- le poids des monnaies est de nouveau décimal
- Erreurs de typographie diverses
- Mise en réserve de sort par le Gardien
- Fenêtre de jets V2
- utilisation pour les jets quelconques
- la fenêtre de jet pour les jets depuis un lien texte
- affichage des ajustements dans la fenêtre d'attaque avec arme à distance
- gestion des défenses contre les armes à distance
- pas de tactiques pour les attaques à distance
- attaque depuis l'onglet combat de la feuille de personnage, sans token sélectionné
- défense contre possession
- correction du mode "méditation" quand le haut-rêvant ne connait pas de méditation
- correction du mode "jeu" quand le personnage ne connait pas de jeux
- correction du mode "oeuvre" quand le personnage ne connait pas d'oeuvres
- Corrections liées à Foundry v12/v13
- Fix ajout de notes dans le journal par un joueur (/chrono, ou clic sur le libelé de l'heure dans l'horloge)
## 13.0.21 - La folie d'Illysis
- Jets d'appréciation et de moral

View File

@@ -63,6 +63,11 @@
#sidebar {
font-family: "GoudyAcc";
}
.sheet header.sheet-header h1 input .chat-message,
.window-app .window-header .chat-message,
#sidebar .chat-message {
font-family: "CaslonAntique";
}
/* For title, sidebar character and scene */
.sheet nav.sheet-tabs,
.window-app input,
@@ -888,7 +893,7 @@ body {
max-width: 1.4rem;
max-height: 1.4rem;
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 {
width: calc(60% - 110px - 1rem);
@@ -1205,6 +1210,10 @@ body {
color: rgba(173, 36, 26, 0.9);
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 {
-webkit-box-flex: 0;
-ms-flex: 0 0 48px;
@@ -1523,6 +1532,7 @@ body {
}
.system-foundryvtt-reve-de-dragon .item-actions-controls img,
.system-foundryvtt-reve-de-dragon .item-controls img {
vertical-align: text-bottom;
display: inline;
max-width: 1rem;
max-height: 1rem;
@@ -1535,10 +1545,17 @@ body {
font-size: 0.8em;
color: var(--color-controls-light);
}
.system-foundryvtt-reve-de-dragon .item-actions-controls img:hover,
.system-foundryvtt-reve-de-dragon .item-controls img:hover,
.system-foundryvtt-reve-de-dragon .item-actions-controls i:is(.fas, .far, .fa-solid, .fa-regular):hover,
.system-foundryvtt-reve-de-dragon .item-controls i:is(.fas, .far, .fa-solid, .fa-regular):hover {
.system-foundryvtt-reve-de-dragon .item-actions-controls a:hover,
.system-foundryvtt-reve-de-dragon .item-controls a:hover {
text-shadow: 1px 0px 0px #ff6600;
}
.system-foundryvtt-reve-de-dragon .item-actions-controls a img:hover,
.system-foundryvtt-reve-de-dragon .item-controls a img:hover {
opacity: 0.6;
filter: drop-shadow(1px 1px 1px #009966) invert(0.8);
}
.system-foundryvtt-reve-de-dragon .item-actions-controls a i:is(.fas, .far, .fa-solid, .fa-regular):hover,
.system-foundryvtt-reve-de-dragon .item-controls a i:is(.fas, .far, .fa-solid, .fa-regular):hover {
opacity: 0.6;
}
.system-foundryvtt-reve-de-dragon .rdd-roll-dialog .description-sort {
@@ -1721,25 +1738,121 @@ body {
.system-foundryvtt-reve-de-dragon form.app-personnage-aleatoire h2 {
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;
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;
left: calc(50% - 6.5rem);
width: 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;
width: 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;
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.sheet .window-content .sheet-body,
.system-foundryvtt-reve-de-dragon .application .window-content {
@@ -2266,8 +2379,9 @@ body {
}
.system-foundryvtt-reve-de-dragon .chat-inline-icon {
border: 0;
padding: 1px;
padding: 0 0.2rem;
vertical-align: text-top;
display: inline;
}
.system-foundryvtt-reve-de-dragon .actor-img-small {
max-width: 1.5rem;
@@ -2584,102 +2698,6 @@ body {
top: calc(50% - 0.7rem + 0.5 * 38%);
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 {
color: hsla(0, 0%, 100%, 0.5);
border: none;

Binary file not shown.

After

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

6
info-message.html Normal file
View File

@@ -0,0 +1,6 @@
<h3>L'oeuf de Dragon</h3>
<p>
On raconte que si le premier Vaisseau, on trouve un oeuf couvé par
un lapin, il faut bien s'occuper dudit lapin, car quatre mois plus tard
pourrait bien éclore un dragon!
</p>

View File

@@ -71,7 +71,11 @@
.sheet header.sheet-header h1 input,
.window-app .window-header,
#sidebar {
font-family: "GoudyAcc"
font-family: "GoudyAcc";
.chat-message{
font-family: "CaslonAntique";
}
}
/* For title, sidebar character and scene */

View File

@@ -136,7 +136,7 @@
max-height: 1.4rem;
border: 1px;
background: center / contain no-repeat
url("../../icons/templates/icone_parchement_vierge.webp");
url("../icons/templates/icone_parchement_vierge.webp");
}
.sheet-header .header-compteurs {
@@ -484,7 +484,10 @@
color: rgba(173, 36, 26, 0.9);
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 {
-webkit-box-flex: 0;
-ms-flex: 0 0 48px;
@@ -852,6 +855,7 @@
// }
img {
vertical-align: text-bottom;
display: inline;
max-width: 1rem;
max-height: 1rem;
@@ -865,8 +869,16 @@
color: var(--color-controls-light);
}
img:hover,
i:is(.fas, .far, .fa-solid, .fa-regular):hover {
a:hover {
text-shadow: 1px 0px 0px #ff6600;
}
a img:hover{
opacity: 0.6;
filter: drop-shadow(1px 1px 1px #009966) invert(0.8);
}
a i:is(.fas, .far, .fa-solid, .fa-regular):hover {
opacity: 0.6;
}
}
@@ -1056,7 +1068,7 @@
min-width: 30rem;
}
}
.app-calendar-astrologie {
.rdd-calendar-astrologie {
div.theme-astral {
width: 14rem;
margin: 0.4rem;
@@ -1076,6 +1088,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,
@@ -1665,8 +1776,9 @@
}
.chat-inline-icon {
border: 0;
padding: 1px;
padding: 0 0.2rem;
vertical-align: text-top;
display: inline;
}
.actor-img-small {
@@ -2013,106 +2125,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-btn:is(.calendar-lyre, .calendar-vaisseau) img {
color: hsla(0, 0%, 100%, 0.5);

View File

@@ -40,17 +40,21 @@ export class ChatVente {
static async diminuerQuantiteAchatVente(chatMessageId, quantite) {
const chatMessage = game.messages.get(chatMessageId)
const vente = ChatVente.getDetailVente(chatMessageId)
vente.nbLots = Math.max(0, vente.nbLots - quantite)
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.hbs', vente);
chatMessage.update({ content: html });
chatMessage.render(true);
const vente = ChatVente.getDetailVente(chatMessageId)
if (vente.nbLots <= quantite) {
ChatUtility.removeChatMessageId(chatMessageIdVente);
}
else {
vente.nbLots = vente.nbLots - quantite
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.hbs', vente)
await chatMessage.update({ content: html }, { render: true })
}
}
static async displayAchatVente(vente) {
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.hbs', vente);
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.hbs', vente)
const chatMessage = await ChatMessage.create(RdDUtility.chatDataSetup(html))
await chatMessage.setFlag(SYSTEM_RDD, NB_LOTS, vente.nbLots)
await chatMessage.setFlag(SYSTEM_RDD, DETAIL_VENTE, {

View File

@@ -9,7 +9,7 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { RdDSheetUtility } from "./rdd-sheet-utility.js";
import { MAINS_DIRECTRICES } from "./actor.js";
import { RdDBaseActorReveSheet } from "./actor/base-actor-reve-sheet.js";
import { ITEM_TYPES } from "./constants.js";
import { ACTOR_TYPES, ITEM_TYPES } from "./constants.js";
import { RdDItem } from "./item.js";
import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemBlessure } from "./item/blessure.js";
@@ -19,6 +19,7 @@ import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js";
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
import { MORAL } from "./moral/apprecier.mjs";
import { RdDItemSort } from "./item-sort.js";
/* -------------------------------------------- */
/**
@@ -52,18 +53,23 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
surprise: RdDBonus.find(this.actor.getSurprise(false)).label,
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
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!" : "",
malusArmure: this.actor.getMalusArmure()
})
this.timerRecherche = undefined;
if (formData.type == 'personnage') {
if (formData.type == ACTOR_TYPES.personnage) {
formData.options.mainsDirectrices = MAINS_DIRECTRICES;
formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie)
formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences);
formData.calc.competenceXPTotal = RdDItemCompetence.computeTotalXP(formData.competences);
formData.calc.fatigue = RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max);
foundry.utils.mergeObject(formData.calc, {
comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.competences),
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 => {
item.system.isHidden = this.options.recherche

View File

@@ -54,6 +54,7 @@ import { PART_OEUVRE } from "./roll/roll-part-oeuvre.mjs";
import { PART_CUISINE } from "./roll/roll-part-cuisine.mjs";
import { RdDPossessionV2 } from "./rdd-possession-v2.mjs";
import { Apprecier, MORAL, SITUATION_MORAL } from "./moral/apprecier.mjs";
import { Distance } from "./combat/distance.mjs";
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
@@ -205,7 +206,7 @@ export class RdDActor extends RdDBaseActorSang {
const niveau = comp?.system.niveau ?? (['(lancer)', '(tir)'].includes(main) ? -8 : -6)
const ajustement = (arme.parent?.getEtatGeneral() ?? 0) + ecaillesEfficacite
actions.push({
const attaque = {
label: arme.name + (main ? ' ' + main : ''),
action: 'attaque',
initOnly: false,
@@ -217,7 +218,9 @@ export class RdDActor extends RdDBaseActorSang {
dommages: dommages,
forceRequise: forceRequise,
initiative: RdDInitiative.getRollInitiative(caracValue, niveau, ajustement)
})
};
attaque.isDistance = Distance.typeAttaqueDistance(attaque),
actions.push(attaque)
}
addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS)
@@ -451,7 +454,7 @@ export class RdDActor extends RdDBaseActorSang {
blessures
})));
await this.supprimerBlessures(it => it.system.gravite <= 0);
await this.supprimerBlessures(it => it.system.gravite <= 0)
}
/* -------------------------------------------- */
@@ -495,18 +498,18 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async remiseANeuf() {
await this.removeEffects(e => !e.statuses?.has(STATUSES.StatusDemiReve), { render: false })
await this.supprimerBlessures(it => true, { render: false })
await this.update({
'system.sante.endurance.value': this.system.sante.endurance.max,
'system.sante.vie.value': this.system.sante.vie.max,
'system.sante.fatigue.value': 0,
'system.compteurs.ethylisme': { value: 1, nb_doses: 0, jet_moral: false }
})
await this.removeEffects(e => !e.statuses?.has(STATUSES.StatusDemiReve));
await this.supprimerBlessures(it => true);
}, { render: true })
await ChatMessage.create({
whisper: ChatUtility.getOwners(this),
content: 'Remise à neuf de ' + this.name
});
})
}
/* -------------------------------------------- */
@@ -700,9 +703,9 @@ export class RdDActor extends RdDBaseActorSang {
rencontre: rencontre,
tmr: true,
use: { libre: false, conditions: false },
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.getReveActuel() } }
forceCarac: this.getCaracReveActuel()
}
rollData.competence.system.defaut_carac = 'reve-actuel';
rollData.competence.system.defaut_carac = CARACS.REVE_ACTUEL
const dialog = await RdDRoll.create(this, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-reve-de-dragon.hbs' },
@@ -1071,13 +1074,13 @@ export class RdDActor extends RdDBaseActorSang {
}
const donHR = await RdDItemTete.teteDonDeHautReve()
if (donHR) {
this.createEmbeddedDocuments('Item', [donHR.toObject()])
await this.createEmbeddedDocuments('Item', [donHR.toObject()])
}
}
async addSortReserve(item) {
if (item?.type == ITEM_TYPES.sort && !item.system.isrituel) {
this.$createSortReserve(item)
await this.$createSortReserve(item)
return
}
const selectSortReserve = {
@@ -1088,13 +1091,14 @@ export class RdDActor extends RdDBaseActorSang {
DialogSelect.select(selectSortReserve, sort => this.$createSortReserve(sort))
}
$createSortReserve(sort) {
this.createEmbeddedDocuments("Item",
async $createSortReserve(sort) {
const ptReve = Number.isInteger(sort.system.ptreve) ? Number(sort.system.ptreve) : Number(sort.system.ptreve.match(/\d+/))
await this.createEmbeddedDocuments("Item",
[{
type: ITEM_TYPES.sortreserve,
name: sort.name,
img: sort.img,
system: { sortid: sort.id, draconic: sort.system.draconic, ptreve: Number(sort.system.ptreve.match(/\d+/)), coord: 'A1', heurecible: 'Vaisseau' }
system: { sortid: sort.id, draconic: sort.system.draconic, ptreve: ptReve, coord: 'A1', heurecible: 'Vaisseau' }
}],
{ renderSheet: true })
}
@@ -1137,7 +1141,7 @@ export class RdDActor extends RdDBaseActorSang {
async addTMRRencontre(currentRencontre) {
const toCreate = currentRencontre.toObject();
console.log('actor.addTMRRencontre(', toCreate, ')');
this.createEmbeddedDocuments('Item', [toCreate]);
await this.createEmbeddedDocuments('Item', [toCreate]);
}
/* -------------------------------------------- */
@@ -1312,14 +1316,6 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
async consommerNourritureboisson(itemId, choix = { doses: 1, seForcer: false, supprimerSiZero: false }) {
if (!this.isOwner) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'consommerNourritureboisson', args: [itemId, choix]
})
return
}
const item = this.getItem(itemId)
if (!item.getUtilisationCuisine()) {
return
@@ -1329,26 +1325,36 @@ export class RdDActor extends RdDBaseActorSang {
return
}
const onManger = [
async () => await this.manger(item, choix.doses, { diminuerQuantite: false }),
async () => await this.boire(item, choix.doses, { diminuerQuantite: false }),
async () => await item.diminuerQuantite(choix.doses, choix)
]
if (!this.isOwner) {
RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'consommerNourritureboisson', args: [itemId, choix]
})
return
}
if (await this._surmonterExotisme(item)) {
const appreciation = item.system.appreciation;
new Apprecier(this, appreciation, item.system.qualite)
.apprecier(onManger)
if (item.system.qualite > 0) {
new Apprecier(this, item.system.appreciation, item.system.qualite).apprecier()
}
await this.onConsommerNourritureboisson(item, choix)
}
else if (choix.seForcer) {
await this.jetDeMoral(MORAL.MALHEUREUX)
await Promise.all(onManger.map(async callback => await callback()))
await this.onConsommerNourritureboisson(item, choix)
}
else {
ui.notifications.info(`${this.name} ne n'arrive pas à manger de ${item.name}`)
}
}
async onConsommerNourritureboisson(item, choix) {
await this.manger(item, choix.doses, { diminuerQuantite: false })
await this.boire(item, choix.doses, { diminuerQuantite: false })
await item.diminuerQuantite(choix.doses, choix)
}
/* -------------------------------------------- */
async _surmonterExotisme(item) {
const qualite = Math.min(item.system.qualite, 0)
@@ -1359,7 +1365,7 @@ export class RdDActor extends RdDBaseActorSang {
const rolled = await this.doRollCaracCompetence(CARACS.VOLONTE, competence, difficulte, { title: `tente de surmonter l'exotisme de ${item.name}` })
return rolled.isSuccess
}
return true;
return true
}
/* -------------------------------------------- */
@@ -1415,6 +1421,7 @@ export class RdDActor extends RdDBaseActorSang {
actor: this,
vie: this.system.sante.vie.max,
alcool: alcool,
perteEndurance: 0,
jetVie: {
forceAlcool: forceAlcool,
nbDoses: nbDoses,
@@ -1427,7 +1434,7 @@ export class RdDActor extends RdDBaseActorSang {
}
await RdDResolutionTable.rollData(ethylismeData.jetVie);
this.gererExperience(ethylismeData.jetVie);
this.ajoutExperience(ethylismeData.jetVie);
RollDataAjustements.calcul(ethylismeData.jetVie, this);
if (ethylismeData.jetVie.rolled.isSuccess) {
ethylisme.nb_doses++;
@@ -1435,8 +1442,9 @@ export class RdDActor extends RdDBaseActorSang {
ethylisme.value = Math.max(ethylisme.value - 1, -7);
ethylisme.nb_doses = 0;
let perte = await RdDDice.rollTotal("1d6");
ethylismeData.perteEndurance = await this.santeIncDec("endurance", -perte);
if (ethylisme.value > 0) {
ethylismeData.perteEndurance = await this.santeIncDec("endurance", -(await RdDDice.rollTotal("1d6")))
}
if (!ethylisme.jet_moral) {
ethylismeData.jetMoral = await this._jetDeMoral(MORAL.HEUREUX, "Ethylisme");
@@ -1459,7 +1467,7 @@ export class RdDActor extends RdDBaseActorSang {
finalLevel: Number(ethylisme.value) + Number(this.system.compteurs.moral.value)
}
await RdDResolutionTable.rollData(ethylismeData.jetVolonte);
this.gererExperience(ethylismeData.jetVolonte);
this.ajoutExperience(ethylismeData.jetVolonte);
RollDataAjustements.calcul(ethylismeData.jetVolonte, this);
}
}
@@ -1554,21 +1562,6 @@ export class RdDActor extends RdDBaseActorSang {
return 0;
}
/* -------------------------------------------- */
createCallbackExperience() {
return {
action: r => this.appliquerAjoutExperience(r)
};
}
/* -------------------------------------------- */
createCallbackAppelAuMoral() { /* Si l'appel au moral est utilisé, on l'affiche dans le chat et on diminue éventuellement le moral */
return {
action: r => this.appliquerAppelMoral(r)
};
}
/* -------------------------------------------- */
isCaracMax(code) {
return RdDItemRace.isRacialMax(this, code)
@@ -1633,7 +1626,7 @@ export class RdDActor extends RdDBaseActorSang {
}
/* -------------------------------------------- */
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') {
async ajoutExperience(rollData, hideChatMessage = 'show') {
if (!rollData.rolled.isPart ||
rollData.finalLevel >= 0 ||
game.settings.get("core", "rollMode") == 'selfroll' ||
@@ -1885,16 +1878,11 @@ export class RdDActor extends RdDBaseActorSang {
};
RollDataAjustements.calcul(rollData, this);
await RdDResolutionTable.rollData(rollData);
this.gererExperience(rollData);
this.ajoutExperience(rollData);
await RdDRollResult.displayRollData(rollData, this)
return rollData.rolled;
}
/* -------------------------------------------- */
gererExperience(rollData) {
this.createCallbackExperience().action(rollData);
}
/* -------------------------------------------- */
async creerTacheDepuisLivre(item, options = { renderSheet: true }) {
const nomTache = "Lire " + item.name;
@@ -1930,7 +1918,7 @@ export class RdDActor extends RdDBaseActorSang {
async getTacheBlessure(blesse, blessure) {
const gravite = blessure?.system.gravite ?? 0;
if (gravite > 0) {
const tache = this.itemTypes['tache'].find(it => it.system.itemId == blessure.id)
const tache = this.itemTypes[ITEM_TYPES.tache].find(it => it.system.itemId == blessure.id)
?? await RdDItemBlessure.createTacheSoinBlessure(this, gravite);
await blessure?.updateTacheSoinBlessure(tache);
return tache
@@ -1950,7 +1938,7 @@ export class RdDActor extends RdDBaseActorSang {
diff: { value: diff ?? 0 }
}
}
return await RollDialog.create(rollData)
return await RollDialog.create(rollData, options)
}
RdDEmpoignade.checkEmpoignadeEnCours(this)
@@ -1984,7 +1972,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { tache: { key: tache.id, forced: options.forced } },
type: { allowed: [PART_TACHE], current: PART_TACHE }
}
return await RollDialog.create(rollData)
return await RollDialog.create(rollData, options)
}
const compData = this.getCompetence(tache.system.competence)
@@ -2028,8 +2016,8 @@ export class RdDActor extends RdDBaseActorSang {
await this.santeIncDec("fatigue", rollData.tache.system.fatigue);
await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-tache.hbs');
if (options?.onRollAutomate) {
options.onRollAutomate(rollData);
if (options?.callbacks) {
await Promise.all(callbacks.map(callback => callback(rollData)))
}
}
@@ -2498,79 +2486,18 @@ export class RdDActor extends RdDBaseActorSang {
const blessure = blesse.blessuresASoigner().find(it => it.id == blessureId);
if (blessure) {
if (!blessure.system.premierssoins.done) {
const tache = await this.getTacheBlessure(blesse, blessure);
return await this.rollTache(tache.id, {
onRollAutomate: async r => blesse.onRollTachePremiersSoins(blessureId, r),
title: 'Premiers soins',
forced: true
const tacheId = (await this.getTacheBlessure(blesse, blessure))?.id
return await this.rollTache(tacheId, {
callbacks: [async r => await blesse.callbackPremiersSoins(blessureId, r, this.id)],
title: 'Premiers soins', forced: true
});
}
else if (!blessure.system.soinscomplets.done) {
const diff = blessure.system.difficulte + (blessure.system.premierssoins.bonus ?? 0);
return await this.rollCaracCompetence(CARACS.DEXTERITE, "Chirurgie", diff, {
title: "Soins complets",
onRollAutomate: r => blesse.onRollSoinsComplets(blessureId, r),
forced: true
})
}
}
}
async onRollTachePremiersSoins(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollTachePremiersSoins', args: [blessureId, rollData]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && !blessure.system.premierssoins.done) {
const tache = rollData.tache;
if (rollData.rolled.isETotal) {
await blessure.update({
'system.difficulte': blessure.system.difficulte - 1,
'system.premierssoins.tache': Math.max(0, tache.system.points_de_tache_courant)
})
}
else {
const bonus = tache.system.points_de_tache_courant - tache.system.points_de_tache
await blessure.update({
'system.premierssoins': {
done: (bonus >= 0),
bonus: Math.max(0, bonus),
tache: Math.max(0, tache.system.points_de_tache_courant)
}
})
if (bonus >= 0) {
await this.deleteEmbeddedDocuments('Item', [tache.id])
}
}
}
}
async onRollSoinsComplets(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollSoinsComplets', args: [blessureId, rollData]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && blessure.system.premierssoins.done && !blessure.system.soinscomplets.done) {
// TODO: update de la blessure: passer par le MJ!
if (rollData.rolled.isETotal) {
await blessure.setSoinsBlessure({
difficulte: blessure.system.difficulte - 1,
premierssoins: { done: false, bonus: 0 }, soinscomplets: { done: false, bonus: 0 },
})
}
else {
// soins complets finis
await blessure.setSoinsBlessure({
soinscomplets: { done: true, bonus: Math.max(0, rollData.rolled.ptTache) },
callbacks: [async r => await blesse.onRollSoinsComplets(blessureId, r, this.id)],
onRollDone: RollDialog.onRollDoneClose,
title: "Soins complets", forced: true
})
}
}
@@ -2843,20 +2770,20 @@ export class RdDActor extends RdDBaseActorSang {
const guerisonData = { list: [], pointsConsommes: 0 }
for (let blessure of blessures) {
if (pointsGuerison >= blessure.system.gravite) {
pointsGuerison -= blessure.system.gravite;
guerisonData.list.push(`1 Blessure ${blessure.system.label} (${blessure.system.gravite} points)`);
pointsGuerison -= blessure.system.gravite
guerisonData.list.push(`1 Blessure ${blessure.system.label} (${blessure.system.gravite} points)`)
ids.push(blessure.id)
}
}
if (ids.length > 0) {
await this.supprimerBlessures(it => ids.includes(it.id));
await this.supprimerBlessures(it => ids.includes(it.id), { render: blessures.length != ids.length })
}
if (blessures.length == ids.length) {
let pvManquants = this.system.sante.vie.max - this.system.sante.vie.value;
let pvSoignees = Math.min(pvManquants, Math.floor(pointsGuerison / 2));
pointsGuerison -= pvSoignees * 2;
guerisonData.list.push(pvSoignees + " Points de Vie soignés");
await this.santeIncDec('vie', +pvSoignees, false);
await this.santeIncDec('vie', +pvSoignees, { render: true })
}
guerisonData.pointsConsommes = pointsGuerisonInitial - pointsGuerison;
return guerisonData;
@@ -2986,15 +2913,6 @@ export class RdDActor extends RdDBaseActorSang {
await this.diminuerQuantiteObjet(potion.id, 1, { supprimerSiZero: potion.supprimer });
}
/* -------------------------------------------- */
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 onPreUpdateItem(item, change, options, id) {
if (item.isCompetencePersonnage() && item.system.defaut_carac && item.system.xp) {

View File

@@ -26,7 +26,7 @@ import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES_CREATURES } fr
import { RollDataAjustements } from "../rolldata-ajustements-v1.js";
import { MappingCreatureArme } from "../item/mapping-creature-arme.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 } from "../roll/roll-constants.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js";
import { PART_COMP } from "../roll/roll-part-comp.mjs";
import { RdDInitiative } from "../initiative.mjs";
@@ -48,39 +48,24 @@ export class RdDBaseActorReve extends RdDBaseActor {
}
getCarac() {
return foundry.utils.mergeObject(this.system.carac,
{
'reve-actuel': this.getCaracReveActuel(),
'chance-actuelle': this.getCaracChanceActuelle()
},
{ inplace: false })
}
getCaracChanceActuelle() {
return {
label: 'Chance actuelle',
value: this.getChanceActuel(),
type: "number"
};
}
getCaracReveActuel() {
return {
label: 'Rêve actuel',
value: this.getReveActuel(),
type: "number"
};
const carac = super.getCarac()
foundry.utils.mergeObject(carac, this.getCaracReveActuel())
foundry.utils.mergeObject(carac, this.getCaracCompetenceCreature(), { overwrite: false })
return carac
}
getTaille() { return Misc.toInt(this.system.carac.taille?.value) }
getConstitution() { return this.getReve() }
getForce() { return this.getReve() }
getAgilite() { return this.getForce() }
getReve() { return Misc.toInt(this.system.carac.reve?.value) }
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() }
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()) }
getEncombrementMax() { return (this.getForce() + this.getTaille()) / 2 }
@@ -169,11 +154,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
async computeArmure(dmg) { return this.getProtectionNaturelle() }
async remiseANeuf() { }
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
async ajoutExperience(rollData, hideChatMessage = 'show') { }
computeResumeBlessure() { }
countBlessures(filter = it => !it.isContusion()) { return 0 }
async santeIncDec(name, inc, isCritique = false) { }
async santeIncDec(name, inc, options = {}) { }
async finDeRound(options = { terminer: false }) {
await this.finDeRoundSuppressionEffetsTermines(options)
@@ -208,7 +193,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
.map(async it => await RdDEmpoignade.onImmobilisation(this, it)))
}
async finDeRoundPossession(){
async finDeRoundPossession() {
await Promise.all(this.itemTypes[ITEM_TYPES.possession]
.map(async it => await RdDPossessionV2.onPossession(this, it)))
}
@@ -257,6 +242,13 @@ export class RdDBaseActorReve extends RdDBaseActor {
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) {
let competence = this.getCompetence(idOrName);
@@ -303,7 +295,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
/* -------------------------------------------- */
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) }
}
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
async ajoutExperience(rollData, hideChatMessage = 'show') { }
async appliquerAppelMoral(rollData) { }
async _onCloseRollDialog(html) { }
@@ -348,7 +340,10 @@ export class RdDBaseActorReve extends RdDBaseActor {
competence: competence,
show: { title: options?.title ?? '' }
},
callbacks: [async r => this.$onRollCompetence(r, options)]
callbacks: [
async r => this.$onRollCompetence(r, options),
...(options?.callbacks ?? [])
]
});
}
/**
@@ -376,15 +371,26 @@ export class RdDBaseActorReve extends RdDBaseActor {
}
RollDataAjustements.calcul(rollData, this);
await RdDResolutionTable.rollData(rollData);
this.gererExperience(rollData);
this.ajoutExperience(rollData);
await RdDResolutionTable.displayRollData(rollData, this)
return rollData.rolled;
}
gererExperience(rollData) { }
/* -------------------------------------------- */
async roll() {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
type: {
allowed: DEFAULT_ROLL_TYPES,
current: PART_COMP,
},
selected: {
diff: { type: DIFF.DEFAUT }
}
}
return await RollDialog.create(rollData)
}
RdDEmpoignade.checkEmpoignadeEnCours(this)
const carac = this.getCarac()
@@ -474,17 +480,15 @@ export class RdDBaseActorReve extends RdDBaseActor {
async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) {
RdDEmpoignade.checkEmpoignadeEnCours(this)
const competence = this.getCompetence(idOrName);
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
type: { allowed: options.arme ? ATTAQUE_ROLL_TYPES : DEFAULT_ROLL_TYPES },
type: { allowed: DEFAULT_ROLL_TYPES },
selected: {
carac: competence.type == ITEM_TYPES.competencecreature ? { key: competence.name } : undefined,
comp: { key: competence.name },
diff: { type: options.arme ? DIFF.ATTAQUE : DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 },
attaque: options.arme ? { arme: { key: options.arme.id } } : undefined
diff: { type: DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 },
}
}
return await RollDialog.create(rollData)
@@ -556,7 +560,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
type: {
allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE
}
};
}
return await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
}
})
@@ -565,16 +569,18 @@ export class RdDBaseActorReve extends RdDBaseActor {
/** --------------------------------------------
* @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
*/
rollArme(arme, categorieArme = 'competence', token = undefined) {
async rollArme(arme, maniement = 'competence', token = undefined) {
token = token ?? RdDUtility.getSelectedToken(this)
const compToUse = RdDItemArme.getCompetenceArme(arme, categorieArme)
const compToUse = RdDItemArme.getCompetenceArme(arme, maniement)
if (!RdDItemArme.isUtilisable(arme)) {
ui.notifications.warn(`Arme inutilisable: ${arme.name} non équipée ou avec une résistance de 0 ou moins`)
return
}
if (!Targets.hasTargets()) {
RdDConfirm.confirmer({
settingConfirmer: "confirmer-combat-sans-cible",
@@ -586,7 +592,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
onAction: async () => {
this.rollCompetence(compToUse, { tryTarget: false, arme: arme })
}
});
})
return
}
@@ -596,11 +602,12 @@ export class RdDBaseActorReve extends RdDBaseActor {
return
}
const competence = this.getCompetence(compToUse)
if (competence.isCompetencePossession()) {
return RdDPossession.onAttaquePossession(target, this, competence);
const comp = this.getCompetence(compToUse)
if (comp.isCompetencePossession()) {
// 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)
})
}
@@ -647,26 +654,21 @@ export class RdDBaseActorReve extends RdDBaseActor {
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 $afficherEncaissement(encaissement, show, defenderToken) {
async $onEncaissement(encaissement, show, attackerToken, defenderToken) {
await this.onAppliquerJetEncaissement(encaissement, attackerToken);
foundry.utils.mergeObject(encaissement, {
alias: defenderToken?.name ?? this.getAlias(),
hasPlayerOwner: this.hasPlayerOwner,
show: show ?? {}
}, { overwrite: false });
await ChatUtility.createChatWithRollMode(
{
roll: encaissement.roll,
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.hbs', encaissement)
},
await ChatUtility.createChatWithRollMode({
roll: encaissement.roll,
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.hbs', encaissement)
},
this
)
@@ -723,7 +725,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
}
await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-accorder-cauchemar.hbs')
await this.appliquerAjoutExperience(rollData, true)
await this.ajoutExperience(rollData, true)
return rolled.isSuccess;
}

View File

@@ -7,6 +7,8 @@ import { RdDDice } from "../rdd-dice.js";
import { RdDItemBlessure } from "../item/blessure.js";
import { ChatUtility } from "../chat-utility.js";
import { Misc } from "../misc.js";
import { RdDBaseActor } from "./base-actor.js";
import { CARACS } from "../rdd-carac.js";
/**
* Classe de base pour les acteurs qui peuvent subir des blessures
@@ -22,10 +24,18 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
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) }
getConstitution() { return Misc.toInt(this.system.carac.constitution?.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) }
getEnduranceMax() { return Math.max(1, this.getTaille() + this.getConstitution()) }
getFatigueMax() { return this.getEnduranceMax() * 2 }
@@ -97,15 +107,39 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
async computeArmure(attackerRoll) { return this.getProtectionNaturelle() }
async remiseANeuf() { }
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
async ajoutExperience(rollData, hideChatMessage = 'show') { }
/* -------------------------------------------- */
async onAppliquerJetEncaissement(encaissement, attackerToken) {
const santeOrig = foundry.utils.duplicate(this.system.sante);
const blessure = await this.ajouterBlessure(encaissement, attackerToken); // Will update the result table
const perteVie = await this.santeIncDec("vie", -encaissement.vie);
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, blessure?.isCritique());
const blessure = this.nouvelleBlessure(encaissement.gravite, {
localisation: encaissement.dmg?.loc.label ?? '',
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, { render: false })
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, { isCritique, render: false })
await this.createEmbeddedDocuments('Item', [blessure])
foundry.utils.mergeObject(encaissement, {
resteEndurance: perteEndurance.newValue,
@@ -114,33 +148,32 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
endurance: perteEndurance.perte,
vie: santeOrig.vie.value - perteVie.newValue,
blessure: blessure
});
})
}
/* -------------------------------------------- */
async santeIncDec(name, inc, isCritique = false) {
async santeIncDec(name, inc, options = {}) {
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
return;
return
}
if (!this.system.sante[name]) {
return
}
const sante = foundry.utils.duplicate(this.system.sante)
let compteur = sante[name];
if (!compteur) {
return;
}
let result = {
sonne: false,
};
const compteur = sante[name]
const result = { sonne: false }
let perteEndurance = 0
let minValue = name == "vie" ? -this.getSConst() - 1 : 0;
result.newValue = Math.max(minValue, Math.min(compteur.value + inc, compteur.max));
//console.log("New value ", inc, minValue, result.newValue);
let fatigue = 0;
if (name == "endurance" && result.newValue == 0 && inc < 0 && !options.isCritique) { // perte endurance et endurance devient 0 (sauf critique) -> -1 vie
sante.vie.value--;
result.perteVie = true;
}
foundry.utils.mergeObject(options, { render: true }, { overwrite: false })
if (name == "endurance") {
if (result.newValue == 0 && inc < 0 && !isCritique) { // perte endurance et endurance devient 0 (sauf critique) -> -1 vie
sante.vie.value--;
result.perteVie = true;
}
result.newValue = Math.max(0, result.newValue);
if (inc > 0) { // le max d'endurance s'applique seulement à la récupération
result.newValue = Math.min(result.newValue, this._computeEnduranceMax())
@@ -156,21 +189,87 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && sante.fatigue && fatigue > 0) {
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 }, options)
if (perteEndurance > 1) {
// 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, options));
} else if (name == "endurance" && inc > 0) {
await this.setSonne(false);
await this.setSonne(false, options)
}
if (this.isDead()) {
await this.setEffect(STATUSES.StatusComma, true);
await this.setEffect(STATUSES.StatusComma, true, options)
}
return result
}
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) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollTachePremiersSoins', args: [blessureId, tache, isETotal, soigneurId]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && !blessure.system.premierssoins.done) {
if (isETotal) {
await blessure.update({
'system.difficulte': blessure.system.difficulte - 1,
'system.premierssoins.tache': Math.max(0, tache.system.points_de_tache_courant)
})
}
else {
const bonus = tache.system.points_de_tache_courant - tache.system.points_de_tache
await blessure.update({
'system.premierssoins': {
done: (bonus >= 0),
bonus: Math.max(0, bonus),
tache: Math.max(0, tache.system.points_de_tache_courant)
}
})
if (bonus >= 0 && soigneurId) {
const soigneur = game.actors.get(soigneurId)
await soigneur.deleteEmbeddedDocuments('Item', [tache.id], { render: true })
}
}
}
}
async onRollSoinsComplets(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollSoinsComplets', args: [blessureId, rollData]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && blessure.system.premierssoins.done && !blessure.system.soinscomplets.done) {
// TODO: update de la blessure: passer par le MJ!
if (rollData.rolled.isETotal) {
await blessure.setSoinsBlessure({
difficulte: blessure.system.difficulte - 1,
premierssoins: { done: false, bonus: 0 }, soinscomplets: { done: false, bonus: 0 },
})
}
else {
// soins complets finis
await blessure.setSoinsBlessure({
soinscomplets: { done: true, bonus: Math.max(0, rollData.rolled.ptTache) },
})
}
}
}
/* -------------------------------------------- */
_computeEnduranceMax() {
const diffVie = this.system.sante.vie.max - this.system.sante.vie.value;
@@ -182,14 +281,22 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
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) {
await this.changeItemEffects(item)
await super.onCreateItem(item, options, id)
}
async onUpdateItem(item, options, id) {
async onUpdateItem(item, updates, options, id) {
await this.changeItemEffects(item);
await super.onUpdateItem(item, options, id)
await super.onUpdateItem(item, updates, options, id)
}
async onDeleteItem(item, options, id) {
@@ -224,32 +331,15 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
}
/* -------------------------------------------- */
async ajouterBlessure(encaissement, attackerToken = undefined) {
if (encaissement.gravite < 0) return;
if (encaissement.gravite > 0) {
while (this.countBlessures(it => it.system.gravite == encaissement.gravite) >= RdDItemBlessure.maxBlessures(encaissement.gravite) && encaissement.gravite <= 6) {
nouvelleBlessure(gravite, options = { origine: undefined, localisation: '' }) {
if (gravite < 0) return
if (gravite > 0) {
while (this.countBlessures(it => it.system.gravite == gravite) >= RdDItemBlessure.maxBlessures(gravite) && gravite <= 6) {
// Aggravation
encaissement.gravite += 2
if (encaissement.gravite > 2) {
encaissement.vie += 2;
}
gravite += 2
}
}
const endActuelle = this.getEnduranceActuelle();
const blessure = await RdDItemBlessure.createBlessure(this, encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken);
if (blessure.isCritique()) {
encaissement.endurance = endActuelle
}
if (blessure.isMort()) {
this.setEffect(STATUSES.StatusComma, true);
encaissement.mort = true;
ChatMessage.create({
content: `<img class="chat-icon" src="icons/svg/skull.svg" data-tooltip="charge" />
<strong>${this.getAlias()} vient de succomber à une seconde blessure critique ! Que les Dragons gardent son Archétype en paix !</strong>`
});
}
return blessure;
return RdDItemBlessure.prepareBlessure(gravite, options);
}
async supprimerBlessure({ gravite }) {
@@ -259,10 +349,10 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
}
}
async supprimerBlessures(filterToDelete) {
async supprimerBlessures(filterToDelete, options = { render: true}) {
const toDelete = this.filterItems(filterToDelete, ITEM_TYPES.blessure)
.map(it => it.id);
await this.deleteEmbeddedDocuments('Item', toDelete);
.map(it => it.id)
await this.deleteEmbeddedDocuments('Item', toDelete, options)
}
countBlessures(filter = it => !it.isContusion()) {
@@ -309,29 +399,31 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
}
/* -------------------------------------------- */
async jetEndurance(resteEndurance = undefined) {
async jetEndurance(resteEndurance = undefined, options) {
const jetEndurance = (await RdDDice.roll("1d20")).total;
const sonne = jetEndurance == 20 || jetEndurance > (resteEndurance ?? this.system.sante.endurance.value)
if (sonne) {
await this.setSonne();
await this.setSonne(true, options)
}
return { jetEndurance, sonne }
}
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) {
// Gestion blessure graves : -1 pt endurance par blessure grave
await this.santeIncDec("endurance", -nbGraves);
}
}
async setSonne(sonne = true) {
async setSonne(sonne = true, options = {}) {
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é`);
return;
return
}
await this.setEffect(STATUSES.StatusStunned, sonne)
await this.setEffect(STATUSES.StatusStunned, sonne, options)
}
isSonne() {

View File

@@ -12,6 +12,7 @@ import { SystemCompendiums } from "../settings/system-compendiums.js";
import { RdDItem } from "../item.js";
import { StatusEffects, STATUSES } from "../settings/status-effects.js";
import { Apprecier } from "../moral/apprecier.mjs";
import { CARACS } from "../rdd-carac.js";
export class RdDBaseActor extends Actor {
@@ -23,7 +24,7 @@ export class RdDBaseActor extends Actor {
}
static $findCaracByName(carac, name) {
const caracList = Object.entries(carac);
const caracList = Object.entries(carac)
let entry = Misc.findFirstLike(name, caracList, { mapper: it => it[0], description: 'caractéristique', onMessage: m => { } });
if (!entry || entry.length == 0) {
entry = Misc.findFirstLike(name, caracList, { mapper: it => it[1].label, description: 'caractéristique' });
@@ -50,7 +51,7 @@ export class RdDBaseActor extends Actor {
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("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("updateActor", (actor, change, options, actorId) => Misc.documentIfResponsible(actor)?.onUpdateActor(change, options, actorId))
}
@@ -62,25 +63,29 @@ export class RdDBaseActor extends Actor {
}
}
static remoteActorCall(callData) {
static remoteActorCall(callData, userId = undefined) {
if (game.user.isGM) {
RdDBaseActor.onRemoteActorCall(callData, game.user.id)
return false
}
else {
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_remote_actor_call",
data: callData,
userId: Misc.firstConnectedGMId()
})
return true
const gmUserId = Misc.firstConnectedGMId()
if (gmUserId) {
game.socket.emit(SYSTEM_SOCKET_ID, {
msg: "msg_remote_actor_call",
data: callData,
userId: gmUserId
})
return true
}
return false
}
}
static onRemoteActorCall(callData, userId) {
const actor = RdDBaseActor.getRealActor(callData?.actorId, callData?.tokenId);
if (userId == game.user.id) {
// Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
const actor = RdDBaseActor.getRealActor(callData?.actorId, callData?.tokenId);
const args = callData.args;
console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')');
actor[callData.method](...args);
@@ -88,13 +93,8 @@ export class RdDBaseActor extends Actor {
}
static getRealActor(actorId, tokenId) {
if (tokenId) {
let token = canvas.tokens.get(tokenId)
if (token) {
return token.actor
}
}
return game.actors.get(actorId)
const actor = tokenId ? canvas.tokens.get(tokenId)?.actor : undefined
return actor ?? game.actors.get(actorId)
}
getAlias() {
@@ -151,30 +151,47 @@ export class RdDBaseActor extends Actor {
super(docData, context);
}
getCarac() {
return foundry.utils.duplicate(this.system.carac)
}
findCaracByName(name) {
name = Grammar.toLowerCaseNoAccent(name)
switch (name) {
case 'reve-actuel': case 'reve actuel':
return this.system.carac.reve
case 'chance-actuelle': case 'chance actuelle':
return this.system.carac.chance
case 'vie':
return this.system.sante.vie
case 'reve actuel':
name = CARACS.REVE_ACTUEL
break
case 'chance actuelle':
name = CARACS.CHANCE_ACTUELLE
break
}
const carac = this.system.carac;
const carac = this.getCarac()
return RdDBaseActor.$findCaracByName(carac, name);
}
getCaracCompetenceCreature() {
return this.isCreatureOuEntite()
? Object.fromEntries(this.itemTypes[ITEM_TYPES.competencecreature].map(it => [Grammar.toLowerCaseNoAccent(it.name), { label: it.name, value: it.system.carac_value }]))
: {}
}
mapCarac(caracCode) { return caracCode }
getCaracByName(name) {
name = this.mapCarac(Grammar.toLowerCaseNoAccent(name))
name = this.mapCarac(Grammar.toLowerCaseNoAccent(name)) ?? name
switch (name) {
case 'reve-actuel': case 'reve actuel':
return this.getCaracReveActuel();
case 'chance-actuelle': case 'chance-actuelle':
return this.getCaracChanceActuelle();
case 'reve actuel':
name = CARACS.REVE_ACTUEL
break
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);
}
@@ -263,14 +280,14 @@ export class RdDBaseActor extends Actor {
return this.getEffects().filter(it => it.statuses.has(effectId))
}
async setEffect(effectId, status) {
async setEffect(effectId, status, options = { render: true }) {
if (this.isEffectAllowed(effectId)) {
const effects = this.getEffectsByStatus(effectId)
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) {
await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.prepareActiveEffect(effectId)], { render: true })
await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.prepareActiveEffect(effectId)], options)
}
}
}
@@ -279,13 +296,13 @@ export class RdDBaseActor extends Actor {
this.removeEffects(it => it.id == id)
}
async removeEffects(filter = e => true) {
async removeEffects(filter = e => true, options = { render: true }) {
if (game.user.isGM) {
const ids = this.getEffects(filter)
.filter(it => this.canRemoveEffects(it))
.map(it => it.id)
if (ids.length > 0) {
await this.deleteEmbeddedDocuments('ActiveEffect', ids)
await this.deleteEmbeddedDocuments('ActiveEffect', ids, options)
}
}
@@ -318,7 +335,9 @@ export class RdDBaseActor extends Actor {
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) {
@@ -327,9 +346,8 @@ export class RdDBaseActor extends Actor {
}
}
async _removeItemFromConteneur(item) {
const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id))
const updates = this.findConteneur(item)
.map(conteneur => {
const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id)
return { _id: conteneur.id, 'system.contenu': nouveauContenu }
@@ -359,7 +377,7 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */
async cleanupConteneurs() {
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)
.map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } });
if (updates.length > 0) {
@@ -370,7 +388,7 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */
getFortune() {
return Monnaie.getFortune(this.itemTypes['monnaie']);
return Monnaie.getFortune(this.itemTypes[ITEM_TYPES.monnaie]);
}
/* -------------------------------------------- */
@@ -413,6 +431,14 @@ export class RdDBaseActor extends Actor {
}
async depenserSols(sols) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
userId: Misc.connectedGMOrUser(),
tokenId: this.token?.id,
actorId: this.id,
method: 'depenserSols', args: [sols]
})
}
let reste = this.getFortune() - Number(sols);
if (reste >= 0) {
await Monnaie.optimiserFortune(this, reste);
@@ -421,32 +447,31 @@ export class RdDBaseActor extends Actor {
}
async ajouterSols(sols, fromActorId = undefined) {
sols = Number(sols);
sols = Number(sols)
if (sols == 0) {
return;
return
}
if (sols < 0) {
ui.notifications.error(`Impossible d'ajouter un gain de ${sols} <0`);
return;
ui.notifications.error(`Impossible d'ajouter un gain de ${sols} <0`)
return
}
if (fromActorId && !this.isOwner) {
RdDBaseActor.remoteActorCall({
return RdDBaseActor.remoteActorCall({
userId: Misc.connectedGMOrUser(),
tokenId: this.token?.id,
actorId: this.id,
method: 'ajouterSols', args: [sols, fromActorId]
});
})
}
else {
const fromActor = game.actors.get(fromActorId)
await Monnaie.optimiserFortune(this, sols + this.getFortune());
RdDAudio.PlayContextAudio("argent"); // Petit son
ChatMessage.create({
whisper: ChatUtility.getOwners(this),
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
});
}
const fromActor = game.actors.get(fromActorId)
await Monnaie.optimiserFortune(this, sols + this.getFortune());
RdDAudio.PlayContextAudio("argent"); // Petit son
ChatMessage.create({
whisper: ChatUtility.getOwners(this),
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
})
}
/* -------------------------------------------- */
@@ -458,24 +483,28 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */
async achatVente(achat) {
if (achat.vendeurId == achat.acheteurId) {
ui.notifications.info("Inutile de se vendre à soi-même");
return;
ui.notifications.info("Inutile de se vendre à soi-même")
return
}
if (!Misc.isFirstConnectedGM()) {
const cout = Number(achat.prixTotal ?? 0)
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined
if (acheteur && !acheteur.isOwner) {
ui.notifications.warn(`${game.user.id} n'est pas propriétaire de ${this.name} et effectue un achat pour lui!`)
RdDBaseActor.remoteActorCall({
actorId: achat.vendeurId ?? achat.acheteurId,
actorId: achat.acheteurId,
method: 'achatVente', args: [achat]
});
return
}
const cout = Number(achat.prixTotal ?? 0);
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined;
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined;
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined
const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id);
if (!itemVendu) {
ChatUtility.notifyUser(achat.userId, 'warn', vendeur ? `Le vendeur n'a pas plus de ${achat.vente.item.name} !` : `Impossible de retrouver: ${achat.vente.item.name} !`);
return;
return
}
if (vendeur && !vendeur.verifierQuantite(itemVendu, quantite)) {
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
@@ -483,10 +512,10 @@ export class RdDBaseActor extends Actor {
}
if (acheteur && !acheteur.verifierFortune(cout)) {
ChatUtility.notifyUser(achat.userId, 'warn', `Vous n'avez pas assez d'argent pour payer ${Math.ceil(cout / 100)} sols !`);
return;
return
}
await vendeur?.vendre(itemVendu, quantite, cout);
await acheteur?.acheter(itemVendu, quantite, cout, achat)
await vendeur?.vendre(itemVendu, quantite, cout, acheteur);
await acheteur?.acheter(itemVendu, quantite, cout, achat, vendeur)
if (cout > 0) {
RdDAudio.PlayContextAudio("argent");
@@ -501,22 +530,32 @@ export class RdDBaseActor extends Actor {
});
if (!achat.vente.quantiteIllimite) {
if (achat.vente.nbLots <= achat.choix.nombreLots) {
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
}
else if (achat.chatMessageIdVente) {
await ChatVente.diminuerQuantiteAchatVente(achat.chatMessageIdVente, achat.choix.nombreLots)
}
await this.updateMessageVente(achat.chatMessageIdVente, achat.choix.nombreLots);
}
}
async vendre(item, quantite, cout) {
await this.ajouterSols(cout);
await this.decrementerQuantiteItem(item, quantite);
async updateMessageVente(chatMessageIdVente, nombreLots) {
const chatMessage = game.messages.get(chatMessageIdVente)
if (!chatMessage.isOwner) {
return RdDBaseActor.remoteActorCall({
userId: Misc.firstConnectedGMId(),
actorId: this.id,
method: 'updateMessageVente', args: [chatMessageIdVente, nombreLots]
})
}
await ChatVente.diminuerQuantiteAchatVente(chatMessageIdVente, nombreLots);
}
async vendre(item, quantite, cout, acheteur) {
await this.ajouterSols(cout, acheteur?.id)
await this.decrementerQuantiteItem(item.id, quantite)
}
async acheter(item, quantite, cout, achat) {
await this.depenserSols(cout)
if (!this.isOwner) {
ui.notifications.warn(`${game.user.id} n'est pas propriétaire de ${this.name} et effectue un achat!`)
}
const createdItemId = await this.creerQuantiteItem(item, quantite)
if (item.type == ITEM_TYPES.nourritureboisson && achat.choix.consommer && createdItemId != undefined) {
achat.choix.doses = achat.choix.nombreLots;
@@ -538,43 +577,46 @@ export class RdDBaseActor extends Actor {
async consommerNourritureboisson(itemId, choix, userId) { }
async decrementerQuantiteItem(item, quantite, options = { supprimerSiZero: true }) {
async decrementerQuantiteItem(itemId, quantite, options = { supprimerSiZero: true }) {
const item = this.items.get(itemId)
if (item.isService()) {
return;
return
}
const itemId = item.id;
let resteQuantite = (item.system.quantite ?? 1) - quantite;
if (resteQuantite <= 0) {
if (options.supprimerSiZero) {
await this.deleteEmbeddedDocuments("Item", [item.id]);
}
else {
await this.updateEmbeddedDocuments("Item", [{ _id: itemId, 'system.quantite': 0 }]);
}
if (resteQuantite < 0) {
ui.notifications.warn(`La quantité de ${item.name} était insuffisante, l'objet a donc été supprimé`)
}
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
userId: Misc.connectedGMOrUser(),
tokenId: this.token?.id,
actorId: this.id,
method: 'decrementerQuantiteItem', args: [itemId, quantite, options]
})
}
else if (resteQuantite > 0) {
const realItem = this.getItem(item.id)
realItem.update({ 'system.quantite': resteQuantite });
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': resteQuantite }]);
const resteQuantite = Math.max((item.system.quantite ?? 1) - quantite, 0)
if (resteQuantite <= 0 && options.supprimerSiZero) {
await this.deleteEmbeddedDocuments("Item", [itemId]);
}
else {
await this.updateEmbeddedDocuments("Item", [{ _id: itemId, 'system.quantite': resteQuantite }])
}
}
async creerQuantiteItem(item, quantite) {
if (this.canReceive(item)) {
const isItemEmpilable = "quantite" in item.system;
const baseItem = {
type: item.type,
img: item.img,
name: item.name,
system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }, { inplace: false })
};
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
const items = await this.createEmbeddedDocuments("Item", newItems);
return items.length > 0 ? items[0].id : undefined;
if (!this.canReceive(item)) {
return
}
const isItemEmpilable = "quantite" in item.system;
const baseItem = {
type: item.type,
img: item.img,
name: item.name,
system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }, { inplace: false })
}
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
const items = await this.createEmbeddedDocuments("Item", newItems);
return newItems.length > 0 ? items[0].id : undefined;
}
/* -------------------------------------------- */
@@ -594,7 +636,7 @@ export class RdDBaseActor extends Actor {
}
getEncTotal() {
return Math.floor(this.encTotal ?? 0)
return Number(this.encTotal?.toFixed(2) ?? 0.00)
}
async createItem(type, name = undefined) {
@@ -627,7 +669,7 @@ export class RdDBaseActor extends Actor {
if (srcId != destId && itemId != destId) { // déplacement de l'objet
const src = this.getItem(srcId);
const dest = this.getItem(destId);
const cible = this.getContenantOrParent(dest);
const cible = this.findConteneurOrParent(dest);
const [empilable, message] = item.isInventaireEmpilable(dest);
if (empilable) {
await dest.empiler(item)
@@ -649,15 +691,15 @@ export class RdDBaseActor extends Actor {
return result;
}
getContenantOrParent(dest) {
findConteneurOrParent(dest) {
if (!dest || dest.isConteneur()) {
return dest;
}
return this.getContenant(dest);
return this.findConteneur(dest)
}
getContenant(item) {
return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id));
findConteneur(item) {
return this.itemTypes[ITEM_TYPES.conteneur].find(it => it.system.contenu.includes(item.id));
}
@@ -832,6 +874,7 @@ export class RdDBaseActor extends Actor {
ui.notifications.info(`${this.getAlias()} ne peut pas faire cette action: ${action}`)
}
ajoutExperience(rollData) { }
isAlcoolise() { return false }
async jetEthylisme() { this.actionImpossible("jet d'éthylisme") }
async rollAppelChance() { this.actionImpossible("appel à la chance") }
@@ -862,4 +905,5 @@ export class RdDBaseActor extends Actor {
}
})
}
}

View File

@@ -28,11 +28,11 @@ export class RdDCommerce extends RdDBaseActor {
await super.depenserSols(cout)
}
async decrementerQuantiteItem(item, quantite) {
async decrementerQuantiteItem(itemId, quantite) {
if (this.system.illimite) {
return;
}
await super.decrementerQuantiteItem(item, quantite, { supprimerSiZero: false });
await super.decrementerQuantiteItem(itemId, quantite, { supprimerSiZero: false });
}
calculerPrix(item) {

View File

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

View File

@@ -18,6 +18,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
formData.niveau = this.actor.getNiveau()
delete formData.system.carac.niveau
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 } })
return formData
}

View File

@@ -86,11 +86,7 @@ export class RdDEntite extends RdDBaseActorReve {
return
}
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance);
foundry.utils.mergeObject(encaissement, {
resteEndurance: perteEndurance.newValue,
endurance: perteEndurance.perte,
blessure: RdDItemBlessure.prepareBlessure(encaissement.gravite, encaissement.dmg?.loc.label ?? '', attackerToken)
})
foundry.utils.mergeObject(encaissement, { resteEndurance: perteEndurance.newValue, endurance: perteEndurance.perte })
}
isEntiteAccordee(attacker) {

View File

@@ -103,11 +103,10 @@ export class RdDActorExportSheet extends RdDActorSheet {
gravite: this.html.find(event.currentTarget).data('gravite')
})
)
this.html.find('.click-blessure-add').click(async event =>
await this.actor.ajouterBlessure({
gravite: this.html.find(event.currentTarget).data('gravite')
})
)
this.html.find('.click-blessure-add').click(async event => {
const blessure = this.actor.nouvelleBlessure(this.html.find(event.currentTarget).data('gravite'))
await actor.createEmbeddedDocuments('Item', [blessure])
})
this.html.find('.button-export').click(async event => await
ExportScriptarium.INSTANCE.exportActors([this.actor],
`${this.actor.uuid}-${this.actor.name}`

View File

@@ -3,6 +3,8 @@ import { RdDCarac } from "../../rdd-carac.js";
import { RdDItemCompetence } from "../../item-competence.js";
import { RdDUtility } from "../../rdd-utility.js";
import { TextRollManager } from "./text-roll-formatter.js";
import RollDialog from "../../roll/roll-dialog.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2 } from "../../settings/options-avancees.js";
const REGECP_CARAC = "(?<carac>[A-Za-zÀ-ÖØ-öø-ÿ\\s\\-]+)"
const REGEXP_COMP = "(\\/(?<competence>[A-Za-zÀ-ÖØ-öø-ÿ ]+([1-2]?[A-Za-zÀ-ÖØ-öø-ÿ ]+)?))?"
@@ -49,10 +51,11 @@ export class TextRollCaracCompetence {
caracCode = actor.mapCarac(caracCode)
if (caracCode) {
if (competence) {
await actor.rollCaracCompetence(caracCode, competence, diff)
await actor.rollCaracCompetence(caracCode, competence, diff,
{ title: "", onRollDone: RollDialog.onRollDoneClose })
}
else {
await actor.rollCarac(caracCode, { diff })
await actor.rollCarac(caracCode, { diff , onRollDone: RollDialog.onRollDoneClose})
}
}
}

View File

@@ -5,7 +5,7 @@ import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
/**
* Class providing helper methods to get the list of users, and
* Class providing helper methods around the Chat message
*/
export class ChatUtility {
@@ -215,11 +215,13 @@ export class ChatUtility {
static async onRenderChatMessage(chatMessage, html, data) {
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 timestampData = timestamp.toCalendrier();
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)
}
}
@@ -233,4 +235,9 @@ export class ChatUtility {
static async setTimestamp(chatMessage) {
await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp());
}
static getISODate(chatMessage) {
const date = new Date(chatMessage.timestamp);
return date?.toISOString().substring(0, 10)
}
}

View File

@@ -0,0 +1,77 @@
import { ChatUtility } from "../chat-utility.js"
import { Misc } from "../misc.js"
import { RdDTimestamp } from "../time/rdd-timestamp.js"
const fields = foundry.applications.fields
export class DialogFlushByDate {
static async init() {
Hooks.once("renderChatLog", async () => await DialogFlushByDate.onFirstRenderChatLog())
}
static async onFirstRenderChatLog() {
if (game.user.isGM) {
const content = await foundry.applications.handlebars.renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat/button-flush-by-date.hbs')
const flushButton = document.querySelector("#chat-controls button[data-action='flush']")
flushButton.insertAdjacentHTML("afterend", content)
flushButton.parentElement.querySelector("button[name='flush-by-date']")?.addEventListener(
"click", e => {
if (game.messages.size > 0) {
DialogFlushByDate.create()
}
else {
ui.notifications.info("Aucun message à supprimer!")
}
e.preventDefault()
})
}
}
static async create() {
const dates = DialogFlushByDate.getChatMessageDates(game.messages)
const selectGroup = fields.createFormGroup({
input: fields.createSelectInput({
options: dates.map(it => { return { label: `${it.dateTerre} | ${it.dateReve}`, value: it.timestamp } }),
name: 'timestamp'
}),
label: 'Messages antérieurs au',
hint: 'Supprimer les messages antérieurs à la date'
})
const selected = await foundry.applications.api.DialogV2.input({
window: { title: "Supprimer les messages du tchat" },
content: selectGroup.outerHTML,
ok: {
label: "Supprimer",
icon: "fa-solid fa-trash-can",
}
})
if (selected) {
const timestamp = Number.parseInt(selected.timestamp)
const toDelete = game.messages.filter(it => it.timestamp < timestamp)
toDelete.forEach(it => it.delete())
}
}
static getChatMessageDates(messages) {
const datesTerre = Object.values(Misc.classifyFirst(messages,
m => ChatUtility.getISODate(m),
m => DialogFlushByDate.chatMessageDates(m)))
const timestamps = new Set(datesTerre.map(it => it.timestamp))
const datesReve = Object.values(Misc.classifyFirst(messages,
m => RdDTimestamp.fromChatMessage(m).isoDate(),
m => DialogFlushByDate.chatMessageDates(m)))
const dates = [...datesTerre, ...datesReve.filter(it => !timestamps.has(it.timestamp))]
return dates.sort(Misc.ascending(it => it.timestamp))
}
static chatMessageDates(it) {
return {
timestamp: it.timestamp,
dateTerre: new Date(it.timestamp).toLocaleDateString(),
dateReve: RdDTimestamp.fromChatMessage(it).formatDate()
}
}
}

122
module/combat/distance.mjs Normal file
View File

@@ -0,0 +1,122 @@
import { ITEM_TYPES } from "../constants.js"
import { Grammar } from "../grammar.js"
import { ATTAQUE_TYPE } from "../item/arme.js"
import { Misc } from "../misc.js"
export class Distance {
static typeAttaqueDistance(attaque) {
function mapTypeAttaque(value) {
switch (value) {
case ATTAQUE_TYPE.LANCER: case 'lancer': return ATTAQUE_TYPE.LANCER
case ATTAQUE_TYPE.TIR: case 'tir': return ATTAQUE_TYPE.TIR
}
return undefined
}
switch (attaque.comp?.type) {
case ITEM_TYPES.competence: return mapTypeAttaque(attaque.main)
case ITEM_TYPES.competencecreature: return mapTypeAttaque(attaque.arme.system.categorie)
}
return undefined
}
static ajustements(token, defenderToken, attaque) {
const typeAttaque = Distance.typeAttaqueDistance(attaque)
if (typeAttaque) {
const distance = Distance.distance(token, defenderToken)
const isVisible = Distance.isVisible(token, defenderToken)
const portee = Distance.ajustementPortee(distance, attaque.arme)
const taille = Distance.ajustementTaille(defenderToken?.actor)
const activite = Distance.ajustementMouvement(defenderToken)
const total = Distance.diff(portee, taille, activite)
const diffDefense = Distance.ajustementDefense(attaque)
return { typeAttaque, isVisible, distance, portee, taille, activite, total, diffDefense }
}
return undefined
}
static distance(token, defenderToken) {
if (Distance.$isToken(token) && Distance.$isToken(defenderToken)) {
const source = token.getCenterPoint()
const target = defenderToken.getCenterPoint()
const measure = canvas.grid.measurePath([ source, target])
return measure.distance
}
return -1 /* distance indéterminée */
}
static isVisible(token, defenderToken) {
// TODO: regarder les StatusEffect aveuglé?
if (Distance.$isToken(token) && Distance.$isToken(defenderToken)) {
return canvas.effects.visibility.testVisibility(defenderToken.getCenterPoint(), { object: token })
}
return true
}
static ajustementPortee(distance, arme) {
if (distance < 0 || !arme) {
return { msg: "non déterminée", diff: 0 };
}
if (arme.system.portee_courte && distance <= arme.system.portee_courte) return { msg: "courte", diff: 0 };
if (arme.system.portee_moyenne && distance <= arme.system.portee_moyenne) return { msg: "moyenne", diff: -3 };
if (arme.system.portee_extreme && distance <= arme.system.portee_extreme) return { msg: "extrême", diff: -5 };
return { msg: "inatteignable", diff: -10 };
}
static ajustementTaille(actor) {
if (!actor) {
return { msg: "non déterminée", diff: 0 };
}
if (actor.isVehicule()) return { msg: "véhicule", diff: 0 }
const taille = actor.getCaracByName('TAILLE')?.value ?? 1;
if (taille <= 1) return { msg: "souris", diff: -8 };
if (taille <= 3) return { msg: "chat", diff: -4 };
if (taille <= 5) return { msg: "chien", diff: -2 };
if (taille <= 15) return { msg: "humanoïde", diff: 0 };
if (taille <= 20) return { msg: "ogre", diff: 2 };
return { msg: "gigantesque", diff: 4 };
}
static ajustementMouvement(defenderToken) {
if (Distance.$isToken(defenderToken)) {
if (defenderToken.actor?.getSurprise(true) != '') return { msg: "immobile (surprise)", diff: 0 };
if (defenderToken.inCombat) return { msg: "en combat", diff: -4 };
}
return { msg: "à déterminer", diff: -3 };
}
static diff(...ajustements) {
return ajustements.map(it => it.diff).filter(d => !Number.isNaN(d)).reduce(Misc.sum(), 0)
}
static ajustementDefense(attaque) {
switch (Grammar.toLowerCaseNoAccentNoSpace(attaque.comp.name)) {
case 'arbalete': return { label: 'Parade carreau', value: -5 }
case 'arc': return { label: 'Parade flêche', value: -5 }
case 'fronde': return { label: 'Parade bille de fronde', value: -4 }
case 'daguedejet': return { label: 'Parade/Esquive dague lancée', value: -2 }
case 'javelot': return { label: 'Parade/Esquive javelot lancé', value: -2 }
case 'fouet': return { label: 'Parade/Esquive fouet', value: 0 }
}
return { label: 'Parade/esquive projectile', value: 0 }
}
static ajustementBouclier(bouclier) {
if (bouclier?.system.categorie_parade == 'boucliers') {
if (bouclier.system.force < 10) {
return { label: 'Bouclier léger', value: -3 }
}
if (bouclier.system.force < 12) {
return { label: 'Bouclier moyen', value: 0 }
}
return { label: 'Bouclier lourd', value: 3 }
}
/* esquive */
return undefined
}
static $isToken(token) {
return token instanceof Token || token instanceof TokenDocument
}
}

View File

@@ -7,7 +7,7 @@ const fields = foundry.data.fields
export class CommonInventaire extends CommonTemplate {
fields() {
return {
encombrement: new fields.NumberField({ label: "Encombrement", initial: 0, ...INTEGER }),
encombrement: new fields.NumberField({ label: "Encombrement", initial: 0, ...DECIMAL }),
quantite: new fields.NumberField({ label: "Quantité", initial: 1, ...INTEGER }),
qualite: new fields.NumberField({ label: "Qualité", initial: 0, ...INTEGER_SIGNED }),
cout: new fields.NumberField({ label: "Coût", initial: 0.0, ...DECIMAL }),

View File

@@ -70,7 +70,7 @@ export class DialogChronologie extends Dialog {
async ajouter() {
await this.forceValidation();
const { journalId, journalEntry } = this.findJournal();
if (journalEntry?.canUserModify(game.user)) {
if (journalEntry?.canUserModify(game.user, 'update')) {
const journalParameters = this.extractJournalParameters();
const jour = journalParameters.dateRdD.jour;

View File

@@ -1,10 +1,10 @@
import { ITEM_TYPES, renderTemplate } from "../constants.js"
import { ACTOR_TYPES, ITEM_TYPES, renderTemplate } from "../constants.js"
import { RdDItemSort } from "../item-sort.js"
import { Misc } from "../misc.js"
export const ACTION_ITEM_ENCHANTER = {
code: 'item-enchanter', label: 'Enchanter', icon: it => 'fa-solid fa-sparkles',
filter: it => game.user.isGM || DialogEnchanter.isEnchantable(it) && it.parent?.type != ACTOR_TYPES.commerce,
filter: it => DialogEnchanter.isEnchantable(it) && it.parent?.type != ACTOR_TYPES.commerce,
action: (item, actor) => DialogEnchanter.enchanter(item)
}

View File

@@ -2,7 +2,7 @@
import { Grammar } from "./grammar.js";
import { RdDInitiative } from "./initiative.mjs";
import { RdDItem } from "./item.js";
import { CATEGORIES_COMPETENCE_COMBAT, CATEGORIES_COMPETENCES, SANS_COMPETENCE } from "./item/base-items.js";
import { CATEGORIES_COMPETENCES, SANS_COMPETENCE } from "./item/base-items.js";
import { Misc } from "./misc.js";
const competenceTroncs = [["Esquive", "Dague", "Corps à corps"],
@@ -136,7 +136,7 @@ export class RdDItemCompetence extends RdDItem {
return troncList;
}
}
return [];
return []
}
/* -------------------------------------------- */

View File

@@ -2,6 +2,7 @@ import { ITEM_TYPES } from "./constants.js";
import { RdDItem } from "./item.js";
import { RdDInitiative } from "./initiative.mjs";
import { RdDItemArme } from "./item/arme.js";
import { Distance } from "./combat/distance.mjs";
/* -------------------------------------------- */
export class RdDItemCompetenceCreature extends RdDItem {
@@ -45,12 +46,12 @@ export class RdDItemCompetenceCreature extends RdDItem {
equipe: true,
mortalite: this.system.mortalite,
dommages: this.system.dommages,
//dmg: this.system.dommages,
initiative: initative
};
}
attaque.isDistance = Distance.typeAttaqueDistance(attaque)
return attaque
}
return undefined;
return undefined
}
getCategorieAttaque() {

View File

@@ -16,6 +16,7 @@ import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
import { ItemAction } from "./item/item-actions.js";
import { SANS_COMPETENCE } from "./item/base-items.js";
import { Apprecier } from "./moral/apprecier.mjs";
import { CARACS } from "./rdd-carac.js";
/**
* Extend the basic ItemSheet for RdD specific items
@@ -104,7 +105,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
descriptionmj: await RdDTextEditor.enrichHTML(this.item.system.descriptionmj, this.item),
isComestible: this.item.getUtilisationCuisine(),
options: RdDSheetUtility.mergeDocumentRights({}, this.item, this.isEditable),
competences: [SANS_COMPETENCE, ...competences],
competences: [new RdDItemCompetence(SANS_COMPETENCE), ...competences],
categories: RdDItem.getCategories(this.item.type),
isAppreciable: Apprecier.isAppreciable(this.item)
}
@@ -118,7 +119,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
this.item.type == ITEM_TYPES.meditation ||
this.item.type == ITEM_TYPES.oeuvre) {
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) {
formData.competences = formData.competences.filter(it => it.isCompetenceArme())

View File

@@ -3,6 +3,7 @@ import { RdDItemCompetence } from "./item-competence.js";
import { ITEM_TYPES } from "./constants.js";
import { Misc } from "./misc.js";
import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js";
import { RdDItem } from "./item.js";
export const VOIES_DRACONIC = [
{ code: 'O', label: "Voie d'Oniros", short: 'Oniros', ordre: 'a' },
@@ -14,7 +15,7 @@ export const VOIES_DRACONIC = [
]
/* -------------------------------------------- */
export class RdDItemSort extends Item {
export class RdDItemSort extends RdDItem {
static preloadHandlebars() {
Handlebars.registerHelper('itemSort-codeDraconic', voie => RdDItemSort.getCode(voie))
Handlebars.registerHelper('itemSort-shortDraconic', voie => RdDItemSort.getShortVoie(voie))
@@ -40,6 +41,11 @@ export class RdDItemSort extends Item {
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) {
let tmr = TMRUtility.getTMR(coord)
const caseTMR = sort.system.caseTMR.toLowerCase();
@@ -62,7 +68,7 @@ export class RdDItemSort extends Item {
static diffReve(sort) { return RdDItemSort.toVar((sort.system.difficulte.match(/\-?(\d)+/) ? 'R' : 'R ') + sort.system.difficulte) }
static coutReve(sort) { return RdDItemSort.toVar((Number.isInteger(sort.system.ptreve || sort.system.ptreve.match(/(\d)+\+?/)) ? 'r' : 'r ') + sort.system.ptreve) }
static coutReve(sort) { return RdDItemSort.toVar((Number.isInteger(sort.system.ptreve) || sort.system.ptreve.match(/(\d)+\+?/) ? 'r' : 'r ') + sort.system.ptreve) }
static getDraconicsSort(competencesDraconic, sort) {
// se baser sur la voie du sort?
switch (Grammar.toLowerCaseNoAccent(sort.name)) {

View File

@@ -81,13 +81,13 @@ export const defaultItemImg = {
souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp",
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.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"
}
/* -------------------------------------------- */
export class RdDItem extends Item {
static get defaultIcon() {
return undefined;
}
@@ -185,6 +185,13 @@ export class RdDItem extends Item {
isCompetencePersonnage() { return this.type == ITEM_TYPES.competence }
isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature }
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 }
isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; }
isService() { return this.type == ITEM_TYPES.service }

View File

@@ -45,7 +45,7 @@ export class RdDItemArme extends RdDItem {
isParade() { return this.system.resistance > 0 && this.system.categorie_parade }
isBouclier() { return RdDItemArme.getCategorieParade(this).includes('bouclier') }
getCompetenceAction(main) {
switch (main) {
case ATTAQUE_TYPE.UNE_MAIN: return this.competence1Mains()
@@ -174,24 +174,30 @@ export class RdDItemArme extends RdDItem {
static defenseArmeParade(armeAttaque, armeParade) {
const defCategory = RdDItemArme.getCategorieParade(armeParade)
if (defCategory == 'boucliers') {
return 'norm'
switch (defCategory) {
case 'boucliers':
return 'norm'
case '':
return 'impossible'
}
if (armeAttaque?.system?.competence?.toLowerCase().match(/(fléau)/)) {
return ''
}
if (armeParade.system?.tir) {
return ''
if (RdDItemArme.$isFleau(armeAttaque)) {
return 'impossible'
}
const attCategory = RdDItemArme.getCategorieParade(armeAttaque)
switch (attCategory) {
case 'armes-naturelles': case 'sans-armes':
return defCategory == 'sans-armes' ? 'norm' : ''
case 'sans-armes':
case 'armes-naturelles':
return defCategory == attCategory ? 'norm' : 'impossible'
default:
return RdDItemArme.needParadeSignificative(armeAttaque, armeParade) ? 'sign' : 'norm'
}
}
static $isFleau(armeAttaque) {
return armeAttaque?.system?.competence?.toLowerCase().match(/(fléau)/);
}
/* -------------------------------------------- */
static needParadeSignificative(armeAttaque, armeParade) {
if (!armeAttaque || !armeParade) {

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: "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: "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 {
@@ -71,13 +71,13 @@ export class RdDItemBlessure extends RdDItem {
return 0
}
static async createBlessure(actor, gravite, localisation = '', attackerToken = undefined) {
const blessure = RdDItemBlessure.prepareBlessure(gravite, localisation, attackerToken);
const blessures = await actor.createEmbeddedDocuments('Item', [blessure])
static async createBlessure(actor, gravite, options = { localisation: '', origine: '', render: true }) {
const blessure = RdDItemBlessure.prepareBlessure(gravite, options);
const blessures = await actor.createEmbeddedDocuments('Item', [blessure], options)
return blessures[0]
}
static prepareBlessure(gravite, localisation, attackerToken) {
static prepareBlessure(gravite, options = { localisation: '', origine: '' }) {
const definition = RdDItemBlessure.getDefinition(gravite);
return {
name: definition.label,
@@ -85,9 +85,11 @@ export class RdDItemBlessure extends RdDItem {
img: definition.icon,
system: {
gravite: gravite,
vie: definition.vie,
endurance: definition.endurance,
difficulte: -gravite,
localisation: localisation,
origine: attackerToken?.name ?? ""
localisation: options.localisation,
origine: options.origine
}
}
}

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 { RdDSheetUtility } from "../rdd-sheet-utility.js"
import { RdDUtility } from "../rdd-utility.js"
@@ -11,33 +11,35 @@ import { RdDUtility } from "../rdd-utility.js"
const _SPACEHOLDER = { placeholder: true }
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,
action: (item, actor) => item.proposerVente()
}
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,
allowLimited: true,
action: (item, actor) => actor.vente(item)
}
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,
action: (item, actor) => item.postItemToChat()
}
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',
filter: it => Misc.toInt(it.system.quantite) > 1 && it.parent?.type != ACTOR_TYPES.commerce,
action: (item, actor) => RdDSheetUtility.splitItem(item, actor)
}
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)
}
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,
action: (item, actor) => RdDUtility.confirmActorItemDelete(item, actor)
}
@@ -48,53 +50,55 @@ const _EQUIPER = {
}
const _CUISINER = {
code: 'item-cuisiner', label: 'Cuisiner', icon: it => 'fa-solid fa-utensils',
code: 'item-cuisiner', label: 'Cuisiner',
img: 'systems/foundryvtt-reve-de-dragon/assets/actions/cuisine.svg',
filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0,
action: (item, actor) => actor.preparerNourriture(item)
}
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',
filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0,
action: (item, actor) => actor.mangerNourriture(item)
}
const _MANGER = {
code: 'item-manger', label: 'Manger', icon: it => 'fa-solid fa-utensils',
code: 'item-manger', label: 'Manger', icon: 'fa-solid fa-utensils',
filter: it => !(it.system.boisson),
action: (item, actor) => actor.mangerNourriture(item)
}
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',
filter: it => it.system.boisson,
action: (item, actor) => actor.mangerNourriture(item)
}
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',
action: (item, actor) => actor.fabriquerDecoctionHerbe(item)
}
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)
}
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',
action: (item, actor) => actor.actionLire(item)
}
const _REFOULER = {
code: 'item-refouler', label: 'Refouler', icon: it => 'fa-solid fa-burst',
code: 'item-refouler', label: 'Refouler', icon: 'fa-solid fa-burst',
filter: it => it.system.refoulement > 0,
action: (item, actor) => actor.actionRefoulement(item)
}
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',
filter: it => game.user.isGM && !it.system.isrituel,
action: (item, actor) => actor.addSortReserve(item)
}
export const COMMON_ACTIONS = [_EQUIPER]
export const DEFAULT_ACTIONS = [_ACHETER, _SPACEHOLDER, _SPLIT, _VENDRE, _MONTRER, _EDIT, _DELETE]
export const DEFAULT_ACTIONS = [_ACHETER, _SPLIT, _SPACEHOLDER, _VENDRE, _MONTRER, _EDIT, _DELETE]
export const ITEM_ACTIONS = {
faune: [_CUISINER, _MANGER_CRU],
@@ -119,11 +123,31 @@ export class ItemAction {
&& (!action.optionsFilter || action.optionsFilter(options))
}
static icon(action, item) {
if (action && action.icon) {
return action.icon(item)
static label(action, item) {
if (action.placeholder) {
return ""
}
return undefined
return ItemAction.getParam(action.label, item)
}
static img(action, item) {
if (action.placeholder) {
return ""
}
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
}
static getParam(p, item) {
return typeof (p) == 'function' ? p(item) : p
}
static async onActionItem(event, actor, options) {

View File

@@ -16,22 +16,18 @@ class Migration {
async migrate() { }
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);
if (actorItemUpdates.length > 0) {
console.log(
this.code,
`Applying updates on actor ${actor.name} items`,
actorItemUpdates
);
await actor.updateEmbeddedDocuments("Item", actorItemUpdates);
console.log(this.code, `Applying updates on actor ${actor.name} items`, actorItemUpdates);
return 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) {
console.log(this.code, "Applying updates on items", itemUpdates);
await Item.updateDocuments(itemUpdates);
console.log(this.code, "Applying updates on items", itemUpdates)
await Item.updateDocuments(itemUpdates)
}
}
}
@@ -58,13 +54,13 @@ class _1_5_34_migrationPngWebp {
//Migrate system png to webp
await Item.updateDocuments(itemsUpdates);
await Actor.updateDocuments(actorsUpdates);
game.actors.forEach(actor => {
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
actor.update({ "token.img": convertImgToWebp(actor.token.img) });
}
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
});
await Promise.all(game.actors
.filter(actor => actor.token?.img && actor.token.img.match(regexOldPngJpg))
.map(actor => actor.update({ "token.img": convertImgToWebp(actor.token.img) }))
)
await Promise.all(game.actors.map(actor =>
actor.updateEmbeddedDocuments('Item', prepareDocumentsImgUpdate(actor.items))
))
}
}
@@ -125,16 +121,15 @@ class _10_0_21_VehiculeStructureResistanceMax extends Migration {
get version() { return "10.0.21"; }
async migrate() {
await game.actors
.filter((actor) => actor.type == "vehicule")
.forEach(async (actor) => {
await actor.update({
await Promise.all(
game.actors.filter(actor => actor.type == "vehicule")
.map(actor => actor.update({
'system.etat.resistance.value': actor.system.resistance,
'system.etat.resistance.max': actor.system.resistance,
'system.etat.structure.value': 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"; }
migrateArmeTirLancer(it) {
let updates = foundry.utils.mergeObject({ _id: it.id }, this.getMapping(it).updates);
console.log(it.name, updates);
return updates;
const updates = foundry.utils.mergeObject({ _id: it.id }, this.getMapping(it).updates)
console.log(it.name, updates)
return updates
}
async migrate() {
@@ -693,6 +688,26 @@ class _13_0_21_AjoutAppreciation extends Migration {
}
}
class _13_0_22_PoidsDesMonnaies extends Migration {
get code() { return "poid-monnaies" }
get version() { return "13.0.22" }
async migrate() {
await this.applyItemsUpdates(items => items
.filter(it => it.type == ITEM_TYPES.monnaie)
.map(it => {
return { _id: it.id, 'system.encombrement': this.poids(it) }
})
)
}
poids(monnaie) {
if (monnaie.system.cout < 0.05) return 0.001
if (monnaie.system.cout < 0.5) return 0.002
if (monnaie.system.cout < 5) return 0.003
return 0.004
}
}
export class Migrations {
static getMigrations() {
return [
@@ -719,6 +734,7 @@ export class Migrations {
new _13_0_4_FixReveActuel(),
new _13_0_7_FixNiveauOeuvres(),
new _13_0_21_AjoutAppreciation(),
new _13_0_22_PoidsDesMonnaies(),
];
}

View File

@@ -134,12 +134,12 @@ export class Misc {
return itemsBy
}
static classifyFirst(items, classifier) {
static classifyFirst(items, classifier, classified = it => it) {
let itemsBy = {};
for (const item of items) {
const classification = classifier(item);
if (!itemsBy[classification]) {
itemsBy[classification] = item;
itemsBy[classification] = classified(item);
}
}
return itemsBy;
@@ -180,11 +180,15 @@ export class Misc {
return (a, b) => a + separator + b;
}
static connectedGMOrUser(ownerId = undefined) {
if (ownerId && game.user.id == ownerId) {
return ownerId;
static connectedUserOrGM(userId = undefined) {
if (userId && game.user.id == userId) {
return userId
}
return Misc.firstConnectedGM()?.id ?? game.user.id;
return Misc.firstConnectedGM()?.id
}
static connectedGMOrUser(userId = undefined) {
return Misc.connectedUserOrGM(userId) ?? game.user.id
}
static isRollModeHiddenToPlayer() {
@@ -200,10 +204,7 @@ export class Misc {
}
static firstConnectedGM() {
if (foundry.utils.isNewerVersion(game.release.version, '12.0')) {
return game.users.activeGM
}
return game.users.find(u => u.isGM && u.active);
return game.users.activeGM
}
static connectedGMs() {
@@ -224,7 +225,9 @@ export class Misc {
*/
static documentIfResponsible(document) {
if (Misc.isFirstConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isFirstOwnerPlayer(document))) {
return document
if (document.isOwner) {
return document
}
}
return undefined
}
@@ -233,16 +236,16 @@ export class Misc {
if (Misc.isOwnerPlayer(document)) {
return await action(document)
} else {
return await orElse(document)
return await orElse(document ?? { name: '<aucune sélection>' })
}
}
static isOwnerPlayer(document) {
return document.testUserPermission && document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
return document?.isOwner
}
static isFirstOwnerPlayer(document) {
if (!document.testUserPermission) {
if (!document?.isOwner) {
return false
}
return game.users.find(u => document.testUserPermission(u, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)) == game.user
@@ -252,15 +255,15 @@ export class Misc {
* @returns true pour un seul utilisateur: le premier GM connecté par ordre d'id
*/
static isFirstConnectedGM() {
return game.user == Misc.firstConnectedGM();
return game.users.activeGM != undefined && game.user == game.users.activeGM
}
static hasConnectedGM() {
return Misc.firstConnectedGM();
return game.users.activeGM
}
static firstConnectedGMId() {
return Misc.firstConnectedGM()?.id;
return game.users.activeGM?.id;
}
/* -------------------------------------------- */

View File

@@ -1,3 +1,4 @@
import { ChatUtility } from "../chat-utility.js"
import { ITEM_TYPES } from "../constants.js"
import { SANS_COMPETENCE } from "../item/base-items.js"
import { Misc } from "../misc.js"
@@ -103,7 +104,7 @@ export class Apprecier {
apprecier(callbacks = []) {
if (this.qualite <= 0) {
this.raisons.push(`la qualité ${this.qualite} est négative.`)
this.raisons.push(`la qualité ${this.qualite} est insuffisante.`)
}
if (this.qualite <= this.actor.getMoralTotal()) {
this.raisons.push(`la qualité de ${this.qualite} est inférieure au moral de ${this.actor.getMoralTotal()}.`)
@@ -149,7 +150,8 @@ export class Apprecier {
callbacks: [
async r => await this.onRollAppreciation(r),
...rollCallbacks
]
],
onRollDone: RollDialog.onRollDoneClose
})
}
@@ -166,7 +168,10 @@ export class Apprecier {
async rollMoral(moral = undefined) {
if (this.raisons.length > 0) {
ui.notifications.info('Pas de jet de moral:' + Misc.concat(this.raisons.map(r => `<br> - ${r}`)))
ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor),
content: 'Pas de jet de moral:' + Misc.concat(this.raisons.map(r => `<br> - ${r}`))
})
return
}

View File

@@ -70,7 +70,7 @@ export class RdDBonus {
dmgParticuliere: RdDBonus._dmgParticuliere(rollData),
dmgSurprise: rollData.opponent?.surprise?.dmg ?? 0,
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)),
dmgDiffLibre: ReglesOptionnelles.isUsing('degat-ajout-malus-libre') ? Math.abs(attaque.diff ?? 0) : 0
}

View File

@@ -61,7 +61,9 @@ export const CARACS = {
DEROBEE: 'derobee',
CHANCE_ACTUELLE: 'chance-actuelle',
REVE_ACTUEL: 'reve-actuel',
VIE: 'vie'
}
export const LIST_CARAC_PERSONNAGE = {
[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' },
@@ -166,10 +168,18 @@ export class RdDCarac {
const total = Object.values(carac ?? {}).filter(c => !c.derivee)
.map(it => parseInt(it.value))
.reduce(Misc.sum(), 0);
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0);
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0)
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) {
it.xpNext = RdDCarac.getCaracNextXp(it.value);
it.isLevelUp = (it.xp >= it.xpNext);
@@ -182,12 +192,16 @@ export class RdDCarac {
/* -------------------------------------------- */
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
return RdDCarac.getCaracXp(nextValue);
return RdDCarac.getCaracXp(value, nextValue)
}
static getCaracXp(targetValue) {
return RdDCarac.getCaracDerivee(targetValue)?.xp ?? 200;
static getCaracXp(from, to) {
return Array.from({ length: to - from },
(_, i) => from + i + 1)
.map(it => RdDCarac.getCaracDerivee(it)?.xp ?? 200)
.reduce(Misc.sum(), 0)
}
}

View File

@@ -19,6 +19,7 @@ import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs"
import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs";
import { RollBasicParts } from "./roll/roll-basic-parts.mjs";
import { Distance } from "./combat/distance.mjs";
/* -------------------------------------------- */
const premierRoundInit = [
@@ -62,6 +63,11 @@ export class RdDCombatManager extends Combat {
it.token.id == tokenId
)
}
static getRangInitiativeCombatant(actorId, tokenId) {
const combatant = RdDCombatManager.getCombatant(actorId, tokenId)
return combatant?.system.init?.rang
}
/* -------------------------------------------- */
async nextRound() {
await this.finDeRound();
@@ -153,7 +159,7 @@ export class RdDCombatManager extends Combat {
alias: combatant.token?.name,
sound: CONFIG.sounds.dice,
},
flavor: `${combatant.token?.name} a une initiatyive de ${init.value} : ${messageOptions.info}<br>`
flavor: `${combatant.token?.name} a une initiative de ${init.value} : ${messageOptions.info}<br>`
},
messageOptions);
init.roll.toMessage(messageData, { rollMode, create: true });
@@ -382,7 +388,7 @@ export class RdDCombat {
/* -------------------------------------------- */
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)) {
let attackerRoll = msg.attackerRoll;
let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined;
@@ -461,24 +467,10 @@ export class RdDCombat {
this.defenderId = this.defender.id
this.attackerTokenId = attackerTokenId
this.defenderTokenId = defenderTokenId
this.attackerToken = RdDCombat.$extractAttackerTokenData(attacker, attackerTokenId)
this.defenderToken = RdDCombat.$extractDefenderTokenData(defender, defenderTokenId, target)
this.attackerToken = Targets.getTokenData(attacker, attackerTokenId)
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) {
const chatMessage = ChatUtility.getChatMessage(event);
@@ -513,8 +505,8 @@ export class RdDCombat {
/* -------------------------------------------- */
attaqueChanceuse(attackerRoll) {
ui.notifications.info("L'attaque est rejouée grâce à la chance")
attackerRoll.essais.attaqueChance = true;
this.attaque(attackerRoll, attackerRoll.arme);
attackerRoll.essais.attaqueChance = true
this.attaque(attackerRoll, attackerRoll.arme)
}
/* -------------------------------------------- */
@@ -625,68 +617,27 @@ export class RdDCombat {
}
else {
const defenderToken = canvas.tokens.get(this.defenderTokenId)
const dist = this.distance(_token, defenderToken)
const isVisible = this.isVisible(_token, defenderToken)
const portee = this._ajustementPortee(dist, rollData.arme)
const taille = this._ajustementTaille(this.defender)
const activite = this._ajustementMouvement(this.defender)
const total = [portee, taille, activite].map(it => it.diff).filter(d => !Number.isNaN(d)).reduce(Misc.sum(), 0)
ChatMessage.create({
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.hbs', {
const info = foundry.utils.mergeObject(
{
rollData: rollData,
attacker: _token,
isVisible: isVisible,
defender: defenderToken,
distance: dist,
portee: portee,
taille: taille,
activite: activite,
total: total
}),
},
Distance.ajustements(_token, defenderToken, { arme: rollData.arme, main: rollData.competence.system.categorie })
)
ChatMessage.create({
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.hbs', info),
whisper: ChatUtility.getGMs()
})
}
}
}
isVisible(token, defenderToken) {
return canvas.effects.visibility.testVisibility(defenderToken.center, { object: token })
}
distance(token, defenderToken) {
return Number(canvas.grid.measureDistances([{ ray: new Ray(token.center, defenderToken.center) }], { gridSpaces: false })).toFixed(1);
}
_ajustementPortee(dist, arme) {
if (dist <= arme.system.portee_courte) return { msg: "courte", diff: 0 };
if (dist <= arme.system.portee_moyenne) return { msg: "moyenne", diff: -3 };
if (dist <= arme.system.portee_extreme) return { msg: "extrême", diff: -5 };
return { msg: "inatteignable", diff: -10 };
}
_ajustementTaille(actor) {
if (actor.isVehicule()) return { msg: "véhicule", diff: 0 }
const taille = actor.getCaracByName('TAILLE')?.value ?? 1;
if (taille <= 1) return { msg: "souris", diff: -8 };
if (taille <= 3) return { msg: "chat", diff: -4 };
if (taille <= 5) return { msg: "chien", diff: -2 };
if (taille <= 15) return { msg: "humanoïde", diff: 0 };
if (taille <= 20) return { msg: "ogre", diff: 2 };
return { msg: "gigantesque", diff: 4 };
}
_ajustementMouvement(defender) {
if (defender.getSurprise(true) != '') return { msg: "immobile (surprise)", diff: 0 };
if (game.combat?.combatants.find(it => it.actorId == defender.id)) return { msg: "en mouvement (combat)", diff: -4 };
return { msg: "à déterminer (0 immobile, -3 actif, -4 en mouvement, -5 en zig-zag)", diff: -3 };
}
async attaqueV2() {
async attaqueV2(options = undefined) {
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
return
}
await this.doRollAttaque({
const rollData = {
ids: {
actorId: this.attackerId,
actorTokenId: this.attackerTokenId,
@@ -694,12 +645,22 @@ export class RdDCombat {
opponentTokenId: this.defenderTokenId,
},
type: { allowed: ['attaque'], current: 'attaque' },
selected: {},
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 = []) {
// TODO V2 await this.proposerAjustementTirLancer(rollData)
return await RollDialog.create(rollData, {
onRollDone: RollDialog.onRollDoneClose,
callbacks: [
@@ -740,7 +701,7 @@ export class RdDCombat {
}
_socketSendMessageDefenseV2(paramChatDefense) {
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_defense_v2", data: {paramChatDefense} })
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_defense_v2", data: { paramChatDefense } })
}
static async onMsgDefenseV2(msg) {
@@ -762,7 +723,7 @@ export class RdDCombat {
const choixDefense = await ChatMessage.create({
// 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(),
whisper: ChatUtility.getOwners(this.defender),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', defenseData)
@@ -777,12 +738,14 @@ export class RdDCombat {
}
/* -------------------------------------------- */
async attaque(competence, arme) {
async attaque(competence, arme, main) {
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
return
}
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) {
RdDEmpoignade.onAttaqueEmpoignade(this.attacker, this.defender)
@@ -791,7 +754,7 @@ export class RdDCombat {
RdDEmpoignade.checkEmpoignadeEnCours(this.attacker)
let rollData = this._prepareAttaque(competence, arme)
console.log("RdDCombat.attaque >>>", rollData);
console.log("RdDCombat.attaque >>>", rollData)
if (arme) {
this.attacker.verifierForceMin(arme);
}
@@ -816,7 +779,7 @@ export class RdDCombat {
/* -------------------------------------------- */
_prepareAttaque(competence, arme) {
let rollData = {
mode: ROLL_TYPE_ATTAQUE,
mode: 'attaque',
alias: this.attacker?.getAlias(),
passeArme: foundry.utils.randomID(16),
mortalite: arme?.system.mortalite,
@@ -966,7 +929,7 @@ export class RdDCombat {
async _chatMessageDefense(paramDemandeDefense, defenderRoll) {
const choixDefense = await ChatMessage.create({
// 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(),
whisper: ChatUtility.getOwners(this.defender),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense-v1.hbs', paramDemandeDefense),
@@ -1084,7 +1047,7 @@ export class RdDCombat {
}
async defenseV2(attackerRoll, callbacks = []) {
// this._prepareParade(attackerRoll, arme, competence);
await this.doRollDefense({
ids: {
actorId: this.defender.id,
@@ -1419,6 +1382,7 @@ export class RdDCombat {
return
}
const alias = token?.name ?? actor.getAlias();
const blessuresGraves = actor.countBlessures(it => it.isGrave());
const formData = {
combatId: combat._id,
alias: alias,
@@ -1429,7 +1393,7 @@ export class RdDCombat {
actorId: actor.id,
actor: actor,
tokenId: token.id,
isGrave: actor.countBlessures(it => it.isGrave()) > 0,
blessuresGraves: blessuresGraves,
isCritique: actor.countBlessures(it => it.isCritique()) > 0
}
await ChatMessage.create({

View File

@@ -116,6 +116,7 @@ export class RdDCommands {
this.registerCommand({
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:
<br>/xp carac 12 15: coût pour passer de 12 15
<br>/xp carac 15: coût pour atteindre 15 (depuis 14)`
});
@@ -440,13 +441,18 @@ export class RdDCommands {
/* -------------------------------------------- */
getCoutXpCarac(msg, params) {
if (params && params.length == 1) {
let to = Number(params[0]);
return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to)}`);
}
else {
return false;
if (params) {
if (params.length == 1) {
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)}`);
}
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() {

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) {
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) {
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
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, attacker, defender, adjust);
}
static async $ajustementEmpoignade(empoignade, attacker, defender, adjust) {
const empId = empoignade?.system.empoignadeid ?? foundry.utils.randomID(16);
const empFin = (empoignade?.system.pointsemp ?? 0) + adjust
@@ -73,30 +80,32 @@ export class RdDEmpoignade {
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee")
});
})
$(html).on("click", '.defense-empoignade-esquive', event => {
const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee")
});
})
$(html).on("click", '.empoignade-poursuivre', event => {
let attackerId = event.currentTarget.attributes['data-attackerId'].value
let defenderId = event.currentTarget.attributes['data-defenderId'].value
RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId))
});
const attacker = RdDEmpoignade.getActorFromEventTag(event, 'data-attackerId')
const defender = RdDEmpoignade.getActorFromEventTag(event, 'data-defenderId')
if (attacker && defender) {
RdDEmpoignade.onAttaqueEmpoignadeValidee(attacker, defender)
}
})
$(html).on("click", '.empoignade-entrainer-sol', event => {
const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
RdDEmpoignade.entrainerAuSol(rollData)
ChatUtility.remover(chatMessage)()
});
})
$(html).on("click", '.empoignade-projeter-sol', event => {
const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
RdDEmpoignade.projeterAuSol(rollData)
ChatUtility.remover(chatMessage)()
});
})
$(html).on("change", '.empoignade-perte-endurance', event => {
const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
@@ -104,7 +113,11 @@ export class RdDEmpoignade {
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
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?
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.")
return true;
return true
}
return false;
return false
}
/* -------------------------------------------- */
static $storeRollEmpoignade(msg, rollData) {
RdDEmpoignade.$reduceActorToIds(rollData);
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData);
ChatUtility.setMessageData(msg, "empoignade-roll-data", RdDEmpoignade.$reduceActorToIds(rollData))
}
static $reduceActorToIds(rollData) {
rollData.attacker = { id: rollData.attacker.id };
rollData.defender = { id: rollData.defender.id };
rollData.attacker = { id: rollData.attacker.id }
rollData.defender = { id: rollData.defender.id }
return rollData
}
/* -------------------------------------------- */
static $readRollEmpoignade(msg) {
const rollData = ChatUtility.getMessageData(msg, 'empoignade-roll-data');
RdDEmpoignade.$replaceIdsWithActors(rollData);
return rollData
return RdDEmpoignade.$replaceIdsWithActors(ChatUtility.getMessageData(msg, 'empoignade-roll-data'))
}
static $replaceIdsWithActors(rollData) {
rollData.attacker = game.actors.get(rollData.attacker.id);
rollData.defender = game.actors.get(rollData.defender.id);
rollData.attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
rollData.defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
return rollData
}
/* -------------------------------------------- */
@@ -147,19 +159,21 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
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) {
let emp = attacker.itemTypes[ITEM_TYPES.empoignade].find(it =>
(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 (attacker && defender) {
const empoignade = attacker.itemTypes[ITEM_TYPES.empoignade].find(it =>
(it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) ||
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
)
if (empoignade) {
return foundry.utils.duplicate(empoignade)
}
}
return undefined;
return undefined
}
/* -------------------------------------------- */
@@ -180,10 +194,14 @@ export class RdDEmpoignade {
}
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) {
ui.notifications.warn(`Vous n'êtes pas autorisé à choisir l'action de ${acting.name}`)
return false;
return false
}
return true
}
@@ -205,7 +223,6 @@ export class RdDEmpoignade {
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
const isNouvelle = empoignade == undefined;
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
//console.log("W.", empoignade, defender.hasArmeeMeleeEquipee())
if ((isNouvelle || empoignade.system.pointsemp == 0) && defender.hasArmeeMeleeEquipee()) {
ChatUtility.createChatWithRollMode(
{
@@ -264,30 +281,34 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static async onAttaqueEmpoignadeFromItem(empoignade) {
let attacker = game.actors.get(empoignade.system.empoigneurid)
let defender = game.actors.get(empoignade.system.empoigneid)
await this.onAttaqueEmpoignadeValidee(attacker, defender)
const attacker = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneurid)
const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
if (attacker && defender) {
await this.onAttaqueEmpoignadeValidee(attacker, defender)
}
}
static async onImmobilisation(attacker, empoignade) {
const defender = game.actors.get(empoignade.system.empoigneid)
const empDefenseur = defender.itemTypes[ITEM_TYPES.empoignade]
.find(it => it.system.empoignadeid == empoignade.system.empoignadeid);
await defender.updateEmbeddedDocuments('Item', [{
_id: empDefenseur.id,
'system.immobilise': true
}])
const rollData = {
mode: "immobilise",
empoignade, attacker, defender,
isEmpoignade: true,
competence: attacker.getCompetenceCorpsACorps()
const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
if (defender) {
const empDefenseur = defender.itemTypes[ITEM_TYPES.empoignade]
.find(it => it.system.empoignadeid == empoignade.system.empoignadeid);
await defender.updateEmbeddedDocuments('Item', [{
_id: empDefenseur.id,
'system.immobilise': true
}])
const rollData = {
mode: "immobilise",
empoignade, attacker, defender,
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 +325,30 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static async $onRollEmpoignade(rollData, isNouvelle = false) {
let attacker = game.actors.get(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id)
const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.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) {
RdDEmpoignade.$createEtatEmpoignade(rollData.empoignade)
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);
}
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") {
let attacker = game.actors.get(attackerRoll.attacker.id)
let defender = game.actors.get(attackerRoll.defender.id)
const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) {
return
}
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
if (!empoignade) {
@@ -367,7 +388,7 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static async $onRollContrerLiberer(rollData) {
let empoignade = rollData.empoignade
const empoignade = rollData.empoignade
if (rollData.mode == "contrer-empoigner" && !rollData.rolled.isSuccess) {
empoignade.system.pointsemp++
@@ -389,35 +410,40 @@ export class RdDEmpoignade {
static async $createEtatEmpoignade(empoignade) {
console.log("CREATE Empoignade", empoignade)
let defender = game.actors.get(empoignade.system.empoigneid)
let attacker = game.actors.get(empoignade.system.empoigneurid)
const attacker = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneurid)
const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
// Creer l'empoignade sur attaquant/defenseur
await attacker.creerObjetParMJ(empoignade)
await defender.creerObjetParMJ(empoignade)
if (attacker && defender) {
// Creer l'empoignade sur attaquant et defenseur
await attacker.creerObjetParMJ(empoignade)
await defender.creerObjetParMJ(empoignade)
}
}
/* -------------------------------------------- */
static async $updateEtatEmpoignade(empoignade, attacker, defender) {
const belligerants = [
attacker ?? game.actors.get(empoignade.system.empoigneurid),
defender ?? game.actors.get(empoignade.system.empoigneid)]
const removeEmp = empoignade.system.pointsemp == 0
attacker = attacker ?? RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneurid)
defender = defender ?? RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
if (removeEmp) {
const emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
return await attacker.deleteEmbeddedDocuments('Item', [emp.id])
}
else {
await Promise.all(
belligerants.map(async belligerant => {
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
}])
}))
if (attacker && defender) {
const belligerants = [attacker, defender]
const removeEmp = empoignade.system.pointsemp == 0
if (removeEmp) {
const emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
return await attacker.deleteEmbeddedDocuments('Item', [emp.id])
}
else {
await Promise.all(
belligerants.map(async belligerant => {
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 +451,21 @@ export class RdDEmpoignade {
static async $deleteEmpoignade(empoignade) {
console.log("DELETE Empoignade", empoignade)
const defender = game.actors.get(empoignade.system.empoigneid)
const emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
await defender.deleteEmbeddedDocuments('Item', [emp.id])
const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
if (defender) {
const emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
await defender.deleteEmbeddedDocuments('Item', [emp.id])
}
}
/* -------------------------------------------- */
static async entrainerAuSol(rollData) {
let attacker = game.actors.get(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id)
const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return
}
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
const empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
empoignade.system.ausol = true
await this.$updateEtatEmpoignade(empoignade)
@@ -445,14 +473,14 @@ export class RdDEmpoignade {
await attacker.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);
}
/* -------------------------------------------- */
static async projeterAuSol(rollData) {
let attacker = game.actors.get(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id)
const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return
}
@@ -467,8 +495,8 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static async perteEndurance(rollData, perteMode) {
let attacker = game.actors.get(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id)
const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (perteMode == "none" || !RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return
}
@@ -501,11 +529,11 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static async deleteLinkedEmpoignade(actorId, empoignade) {
let actorDeleteId = (actorId == empoignade.system.empoigneurid) ? empoignade.system.empoigneid : empoignade.system.empoigneurid
let actor = game.actors.get(actorDeleteId)
let emp = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
if (emp) {
await actor.deleteEmbeddedDocuments('Item', [emp.id])
const actorDeleteId = (actorId == empoignade.system.empoigneurid) ? empoignade.system.empoigneid : empoignade.system.empoigneurid
const actor = RdDEmpoignade.getActorEmpoignade(actorDeleteId)
const empoignadeOpposant = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
if (actor && empoignadeOpposant) {
await actor.deleteEmbeddedDocuments('Item', [empoignadeOpposant.id])
}
}

View File

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

View File

@@ -1,5 +1,7 @@
import { SYSTEM_RDD, SYSTEM_SOCKET_ID, RDD_CONFIG, ITEM_TYPES } from "./constants.js"
const RDD_INFO_MESSAGE_URL = "https://gitea.scriptarium.org/Scriptarium/foundryvtt-reve-de-dragon/raw/branch/v13/info-message.html"
import { RdDUtility } from "./rdd-utility.js"
import { TMRUtility } from "./tmr-utility.js"
import { TMRRencontres } from "./tmr-rencontres.js"
@@ -90,6 +92,8 @@ import { Migrations } from './migrations.js'
import RollDialog from "./roll/roll-dialog.mjs"
import ChatRollResult from "./roll/chat-roll-result.mjs"
import ExportPdf from "./actor/export-pdf/export-pdf.mjs"
import { DialogFlushByDate } from "./chat/dialog-flush-by-date.mjs"
import { Remote } from "./remote.mjs"
/**
* RdD system
@@ -181,6 +185,7 @@ export class SystemReveDeDragon {
game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => {
console.log(">>>>> MSG RECV", sockmsg)
try {
Remote.onSocketMessage(sockmsg)
RdDUtility.onSocketMessage(sockmsg)
RdDCombat.onSocketMessage(sockmsg)
ChatUtility.onSocketMessage(sockmsg)
@@ -247,11 +252,11 @@ export class SystemReveDeDragon {
ITEM_TYPES.jeu,
ITEM_TYPES.race,
ITEM_TYPES.recettecuisine,
ITEM_TYPES.oeuvre,
ITEM_TYPES.oeuvre,
ITEM_TYPES.meditation,
ITEM_TYPES.queue,
ITEM_TYPES.ombre,
ITEM_TYPES.souffle,
ITEM_TYPES.ombre,
ITEM_TYPES.souffle,
ITEM_TYPES.tete,
ITEM_TYPES.casetmr,
ITEM_TYPES.sort,
@@ -300,6 +305,7 @@ export class SystemReveDeDragon {
ExportPdf.init()
RollDialog.init()
ChatRollResult.init()
DialogFlushByDate.init()
}
initSettings() {
@@ -352,6 +358,15 @@ export class SystemReveDeDragon {
},
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() {
@@ -410,10 +425,33 @@ 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>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div>
` })
// 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)
.then(response => response.text())
.then(html => {
console.log("Fetched welcome message:", html);
ChatMessage.create({
user: game.user.id,
whisper: [game.user.id],
content: html
});
})
.catch(error => {
console.error("Error fetching welcome message:", error);
});
}
}
roll(rollData, actors, options){
roll(rollData, actors, options) {
RollDialog.create(rollData, actors, options)
}
}

View File

@@ -178,7 +178,7 @@ export class RdDPossessionV2 {
static async onRollDefense(defense) {
if (defense.rolled.isEchec) {
await RdDPossessionV2.addPointPossession(defense.opponent.actor, defense.active.actor)
await RdDPossessionV2.addPointPossession(defense.opponent, defense.active)
}
RdDPossessionV2.resetPossession(defense)
}

View File

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

View File

@@ -4,7 +4,7 @@ import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemSort } from "./item-sort.js";
import { Misc } from "./misc.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 { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { Grammar } from "./grammar.js";
@@ -65,7 +65,7 @@ export class RdDRoll extends Dialog {
}
// Mini patch :Ajout du rêve actuel
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 });

View File

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

View File

@@ -13,10 +13,10 @@ import { Draconique } from "./tmr/draconique.js";
import { HtmlUtility } from "./html-utility.js";
import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { RdDDice } from "./rdd-dice.js";
import { STATUSES } from "./settings/status-effects.js";
import { RdDRencontre } from "./item/rencontre.js";
import { ITEM_TYPES } from "./constants.js";
import { Misc } from "./misc.js";
import { CARACS } from "./rdd-carac.js";
const TMR_DISPLAY_SIZE = {
code: 'tmr-display-size',
@@ -126,7 +126,7 @@ export class RdDTMRDialog extends Dialog {
HtmlUtility.showControlWhen(this.html.find(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getCoordActor()));
this.html.find('form.tmr-dialog *').click(event => {
if (this.subdialog?.rendered){
if (this.subdialog?.rendered) {
this.subdialog?.bringToFront()
}
})
@@ -187,7 +187,9 @@ export class RdDTMRDialog extends Dialog {
async restoreTMRAfterAction() {
this.subdialog = undefined
await this.maximize()
this.bringToFront()
if (this.rendered) {
this.bringToFront()
}
}
forceTMRContinueAction() {
@@ -348,10 +350,10 @@ export class RdDTMRDialog extends Dialog {
return false
}
this.descenteTMR = true
await await this.actor.quitterTMR(message, this.viewOnly, this.cumulFatigue)
this.pixiTMR.close();
await await this.actor?.quitterTMR(message, this.viewOnly, this.cumulFatigue)
this.pixiTMR?.close()
this.pixiTMR = undefined
await super.close();
await super.close()
return true
}
@@ -684,12 +686,12 @@ export class RdDTMRDialog extends Dialog {
tmr: tmr,
canClose: false,
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' }
}
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined,
rollData.competence.system.defaut_carac = 'reve-actuel';
await this._rollMaitriseCaseHumide(rollData);
rollData.double = EffetsDraconiques.isDoubleResistanceFleuve(this.actor) ? true : undefined
rollData.competence.system.defaut_carac = CARACS.REVE_ACTUEL
await this._rollMaitriseCaseHumide(rollData)
}
}
@@ -809,30 +811,30 @@ export class RdDTMRDialog extends Dialog {
tmr: tmr,
canClose: options.canClose ?? false,
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 }
};
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) {
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({
whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData)
});
})
if (rollData.rolled.isEchec) {
options.onConqueteEchec(rollData, options.effetDraconique);
options.onConqueteEchec(rollData, options.effetDraconique)
}
else {
await options.onConqueteReussie(rollData, options.effetDraconique);
this.updateTokens();
await options.onConqueteReussie(rollData, options.effetDraconique)
this.updateTokens()
}
}
@@ -966,7 +968,7 @@ export class RdDTMRDialog extends Dialog {
const targetOddq = this.pixiTMR.computeEventOddq(event)
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");
return
}

View File

@@ -348,7 +348,8 @@ export class RdDUtility {
// Items
Handlebars.registerHelper('rarete-getChamp', (rarete, field) => RdDRaretes.getChamp(rarete, field));
Handlebars.registerHelper('item-action-applies', (action, item, options) => ItemAction.applies(action, item, options))
Handlebars.registerHelper('item-action-icon', (action, item) => ItemAction.icon(action, item))
Handlebars.registerHelper('item-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-name', (item) => item.nameDisplay)
// TMRs

53
module/remote.mjs Normal file
View File

@@ -0,0 +1,53 @@
import { RdDBaseActor } from "./actor/base-actor.js";
import { SYSTEM_SOCKET_ID } from "./constants.js";
import { Misc } from "./misc.js";
export class Remote {
static onSocketMessage(sockmsg) {
switch (sockmsg.msg) {
case "msg_remote_call":
return Remote.onRemoteCall(sockmsg.userId, sockmsg.data);
}
}
static remoteCall({ userId = undefined, documentName, documentId, tokenId = undefined, method, args }) {
const callData = { documentName, documentId, tokenId, method, args }
const sendToUserId = Misc.connectedUserOrGM(userId)
if (sendToUserId == undefined) {
ui.notifications.error(`Impossible d'envoyer un message à ${userId}`)
}
else if (sendToUserId == game.user.id) {
Remote.onRemoteCall(game.user.id, callData)
return false
}
else {
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_remote_call", userId: sendToUserId, data: callData })
return true
}
}
static onRemoteCall(userId, callData) {
if (userId == game.user.id) {
// Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
const doc = Remote.getDoc(callData)
if (doc) {
const args = callData.args;
const method = callData.method;
console.info(`Remote.onRemoteCall: ${callData.documentName} ${callData.documentId}, appel de ${method}(`, ...args, ')')
doc[method](...args)
}
}
}
static getDoc(callData) {
switch (callData.documentName) {
case 'Actor': return RdDBaseActor.getRealActor(callData.documentId, callData.tokenId)
case 'Item': return game.items.get(callData.documentId)
case 'RollTable': return game.tables.get(callData.documentId)
case 'ChatMessage': return game.messages.get(callData.documentId)
}
return undefined
}
}

View File

@@ -16,6 +16,7 @@ import { Misc } from "../misc.js"
import { RollBasicParts } from "./roll-basic-parts.mjs"
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs"
import { Apprecier } from "../moral/apprecier.mjs"
import { Remote } from "../remote.mjs"
export default class ChatRollResult {
static init() {
@@ -49,9 +50,8 @@ export default class ChatRollResult {
roll.active.actor,
roll.current?.rollmode?.key
)
const save = RollDialog.saveParts(roll, impacts)
await this.saveChatMessageRoll(chatMessage, save)
await this.saveChatMessageRoll(chatMessage, roll, impacts)
return chatMessage
}
@@ -162,59 +162,72 @@ export default class ChatRollResult {
return undefined
}
async saveChatMessageRoll(chatMessage, savedRoll) {
await ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll)
}
loadChatMessageRoll(chatMessage) {
return ChatUtility.getMessageData(chatMessage, 'rollData')
getActiveActor(roll) {
return roll.active?.actor ?? (roll.ids?.actorId ? game.actors.get(roll.ids.actorId) : undefined)
}
async updateChatMessage(chatMessage, savedRoll) {
RollDialog.loadRollData(savedRoll)
savedRoll.dmg = savedRoll.current.attaque?.dmg
await this.saveChatMessageRoll(chatMessage, savedRoll)
const copy = foundry.utils.duplicate(savedRoll)
RollDialog.loadRollData(copy)
savedRoll.dmg = copy.current.attaque?.dmg
this.prepareDisplay(copy)
chatMessage.update({ content: await this.buildRollHtml(copy) })
chatMessage.render(true)
this.prepareDisplay(savedRoll)
const content = await this.buildRollHtml(savedRoll)
Remote.remoteCall({
userId: chatMessage.author.id,
documentName: chatMessage.documentName,
documentId: chatMessage.id,
method: 'update',
args: [{ content: content }, { render: true }]
})
}
async saveChatMessageRoll(chatMessage, roll, impacts = undefined) {
const save = RollDialog.saveParts(roll, impacts)
await ChatUtility.setMessageData(chatMessage, 'rollData', save)
}
loadChatMessageRoll(chatMessage) {
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
RollBasicParts.restore(savedRoll)
return savedRoll
}
onClickAppelChance(event) {
event.preventDefault()
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
const actor = game.actors.get(savedRoll.ids.actorId)
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, it => it.rollAppelChance(
() => this.onAppelChanceSuccess(savedRoll, chatMessage),
() => this.onAppelChanceEchec(savedRoll, chatMessage))
)
}
async onAppelChanceSuccess(savedRoll, chatMessage) {
const reRoll = foundry.utils.duplicate(savedRoll)
console.log('onAppelChanceSuccess savedRoll', savedRoll)
reRoll.type.retry = true
await this.updateChatMessage(chatMessage, reRoll)
const callbacks = [ChatUtility.remover(chatMessage)]
async onAppelChanceSuccess(roll, chatMessage) {
roll.type.retry = true
await this.updateChatMessage(chatMessage, roll)
// TODO: annuler les effets
switch (reRoll.type.current) {
const callbacks = [ChatUtility.remover(chatMessage)]
// TODO: annuler les effets...
switch (roll.type.current) {
case ROLL_TYPE_DEFENSE:
this.getCombat(reRoll)?.doRollDefense(reRoll, callbacks)
this.getCombat(roll)?.doRollDefense(roll, callbacks)
break
case ROLL_TYPE_ATTAQUE:
this.getCombat(reRoll)?.doRollAttaque(reRoll, callbacks)
this.getCombat(roll)?.doRollAttaque(roll, callbacks)
break
default: {
await RollDialog.create(reRoll, { onRollDone: RollDialog.onRollDoneClose, callbacks })
await RollDialog.create(roll, { onRollDone: RollDialog.onRollDoneClose, callbacks })
}
}
}
async onAppelChanceEchec(savedRoll, chatMessage) {
savedRoll.type.retry = true
await this.updateChatMessage(chatMessage, savedRoll)
async onAppelChanceEchec(roll, chatMessage) {
roll.type.retry = true
await this.updateChatMessage(chatMessage, roll)
}
onClickAppelDestinee(event) {
@@ -222,49 +235,53 @@ export default class ChatRollResult {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
const actor = game.actors.get(savedRoll.ids.actorId)
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, it => it.appelDestinee(async () => {
const reRoll = foundry.utils.duplicate(savedRoll)
reRoll.type.retry = true
RdDResolutionTable.significativeRequise(reRoll.rolled)
await this.updateChatMessage(chatMessage, reRoll)
savedRoll.type.retry = true
RdDResolutionTable.significativeRequise(savedRoll.rolled)
await this.updateChatMessage(chatMessage, savedRoll)
}))
}
async onClickDefense(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
RollBasicParts.restore(savedRoll)
const attackerRoll = savedRoll.attackerRoll
RollDialog.loadRollData(attackerRoll)
this.getCombat(attackerRoll)?.defenseV2(attackerRoll,
[ChatUtility.remover(chatMessage)]
)
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, it => {
const attackerRoll = savedRoll.attackerRoll
RollDialog.loadRollData(attackerRoll)
this.getCombat(attackerRoll)?.defenseV2(attackerRoll,
[ChatUtility.remover(chatMessage)]
)
})
}
async onClickDefensePossession(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
await RdDPossessionV2.rollDefensePossession(savedRoll, chatMessage)
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, it => RdDPossessionV2.rollDefensePossession(savedRoll, chatMessage))
}
async onClickMarquerPointPossession(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
RollBasicParts.restore(savedRoll)
await RdDPossessionV2.onMarquerPointPossession(savedRoll)
ChatUtility.remover(chatMessage)()
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, async it => {
await RdDPossessionV2.onMarquerPointPossession(savedRoll)
ChatUtility.remover(chatMessage)()
})
}
async onClickEncaissement(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const isMessageDemande = ChatUtility.getMessageData(chatMessage, 'demande-defense')
const savedRoll = this.loadChatMessageRoll(chatMessage)
const attaque = savedRoll.attackerRoll
const defenderToken = savedRoll.ids.actorTokenId ? canvas.tokens.get(savedRoll.ids.actorTokenId) : undefined
const defender = defenderToken?.actor ?? game.actors.get(savedRoll.ids.actorId)
Misc.doIfOwner(defender, async defender => {
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, async defender => {
const defenderToken = savedRoll.active.token
const attaque = savedRoll.attackerRoll
const attackerToken = savedRoll.ids.opponentTokenId ? canvas.tokens.get(savedRoll.ids.opponentTokenId) : undefined
const attacker = attackerToken?.actor ?? game.actors.get(savedRoll.ids.opponentId)
switch (attaque.dmg.mortalite) {
@@ -290,9 +307,8 @@ export default class ChatRollResult {
async onClickRecul(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
// TODO: gestion sur token non liés?
const defender = game.actors.get(savedRoll.ids.actorId)
Misc.doIfOwner(defender, async defender => {
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, async defender => {
const attacker = game.actors.get(savedRoll.ids.opponentId)
savedRoll.done.recul = await defender.encaisserRecul(attacker.getForce(), savedRoll.attackerRoll.dmg.dmgArme)
await this.updateChatMessage(chatMessage, savedRoll)
@@ -303,42 +319,54 @@ export default class ChatRollResult {
const choix = event.currentTarget.attributes['data-particuliere'].value
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
savedRoll.particuliere = choix
savedRoll.particulieres = [RDD_CONFIG.particuliere[choix]]
await this.updateChatMessage(chatMessage, savedRoll)
await this.getCombat(savedRoll)?.onAttaqueV2(savedRoll)
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, async it => {
savedRoll.particuliere = choix
savedRoll.particulieres = [RDD_CONFIG.particuliere[choix]]
await this.updateChatMessage(chatMessage, savedRoll)
await this.getCombat(savedRoll)?.onAttaqueV2(savedRoll)
})
}
async onClickFaireGouter(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
if (!savedRoll.type.retry) {
savedRoll.type.retry = true
await this.updateChatMessage(chatMessage, savedRoll)
}
await new RollTypeCuisine().onFaireGouter(savedRoll)
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, async it => {
if (!savedRoll.type.retry) {
savedRoll.type.retry = true
await this.updateChatMessage(chatMessage, savedRoll)
}
await new RollTypeCuisine().onFaireGouter(savedRoll)
})
}
async onClickApprecier(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
await Apprecier.onClickApprecier(savedRoll)
Apprecier.onClickApprecier(savedRoll)
}
async onClickMonteeTMR(event, mode) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
if (await new RollTypeMeditation().onMonteeTMR(savedRoll, mode)) {
savedRoll.done.meditation = true
await this.updateChatMessage(chatMessage, savedRoll)
}
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, async it => {
if (await new RollTypeMeditation().onMonteeTMR(savedRoll, mode)) {
savedRoll.done.meditation = true
await this.updateChatMessage(chatMessage, savedRoll)
}
})
}
async onClickTirerMaladresse(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const typeMaladresse = event.currentTarget.attributes['data-maladresse'].value
const savedRoll = this.loadChatMessageRoll(chatMessage)
savedRoll.maladresse = await RdDRollTables.getMaladresse({ arme: typeMaladresse == 'avec-arme', toChat: false })
savedRoll.type.retry = true
await this.updateChatMessage(chatMessage, savedRoll)
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, async it => {
savedRoll.maladresse = await RdDRollTables.getMaladresse({ arme: typeMaladresse == 'avec-arme', toChat: false })
savedRoll.type.retry = true
await this.updateChatMessage(chatMessage, savedRoll)
})
}
}

View File

@@ -13,8 +13,7 @@ export const ROLL_TYPE_TACHE = 'tache'
export const ATTAQUE_ROLL_TYPES = [ROLL_TYPE_ATTAQUE]
export const COMBAT_ROLL_TYPES = [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE]
export const DEMIREVE_ROLL_TYPES = [ROLL_TYPE_SORT]
export const DEFAULT_ROLL_TYPES = [ROLL_TYPE_COMP, ROLL_TYPE_ATTAQUE, ROLL_TYPE_TACHE, ROLL_TYPE_MEDITATION, ROLL_TYPE_CUISINE, ROLL_TYPE_OEUVRE, ROLL_TYPE_JEU]
export const DEFAULT_ROLL_TYPES = [ROLL_TYPE_COMP, ROLL_TYPE_TACHE, ROLL_TYPE_MEDITATION, ROLL_TYPE_CUISINE, ROLL_TYPE_OEUVRE, ROLL_TYPE_JEU]
export const DIFF = {
LIBRE: 'libre',

View File

@@ -50,7 +50,7 @@ export class RollDialogAdapter {
rolled.factorHtml = Misc.getFractionOneN(rollData.current.sign.diviseur)
if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) {
rolled.niveauNecessaire = RdDResolutionTable.findNiveauNecessaire(rolled.caracValue, rolled.roll)
rolled.ajustementNecessaire = rolled.niveauNecessaire - diff
rolled.ajustementNecessaire = rolled.niveauNecessaire - rolled.finalLevel
}
return rolled
}
@@ -92,10 +92,6 @@ export class RollDialogAdapter {
if (rollData.current[PART_APPELMORAL]?.checked) {
rollData.use.moral = true
}
if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) {
rolled.niveauNecessaire = RdDResolutionTable.findNiveauNecessaire(rollData.selectedCarac.value, rolled.roll)
rolled.ajustementNecessaire = rolled.niveauNecessaire - diff
}
rollData.ajustements = rollData.ajustements.map(a => { return { label: a.label, value: a.value } })
}

View File

@@ -42,7 +42,6 @@ import ChatRollResult from "./chat-roll-result.mjs";
import { renderTemplate } from "../constants.js";
import { RollTypeCuisine } from "./roll-type-cuisine.mjs";
import { RollPartCuisine } from "./roll-part-cuisine.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2_TEST } from "../settings/options-avancees.js";
import { ActorImpacts } from "../technical/actor-impacts.mjs";
import { RollPartEmpoignade } from "./roll-part-empoignade.mjs";
import { RollPartEmpoignadeTaille } from "./roll-part-empoignade-taille.mjs";
@@ -199,9 +198,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
}
static onRollDoneClose(dialog, roll) {
if (roll.type.retry || !OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST)) {
dialog.close()
}
dialog.close()
}
static init() { }
@@ -221,7 +218,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
foundry.applications.handlebars.loadTemplates(ALL_ROLL_TYPES.map(m => m.chatResultTemplate))
foundry.applications.handlebars.loadTemplates(ROLL_PARTS.map(p => p.template))
ROLL_PARTS.forEach(p => p.onReady())
ROLL_PARTS.forEach(p => p.onReady(ROLL_PARTS))
Handlebars.registerHelper('roll-centered-array', (base, show) => {
show = Math.abs(show)
@@ -289,6 +286,13 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
// rien pour l'instant
}
static getAllowedParts(rollData) {
return rollData.type?.allowed
? ROLL_PARTS.filter(p => RollDialog.$isIntersecting(rollData.type.allowed, p.rollTypes))
: ROLL_PARTS
}
/** pre-configure les paramètres des différentes parties de la fenêtre (par exemple, prépare les listes de caractéristiques/compétences */
static $prepareRollData(rollData) {
rollData.current = rollData.current ?? {}
@@ -302,16 +306,18 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
? [potential]
: (rollData.type.allowed ?? ALL_ROLL_TYPES.filter(m => m.isAllowed(rollData) && m.visible(rollData)).map(m => m.code) ?? [ROLL_TYPE_COMP])
const rollType = allowed.find(c => c == rollData.type.current) ?? allowed[0]
const allowedRollParts = RollDialog.getAllowedParts(rollData)
rollData.type.allowed = allowed
rollData.type.current = rollType
ALL_ROLL_TYPES.find(m => m.code == rollType).setRollDataType(rollData)
rollData.refs = foundry.utils.mergeObject(rollData.refs ?? {}, Object.fromEntries(ROLL_PARTS.map(p => [p.code, {}])));
rollData.refs = foundry.utils.mergeObject(rollData.refs ?? {}, Object.fromEntries(allowedRollParts.map(p => [p.code, {}])));
rollData.options = rollData.options ?? { rollMode: game.settings.get("core", "rollMode") }
ROLL_PARTS.forEach(p => p.initialize(rollData))
ROLL_PARTS.filter(p => p.isValid(rollData))
allowedRollParts.forEach(p => RollDialog.$initializeRollPart(rollData, p.code))
allowedRollParts
.filter(p => p.isValid(rollData))
.forEach(p => {
p.restore(rollData)
p.loadRefs(rollData)
@@ -320,6 +326,14 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
return rollData
}
static $initializeRollPart(rollData, code) {
rollData.refs[code] = rollData.refs[code] ?? {}
rollData.current[code] = rollData.current[code] ?? {}
rollData.selected[code] = rollData.selected[code] ?? {}
}
static $isIntersecting(allowed, included) { return included ? included.find(it => allowed.includes(it)) : true }
static saveParts(rollData, impacts = undefined) {
if (rollData == undefined) {
return undefined
@@ -327,6 +341,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
function saveBasics(from, to) {
if (from) {
to.ids = from.ids
to.passeArme = from.passeArme
to.rolled = from.rolled
to.particuliere = from.particuliere
@@ -337,15 +352,16 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
to.attackerRoll = {}
saveBasics(from.attackerRoll, to.attackerRoll)
}
if (from.current) {
// stockage de current
RollDialog.getAllowedParts(from)
.filter(p => p.isActive(from))
.forEach(p => p.storeClean(from, target))
}
}
}
const target = RollBasicParts.initFrom(rollData)
if (rollData.current) {
// stockage de current
ROLL_PARTS.filter(p => p.isActive(rollData))
.forEach(p => p.storeClean(rollData, target))
}
saveBasics(rollData, target)
if (impacts) {
target.reverse = {
@@ -364,7 +380,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
this.rollData = rollData
this.rollOptions = {
callbacks: [
async r => await r.active.actor.appliquerAjoutExperience(r),
async r => await r.active.actor.ajoutExperience(r),
async r => await r.active.actor.appliquerAppelMoral(r),
...(rollOptions.callbacks ?? [])
],
@@ -372,12 +388,14 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
onClose: rollOptions.onClose ?? RollDialog.onCloseDoNothing
}
this.chatRollResult = new ChatRollResult()
this.rollParts = RollDialog.getAllowedParts(rollData)
this.selectType()
this.registerHooks(rollData)
}
registerHooks(rollData) {
ROLL_PARTS.filter(p => p.isValid(rollData))
this.rollParts.filter(p => p.isValid(rollData))
.forEach(p => p.getHooks(this).forEach(h => {
const hook = h.hook;
const id = Hooks.on(hook, h.fn)
@@ -397,13 +415,12 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
selectedType.onSelect(this.rollData)
this.rollData.type.label = selectedType.title(this.rollData)
ROLL_PARTS.find(it => it.code == PART_CARAC).filterCaracs(this.rollData)
ROLL_PARTS.find(it => it.code == PART_COMP).filterComps(this.rollData)
this.rollParts.find(it => it.code == PART_CARAC).filterCaracs(this.rollData)
this.rollParts.find(it => it.code == PART_COMP).filterComps(this.rollData)
}
static getActiveParts(rollData) {
return ROLL_PARTS.filter(p => p.isActive(rollData))
getActiveParts() {
return this.rollParts.filter(p => p.isActive(this.rollData))
}
rollTitle(rollData) {
@@ -438,12 +455,13 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
))
Promise.all(
RollDialog.getActiveParts(this.rollData).map(async p => await p._onRender(this, context, options))
this.getActiveParts().map(async p => await p._onRender(this, context, options))
)
}
static getAjustements(rollData) {
return RollDialog.getActiveParts(rollData)
return RollDialog.getAllowedParts(rollData)
.filter(p => p.isActive(rollData))
.map(p => p.getAjustements(rollData))
.reduce((a, b) => a.concat(b))
.sort((a, b) => a.value == undefined ? 1 : b.value == undefined ? -1 : 0)
@@ -460,8 +478,8 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
.map(m => m.toTypeData(rollData))
RollBasicParts.loadSurprises(rollData, this.getSelectedType().code)
rollData.type.label = this.getSelectedType()?.title(rollData)
//TOCHECK: set type.label ?
const visibleRollParts = RollDialog.getActiveParts(rollData)
const visibleRollParts = this.getActiveParts()
visibleRollParts.forEach(p => p.applyExternalImpacts(visibleRollParts, rollData))
this.setSpecialComp(visibleRollParts);
@@ -470,7 +488,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
RollDialog.calculAjustement(rollData)
const templates = RollDialog.getActiveParts(rollData).map(p => p.toTemplateData())
const templates = visibleRollParts.map(p => p.toTemplateData())
const context = await super._prepareContext()
return foundry.utils.mergeObject(
{
@@ -484,8 +502,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
const specialComp = visibleRollParts.map(p => p.getSpecialComp(this.rollData))
.reduce((a, b) => a.concat(b))
if (specialComp.length > 0) {
const rollPartComp = RollDialog.getActiveParts(this.rollData)
.find(it => it.code == PART_COMP);
const rollPartComp = this.getActiveParts().find(it => it.code == PART_COMP)
rollPartComp?.setSpecialComp(this.rollData, specialComp)
}
}
@@ -525,12 +542,15 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
roll.result = selectedRollType.getResult(roll, impacts)
console.info('RollDialog.roll:', roll)
const callbacks = [
...this.rollOptions.callbacks,
...selectedRollType.callbacks(this.rollOptions),
...this.rollOptions.callbacks,
]
await Promise.all(callbacks.map(async callback => await callback(roll)))
for (let callback of callbacks) {
await callback(roll)
}
await impacts.applyImpacts()
selectedRollType.onApplyImpacts(roll, impacts)
@@ -540,13 +560,16 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
static loadRollData(roll) {
RollDialog.$prepareRollData(roll)
if (roll.attackerRoll) {
RollDialog.$prepareRollData(roll.attackerRoll)
}
RollDialog.calculAjustement(roll)
roll.v2 = true
return roll
}
async defaultCallback(roll, rolled) {
await roll.active.actor.appliquerAjoutExperience(roll)
await roll.active.actor.ajoutExperience(roll)
await roll.active.actor.appliquerAppelMoral(roll)
}

View File

@@ -1,7 +1,11 @@
import { Distance } from "../combat/distance.mjs"
import { RDD_CONFIG } from "../constants.js"
import { MAP_PHASE, RdDInitiative } from "../initiative.mjs"
import { ATTAQUE_TYPE_MELEE } from "../item/arme.js"
import { Misc } from "../misc.js"
import { RdDBonus } from "../rdd-bonus.js"
import { CARACS } from "../rdd-carac.js"
import { RdDCombatManager } from "../rdd-combat.js"
import { RdDEmpoignade } from "../rdd-empoignade.js"
import { DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP } from "./roll-constants.mjs"
import RollDialog from "./roll-dialog.mjs"
@@ -10,28 +14,31 @@ import { PART_COMP } from "./roll-part-comp.mjs"
import { PART_DIFF } from "./roll-part-diff.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
import { PART_SIGN } from "./roll-part-sign.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
export const PART_ATTAQUE = 'attaque'
const TACTIQUES = RdDBonus.tactiques.filter(it => it.isTactique)
const FILTER_ATTAQUE_EMPOIGNADE = attaque => attaque.arme.isEmpoignade()
const FILTER_ATTAQUE_NON_EMPOIGNADE = attaque => !attaque.arme.isEmpoignade()
const FILTER_ATTAQUE_EMPOIGNE = attaque => attaque.arme.isUtilisableEmpoigne() && ATTAQUE_TYPE_MELEE.includes(attaque.main)
const FILTER_ATTAQUE_EMPOIGNADE = attaque => attaque.arme?.isEmpoignade()
const FILTER_ATTAQUE_RANG = rang => attaque => !attaque.arme?.isEmpoignade() && (attaque.rang == rang || rang == undefined)
const FILTER_ATTAQUE_EMPOIGNE = attaque => attaque.arme?.isUtilisableEmpoigne() && ATTAQUE_TYPE_MELEE.includes(attaque.main)
export class RollPartAttaque extends RollPartSelect {
get code() { return PART_ATTAQUE }
get section() { return ROLLDIALOG_SECTION.CHOIX }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_ATTAQUE) }
get rollTypes() { return [ROLL_TYPE_ATTAQUE] }
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_ATTAQUE) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
const attaques = rollData.active.actor.listAttaques()
refs.all = attaques.map(it => RollPartAttaque.$extractAttaque(it, rollData.active.actor))
this.filterAttaquesEmpoignade(rollData)
.sort(Misc.descending(it => it.comp?.system.niveau ?? -8))
refs.all = attaques.map(it => RollPartAttaque.$extractAttaque(it, rollData))
this.filterAttaquesInitiative(rollData)
refs.tactiques = TACTIQUES
if (refs.attaques.length > 0) {
const attaque = this.findAttaque(refs.attaques, this.getSaved(rollData))
@@ -43,49 +50,63 @@ export class RollPartAttaque extends RollPartSelect {
return it.arme.isEmpoignade()
}
store(rollData, targetData) {
super.store(rollData, targetData)
this.getSaved(targetData).dmg = this.getCurrent(rollData).dmg
}
restore(rollData) {
const saved = this.getSaved(rollData)
super.restore(rollData)
if (saved.dmg != undefined) {
this.getCurrent(rollData).dmg = this.getSaved(rollData).dmg
const saved = this.getSaved(rollData) ?? {}
if (saved.key) {
this.setCurrent(rollData, {
key: saved.key,
tactique: saved.tactique,
dmg: saved.dmg
})
}
}
store(rollData, targetData) {
const current = this.getCurrent(rollData)
this.setSaved(targetData, {
key: current.key,
tactique: current.tactique,
dmg: current.dmg
})
}
findAttaque(attaques, saved) {
return attaques.find(at => at.arme.id == saved?.arme?.id &&
at.comp.id == saved?.comp?.id
)
return attaques.find(it => it.key == saved.key) ??
attaques.find(it => it.arme.id == (saved?.arme?.id ?? it.arme.id)
&& it.comp.id == (saved?.comp?.id ?? it.comp.id)
&& it.main == (saved?.main ?? it.main)
)
}
choices(refs) { return refs.attaques }
static $extractAttaque(attaque, actor) {
static $extractAttaque(attaque, rollData) {
attaque.key = `${attaque.action}::${attaque.label}`
attaque.tactique = TACTIQUES[0]
attaque.initialDiff = attaque.comp?.system.default_diffLibre ?? 0
attaque.distance = Distance.ajustements(rollData.active?.token, rollData.opponent?.token, attaque)
attaque.rang = RdDInitiative.phaseArme(attaque.comp?.system.categorie, attaque.arme)?.rang
return attaque
}
prepareContext(rollData) {
this.filterAttaquesEmpoignade(rollData)
this.filterAttaquesInitiative(rollData)
const current = this.getCurrent(rollData)
current.dmg = RdDBonus.dmgRollV2(rollData, current)
}
filterAttaquesEmpoignade(rollData) {
filterAttaquesInitiative(rollData) {
const refs = this.getRefs(rollData)
const isEmpoignade = RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId)
const rang = RdDCombatManager.getRangInitiativeCombatant(rollData.ids.actorId, rollData.ids.actorTokenId)
const isEmpoignade = MAP_PHASE.empoignade.rang == rang
//const isEmpoignade = RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId)
refs.isEmpoignadeEnCours = RdDEmpoignade.isEmpoignadeEnCours(rollData.active.actor)
const filterAttaques = isEmpoignade ?
FILTER_ATTAQUE_EMPOIGNADE
: refs.isEmpoignadeEnCours
? FILTER_ATTAQUE_EMPOIGNE
: FILTER_ATTAQUE_NON_EMPOIGNADE
: FILTER_ATTAQUE_RANG(rang)
refs.attaques = refs.all.filter(filterAttaques)
}
@@ -98,24 +119,30 @@ export class RollPartAttaque extends RollPartSelect {
$selectAttaque(rollData, key) {
const tactique = this.getCurrent(rollData).tactique
this.selectByKey(rollData, key)
if (tactique) {
this.getCurrent(rollData).tactique = tactique
}
}
async _onRender(rollDialog, context, options) {
const inputDiff = rollDialog.element.querySelector(`roll-section[name="diff"] input[name="diff"]`)
const selectAttaque = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-attaque"]`)
const selectTactique = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-tactique"]`)
const checkMortalite = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="check-mortalite"]`)
const utiliserDagueEmpoignade = rollDialog.element.querySelector(`roll-section[name="${this.code}"] a.utiliser-dague-empoignade`)
const current = this.getCurrent(rollDialog.rollData)
const rollData = rollDialog.rollData
const current = this.getCurrent(rollData)
selectAttaque.addEventListener("change", e => {
selectAttaque?.addEventListener("change", e => {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectAttaque(rollDialog.rollData, selectOptions[index]?.value)
this.$selectAttaque(rollData, selectOptions[index]?.value)
rollDialog.render()
})
selectTactique.addEventListener("change", e => {
selectTactique?.addEventListener("change", e => {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
current.tactique = RdDBonus.find(selectOptions[index]?.value)
@@ -128,9 +155,11 @@ export class RollPartAttaque extends RollPartSelect {
})
utiliserDagueEmpoignade?.addEventListener("click", e => {
e.preventDefault()
const rollData = rollDialog.rollData
this.utiliserDagueEmpoignade(rollData)
})
inputDiff?.addEventListener("input", e => {
this.getRefs(rollData).all.forEach(attaque => attaque.initialDiff = undefined)
})
}
utiliserDagueEmpoignade(rollData) {
@@ -150,11 +179,14 @@ export class RollPartAttaque extends RollPartSelect {
if (this.visible(rollData)) {
const current = this.getCurrent(rollData)
switch (part.code) {
case PART_CARAC: return part.filterCaracs(rollData, [current.carac.key])
case PART_COMP: return part.filterComps(rollData, [current.comp.name])
case PART_CARAC: return part.filterCaracs(rollData, [current.carac?.key])
case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
case PART_DIFF: {
if (current.initialDiff) {
part.setDiff(rollData, { type: DIFF.ATTAQUE, value: current.initialDiff })
if (Distance.typeAttaqueDistance(current)) {
part.setDiff(rollData, { type: DIFF.DEFAUT })
}
else {
part.setDiff(rollData, { type: DIFF.ATTAQUE, diff: current.initialDiff })
current.initialDiff = undefined
}
break

View File

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

View File

@@ -1,7 +1,9 @@
import { Grammar } from "../grammar.js"
import { Misc } from "../misc.js"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_DIFF } from "./roll-part-diff.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
export const PART_COMP = "comp"
@@ -15,15 +17,21 @@ export class RollPartComp extends RollPartSelect {
get name() { return 'Compétences' }
get section() { return ROLLDIALOG_SECTION.COMP }
onReady(rollParts) {
this.rollPartCarac = rollParts.find(it => it.code == PART_CARAC)
this.rollPartDiff = rollParts.find(it => it.code == PART_DIFF)
}
loadRefs(rollData) {
const refs = this.getRefs(rollData)
const selected = this.getSelected(rollData)
const all = this.$getActorComps(rollData)
if (selected.forced) {
refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selected.key))
const selectedComp = selected.key
if (selected.forced && selectedComp) {
refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selectedComp))
if (refs.all.length == 0) {
if (selected.key.length > 0) {
refs.all = all.filter(comp => Grammar.includesLowerCaseNoAccent(comp.label, selected.key))
if (selected.key && selected.key.length > 0) {
refs.all = all.filter(comp => Grammar.includesLowerCaseNoAccent(comp.label, selectedComp))
}
else {
refs.all = all.filter(comp => comp == SANS_COMPETENCE)
@@ -35,6 +43,13 @@ export class RollPartComp extends RollPartSelect {
}
refs.comps = refs.all
this.$selectComp(rollData)
if (rollData.type.current == PART_COMP && selectedComp) {
const current = this.getCurrent(rollData)
const selectedCarac = RollPart.getSelectedPart(rollData, PART_CARAC)
const selectedDiff = RollPart.getSelectedPart(rollData, PART_DIFF)
this.rollPartCarac.selectByKey(rollData, selectedCarac?.key ?? current.comp.system.defaut_carac)
this.rollPartDiff.setDiff(rollData, selectedDiff?.value ?? current.comp.system.default_diffLibre)
}
}
choices(refs) { return refs.comps }
@@ -71,6 +86,7 @@ export class RollPartComp extends RollPartSelect {
refs.comps.sort(sorting)
}
this.$selectComp(rollData)
}
prepareContext(rollData) {

View File

@@ -10,7 +10,7 @@ export class RollPartConditions extends RollPart {
settingMin() { return RollPart.settingKey(this, 'min') }
settingMax() { return RollPart.settingKey(this, 'max') }
onReady() {
onReady(rollParts) {
game.settings.register(SYSTEM_RDD, this.settingMin(),
{
name: "Malus maximal de conditions",
@@ -65,12 +65,7 @@ export class RollPartConditions extends RollPart {
async _onRender(rollDialog, context, options) {
const input = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`)
input?.addEventListener("input", e => this.onInputChange(e, rollDialog))
}
onInputChange(event, rollDialog) {
this.getCurrent(rollDialog.rollData).value = parseInt(event.currentTarget.value)
rollDialog.render()
input?.addEventListener("input", e => this.onNumericInputChange(e, rollDialog))
}
}

View File

@@ -4,20 +4,22 @@ import { ROLL_TYPE_CUISINE } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
export const PART_CUISINE = "cuisine"
export class RollPartCuisine extends RollPartSelect {
onReady() {
onReady(rollParts) {
foundry.applications.handlebars.loadTemplates({ 'roll-oeuvre-recettecuisine': `systems/foundryvtt-reve-de-dragon/templates/roll/roll-oeuvre-recettecuisine.hbs` })
}
get code() { return PART_CUISINE }
get section() { return ROLLDIALOG_SECTION.CHOIX }
get rollTypes() { return [ROLL_TYPE_CUISINE] }
isValid(rollData) { return rollData.active.actor.isPersonnage() }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_CUISINE) }
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_CUISINE) }
restore(rollData) {
super.restore(rollData)
@@ -148,12 +150,13 @@ export class RollPartCuisine extends RollPartSelect {
this.$selectPreparation(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.render()
})
checkboxFabriquer?.addEventListener("change", e => {
current.fabriquer = e.currentTarget.checked
})
inputDiff?.addEventListener("change", e => {
current.value = parseInt(e.currentTarget.value)
rollDialog.render()
})
inputProportions?.addEventListener("change", e => {
current.proportions = parseInt(e.currentTarget.value)

View File

@@ -1,4 +1,5 @@
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js"
import { Distance } from "../combat/distance.mjs"
import { ITEM_TYPES } from "../constants.js"
import { ATTAQUE_TYPE, RdDItemArme } from "../item/arme.js"
import { CARACS } from "../rdd-carac.js"
import { DIFF, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
@@ -7,7 +8,7 @@ import { PART_COMP } from "./roll-part-comp.mjs"
import { PART_DIFF } from "./roll-part-diff.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
import { PART_SIGN } from "./roll-part-sign.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
export const PART_DEFENSE = 'defense'
@@ -16,56 +17,67 @@ export class RollPartDefense extends RollPartSelect {
get code() { return PART_DEFENSE }
get section() { return ROLLDIALOG_SECTION.CHOIX }
isValid(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) && rollData.attackerRoll != undefined }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) && rollData.attackerRoll != undefined }
static getDiffAttaque(attackerRoll) {
// TODO: rollDataV2?
return attackerRoll.diffLibre;
}
get rollTypes() { return [ROLL_TYPE_DEFENSE] }
isValid(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_DEFENSE) && rollData.attackerRoll != undefined }
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_DEFENSE) && rollData.attackerRoll != undefined }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
const attackerRoll = rollData.attackerRoll
const defenseur = rollData.active.actor
refs.isDistance = [ATTAQUE_TYPE.TIR, ATTAQUE_TYPE.LANCER].find(it => it == attackerRoll?.main)
refs.distance = rollData.attackerRoll.current?.attaque?.distance
const isEmpoignade = attackerRoll.dmg.isEmpoignade
const isEmpoignadeEnCours = isEmpoignade && defenseur.itemTypes[ITEM_TYPES.empoignade].find(it =>
[it.system.empoigneurid, it.system.empoigneid].includes(rollData.ids.opponentId) &&
it.system.pointsemp != 0)
const esquives = (refs.isDistance == ATTAQUE_TYPE.TIR || isEmpoignadeEnCours)
const esquives = (refs.distance?.typeAttaque == ATTAQUE_TYPE.TIR || isEmpoignadeEnCours)
? []
: defenseur.getCompetencesEsquive()
const parades = isEmpoignade
? [RdDItemArme.empoignade(defenseur)]
: defenseur.items.filter(it => it.isParade() && (!refs.isDistance || it.isBouclier()))
: this.$getParades(defenseur, attackerRoll, refs.distance)
refs.defenses = [
...esquives.map(it => RollPartDefense.$extractEsquive(it, defenseur)),
...parades.map(it => RollPartDefense.$extractParade(it, attackerRoll?.arme, defenseur))
...esquives.map(it => RollPartDefense.$extractEsquive(it, defenseur, attackerRoll)),
...parades.map(it => RollPartDefense.$extractParade(it, defenseur, attackerRoll))
]
this.$selectDefense(rollData)
}
static $extractEsquive(esquive, defenseur) {
return {
$getParades(defenseur, attackerRoll, distance) {
const parades = defenseur.items.filter(it => it.isParade() && (!distance || it.isBouclier()))
const armeAttaque = attackerRoll?.current?.attaque?.arme
return armeAttaque
? parades.filter(armeDefense => RdDItemArme.defenseArmeParade(armeAttaque, armeDefense) != 'impossible')
: parades
}
static $extractEsquive(esquive, defenseur, attackerRoll) {
const defense = {
key: esquive.id,
label: esquive.name,
img: esquive.img,
// TODO: carac pour créatures
// TODO: carac pour créatures à vérifier
carac: defenseur.isPersonnage() ? CARACS.DEROBEE : esquive.name,
verb: "esquive",
comp: esquive,
isEsquive: true
}
if (attackerRoll.current?.attaque?.distance) {
defense.distance = {
ajustementDefense: Distance.ajustementDefense(attackerRoll.current.attaque),
}
}
return defense
}
static $extractParade(armeDefense, armeAttaque, defenseur) {
static $extractParade(armeDefense, defenseur, attackerRoll) {
const armeAttaque = attackerRoll?.arme
const comp = (ITEM_TYPES.competencecreature == armeDefense.type)
? armeDefense
: defenseur.getCompetence(armeDefense.system.competence)
return {
const defense = {
key: armeDefense.id,
label: 'Parade ' + armeDefense.name,
img: armeDefense.img,
@@ -78,6 +90,13 @@ export class RollPartDefense extends RollPartSelect {
typeParade: armeAttaque ? RdDItemArme.defenseArmeParade(armeDefense, armeAttaque) : 'norm',
isEsquive: false
}
if (attackerRoll.current?.attaque?.distance) {
defense.distance = {
ajustementBouclier: Distance.ajustementBouclier(armeDefense),
ajustementDefense: Distance.ajustementDefense(attackerRoll.current.attaque),
}
}
return defense
}
prepareContext(rollData) {
@@ -107,38 +126,42 @@ export class RollPartDefense extends RollPartSelect {
impactOtherPart(part, rollData) {
if (this.visible(rollData)) {
const refs = this.getRefs(rollData)
const current = this.getCurrent(rollData)
switch (part.code) {
case PART_CARAC: return part.filterCaracs(rollData, [current.carac])
case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
case PART_CARAC: return part.filterCaracs(rollData, refs.defenses.length > 0 ? [current.carac] : ['impossible'])
case PART_COMP: return part.filterComps(rollData, refs.defenses.length > 0 ? [current.comp?.name] : ['impossible'])
case PART_DIFF: return part.setDiff(rollData, this.getDiffDefense(rollData))
case PART_SIGN: return part.setArme(rollData, this.isArmeDisparate(rollData), current.forceRequise)
case PART_SIGN: return part.setArme(rollData, this.getArmeDisparate(rollData), current.forceRequise)
}
}
return undefined
}
isArmeDisparate(rollData) {
getArmeDisparate(rollData) {
const armeDefense = this.getCurrent(rollData).arme
if (armeDefense) {
const armeAttaque = rollData.attackerRoll?.current.attaque.arme
return RdDItemArme.defenseArmeParade(armeAttaque, armeDefense) == 'sign'
return RdDItemArme.defenseArmeParade(armeAttaque, armeDefense)
}
return false
return 'norm'
}
getDiffDefense(rollData) {
const refs = this.getRefs(rollData)
if (refs.isDistance || !rollData.attackerRoll) {
// TODO: Déterminer la difficulté de parade
return { diff: 0, type: DIFF.LIBRE }
if (refs.distance) {
const current = this.getCurrent(rollData)
const diff = (current.distance?.ajustementBouclier?.value ?? 0)
+ (current.distance?.ajustementDefense?.value ?? 0)
return { diff: diff, type: DIFF.DEFENSE }
}
else {
if (rollData.attackerRoll) {
const attackerRoll = rollData.attackerRoll
const diff = attackerRoll.v2
? attackerRoll.selected.diff.value
: attackerRoll.diff
return { diff: diff ?? 0, type: DIFF.DEFENSE }
}
return { diff: 0, type: DIFF.LIBRE }
}
}

View File

@@ -73,12 +73,7 @@ export class RollPartDiff extends RollPart {
async _onRender(rollDialog, context, options) {
const input = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`)
input?.addEventListener("input", e => this.onInputChange(e, rollDialog))
}
onInputChange(event, rollDialog) {
this.getCurrent(rollDialog.rollData).value = parseInt(event.currentTarget.value)
rollDialog.render()
input?.addEventListener("input", e => this.onNumericInputChange(e, rollDialog))
}
}

View File

@@ -3,6 +3,7 @@ import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
import { PART_DEFENSE } from "./roll-part-defense.mjs"
import { RollPart } from "./roll-part.mjs"
const ECAILLES = "ecailles"
@@ -10,8 +11,9 @@ export class RollPartEcailles extends RollPartCheckbox {
get code() { return ECAILLES }
get rollTypes() { return [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE] }
isValid(rollData) {
return this.isRollType(rollData, ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE)
return RollPart.isRollType(rollData, ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE)
}
visible(rollData) {
@@ -25,9 +27,9 @@ export class RollPartEcailles extends RollPartCheckbox {
}
getArme(rollData) {
return this.isRollType(rollData, ROLL_TYPE_ATTAQUE)
return RollPart.isRollType(rollData, ROLL_TYPE_ATTAQUE)
? rollData.current[PART_ATTAQUE]?.arme
: this.isRollType(rollData, ROLL_TYPE_DEFENSE)
: RollPart.isRollType(rollData, ROLL_TYPE_DEFENSE)
? rollData.current[PART_DEFENSE]?.arme
: undefined
}

View File

@@ -1,7 +1,8 @@
import { RDD_CONFIG } from "../constants.js"
import { RdDEmpoignade } from "../rdd-empoignade.js"
import { COMBAT_ROLL_TYPES } from "./roll-constants.mjs"
import { COMBAT_ROLL_TYPES, ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
import { RollPart } from "./roll-part.mjs"
const EMPOIGNADE_TAILLE = "empoignade-taille"
@@ -9,6 +10,7 @@ export class RollPartEmpoignadeTaille extends RollPartCheckbox {
get code() { return EMPOIGNADE_TAILLE }
get rollTypes() { return [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE] }
isValid(rollData) {
return RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId)
}

View File

@@ -1,9 +1,10 @@
import { RDD_CONFIG } from "../constants.js"
import { ATTAQUE_TYPE_MELEE } from "../item/arme.js"
import { RdDEmpoignade } from "../rdd-empoignade.js"
import { ROLL_TYPE_ATTAQUE } from "./roll-constants.mjs"
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
import { RollPart } from "./roll-part.mjs"
const EMPOIGNADE = "empoignade"
@@ -11,6 +12,7 @@ export class RollPartEmpoignade extends RollPartCheckbox {
get code() { return EMPOIGNADE }
get rollTypes() { return [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE] }
isValid(rollData) {
return RdDEmpoignade.isCombatantEmpoignade(rollData.ids.opponentId, rollData.ids.opponentTokenId) &&
!RdDEmpoignade.isCombatantEmpoignade(rollData.ids.actorId, rollData.ids.actorTokenId)

View File

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

View File

@@ -4,9 +4,10 @@ import { ROLL_TYPE_JEU } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP, RollPartComp } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
import { RdDItem } from "../item.js"
import { Misc } from "../misc.js"
import { Grammar } from "../grammar.js"
export const PART_JEU = "jeu"
@@ -17,8 +18,9 @@ export class RollPartJeu extends RollPartSelect {
get code() { return PART_JEU }
get section() { return ROLLDIALOG_SECTION.CHOIX }
get rollTypes() { return [ROLL_TYPE_JEU] }
isValid(rollData) { return rollData.active.actor.isPersonnage() }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_JEU) }
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_JEU) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
@@ -88,14 +90,19 @@ export class RollPartJeu extends RollPartSelect {
static forceCompJeu(rollData) {
const jeu = rollData.current[PART_JEU].base ?? rollData.current[PART_JEU].comp
rollData.refs[PART_COMP].comps = [jeu].map(it => RollPartComp.extractComp(it))
if (jeu){
rollData.refs[PART_COMP].comps = [jeu].map(it => RollPartComp.extractComp(it))
}
else {
rollData.refs[PART_COMP].comps = rollData.refs[PART_COMP].all.filter(comp => comp.label == 'Jeu')
}
rollData.current[PART_COMP] = rollData.refs[PART_COMP].comps[0]
}
async _onRender(rollDialog, context, options) {
const selectjeu = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-jeu"]`)
selectjeu.addEventListener("change", e => {
selectjeu?.addEventListener("change", e => {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectJeu(rollDialog.rollData, selectOptions[index]?.value)

View File

@@ -4,10 +4,10 @@ import { CARACS } from "../rdd-carac.js"
import { RdDTimestamp } from "../time/rdd-timestamp.js"
import { TMRUtility } from "../tmr-utility.js"
import { ROLL_TYPE_MEDITATION } from "./roll-constants.mjs"
import { PART_CARAC, RollPartCarac } from "./roll-part-carac.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
export const PART_MEDITATION = "meditation"
@@ -18,6 +18,10 @@ export class RollPartMeditation extends RollPartSelect {
get code() { return PART_MEDITATION }
get section() { return ROLLDIALOG_SECTION.CHOIX }
get rollTypes() { return [ROLL_TYPE_MEDITATION] }
isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() }
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_MEDITATION) }
store(rollData, targetData) {
const current = this.getCurrent(rollData)
this.setSaved(targetData, {
@@ -29,9 +33,6 @@ export class RollPartMeditation extends RollPartSelect {
})
}
isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_MEDITATION) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
const actor = rollData.active.actor
@@ -69,7 +70,7 @@ export class RollPartMeditation extends RollPartSelect {
}
getMalusEchecs(rollData) {
return this.getCurrent(rollData).meditation.system.malus
return this.getCurrent(rollData).meditation?.system.malus ?? 0
}
getAjustements(rollData) {
@@ -89,16 +90,18 @@ export class RollPartMeditation extends RollPartSelect {
$selectConditionMeditation(rollData) {
const current = this.getCurrent(rollData)
current.heureMonde = RdDTimestamp.getWorldTime().heure
current.heureMeditation = RdDTimestamp.findHeure(current.meditation.system.heure)?.heure
current.isHeure = current.heureMeditation == current.heureMonde
current.isTMR = Grammar.equalsInsensitive(current.meditation.system.tmr, TMRUtility.getTMRType(rollData.active.actor.system.reve.tmrpos.coord))
if (current.meditation){
current.heureMonde = RdDTimestamp.getWorldTime().heure
current.heureMeditation = RdDTimestamp.findHeure(current.meditation.system.heure)?.heure
current.isHeure = current.heureMeditation == current.heureMonde
current.isTMR = Grammar.equalsInsensitive(current.meditation.system.tmr, TMRUtility.getTMRType(rollData.active.actor.system.reve.tmrpos.coord))
}
}
async _onRender(rollDialog, context, options) {
const selectMeditation = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-meditation"]`)
selectMeditation.addEventListener("change", e => {
selectMeditation?.addEventListener("change", e => {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectMeditation(rollDialog.rollData, selectOptions[index]?.value)
@@ -110,7 +113,7 @@ export class RollPartMeditation extends RollPartSelect {
setupListenerCondition(rollDialog, inputName) {
const checkbox = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${inputName}"]`)
checkbox.addEventListener("change", e => {
checkbox?.addEventListener("change", e => {
const current = this.getCurrent(rollDialog.rollData)
current[inputName] = e.currentTarget.checked
rollDialog.render()

View File

@@ -5,7 +5,7 @@ import { ROLL_TYPE_OEUVRE } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
export const PART_OEUVRE = "oeuvre"
@@ -24,7 +24,7 @@ const ARTS = [
]
export class RollPartOeuvre extends RollPartSelect {
onReady() {
onReady(rollParts) {
ARTS.forEach(art => art.label = Misc.typeName('Item', art.type))
ARTS.map(it => `roll-oeuvre-${it.type}`)
.forEach(art =>
@@ -35,8 +35,9 @@ export class RollPartOeuvre extends RollPartSelect {
get code() { return PART_OEUVRE }
get section() { return ROLLDIALOG_SECTION.CHOIX }
get rollTypes() { return [ROLL_TYPE_OEUVRE] }
isValid(rollData) { return rollData.active.actor.isPersonnage() }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_OEUVRE) }
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_OEUVRE) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
@@ -75,7 +76,7 @@ export class RollPartOeuvre extends RollPartSelect {
async _onRender(rollDialog, context, options) {
const selectOeuvre = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-oeuvre"]`)
selectOeuvre.addEventListener("change", e => {
selectOeuvre?.addEventListener("change", e => {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectOeuvre(rollDialog.rollData, selectOptions[index]?.value)
@@ -88,7 +89,7 @@ export class RollPartOeuvre extends RollPartSelect {
const current = this.getCurrent(rollData)
switch (part.code) {
case PART_CARAC: return part.filterCaracs(rollData, current.caracs)
case PART_COMP: return part.filterComps(rollData,[current.comp?.name])
case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
}
}
return undefined

View File

@@ -5,7 +5,7 @@ import { ROLL_TYPE_POSSESSION } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { RollPartSelect } from "./roll-part-select.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
export const PART_POSSESSION = "possession"
@@ -17,7 +17,8 @@ export class RollPartPossession extends RollPartSelect {
get name() { return 'Possession' }
get section() { return ROLLDIALOG_SECTION.CHOIX }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_POSSESSION) }
get rollTypes() { return [ROLL_TYPE_POSSESSION] }
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_POSSESSION) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
@@ -61,10 +62,10 @@ export class RollPartPossession extends RollPartSelect {
rollDialog.render()
})
button?.addEventListener("click", async e => {
e.preventDefault()
await RdDPossessionV2.createPossessionIfMissing(rollData.active, rollData.opponent)
rollDialog.render()
})
e.preventDefault()
await RdDPossessionV2.createPossessionIfMissing(rollData.active, rollData.opponent)
rollDialog.render()
})
}
$selectPossession(rollData, key) {

View File

@@ -29,4 +29,17 @@ export class RollPartRollMode extends RollPart {
rollDialog.render()
}))
}
getHooks(rollDialog) {
return [
{ hook: "clientSettingChanged", fn: (setting, update, options, id) => this.onUpdateSetting(rollDialog, setting, update, options, id) },
]
}
async onUpdateSetting(rollDialog, setting, update, options, id) {
if (setting == 'core.rollMode') {
this.setCurrent(rollDialog.rollData, { key: game.settings.get("core", "rollMode") })
rollDialog.render()
}
}
}

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