Compare commits

...

72 Commits

Author SHA1 Message Date
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
36c771518d v13.0.21 2025-12-08 20:12:17 +01:00
dd7a3700dc Appréciation des services 2025-12-08 20:10:56 +01:00
f0736015a7 Surcharge de couleurs de style
Les titres dans les descriptions n'étaient pas bien affichés dans la
fenêtre de jet
2025-12-08 19:40:21 +01:00
aae603d798 Appréciation de plats 2025-12-08 19:39:21 +01:00
d9bc6309fb Correction des bonus des Cyans 2025-12-08 01:42:57 +01:00
c14361919c Update compendiums 2025-12-08 01:42:55 +01:00
b26c39cf21 Ajout des options d'appréciation
L'appréciation utilise:

- un niveau de qualité (qui réutilise la qualité sur les items en ayant)
- un bon moment (coeur/musique/...)
- un niveau de jet de moral
- une caractéristique (perception)
- une compétence

Les bon moments passés sont remis à zéro lors du passage de
château dormant.

Ajout des jets de moral très heureux.

Ajout de jet d'appréciation sur les résultats des oeuvres et des jeux.
2025-12-08 01:42:47 +01:00
ca2d17bd25 Encombrement avec décimales 2025-12-07 23:48:41 +01:00
a243209c90 Fix: selection parmi les cibles 2025-12-07 02:52:19 +01:00
90435c07b4 cleanup unused imports 2025-12-06 21:12:30 +01:00
46d09c7bd9 Dimension des zones editeur
amélioration des zones de saisie des éditeurs (journaux, ...)
2025-12-06 21:12:30 +01:00
05036877ed Possessions dans HUD
Permettre de commencer les possessions V2
2025-12-06 21:12:25 +01:00
98e8c7a10c Gestion de possession - fin de round
- affichage du message pour indiquer l'état d'une possession en fin de
round
- bouton de conjuration depuis la feuille de personnage
2025-12-05 20:12:14 +01:00
19cabe816e Gestion défense et compteur de possession 2025-12-05 20:12:14 +01:00
706aa657b1 Méthode rollPossession pour attaque possession
- Ajout d'une méthode pour ouvrir le dialogue en mode possession
- gestion des information de possession
- fenêtre défense possession
- préparation des messages de tchat
2025-12-05 20:12:09 +01:00
fd3f988a4f Roll V2 mode possession 2025-11-28 19:44:06 +01:00
981282d809 Ajout de méthode getConjurations
Pour lister les compétences de possession/conjuration de manière
homogène (tout actor doué de rêve)
2025-11-28 00:04:16 +01:00
fcce8b0a4b Merge pull request 'feature/v13-empoignade-v2' (#785) from feature/v13-empoignade-v2 into v13
All checks were successful
Release Creation / build (release) Successful in 16m21s
Reviewed-on: https, #785
2025-11-27 14:38:25 +01:00
461a398965 Police homogène pour la navigation 2025-11-27 02:08:25 +01:00
eef0893d1a Version 13.0.20 2025-11-27 01:55:19 +01:00
c50f1287b5 Ajustement astrologique rituels 2025-11-27 01:14:46 +01:00
acd40f3154 Fix dépense rêve sort
La dépense de rêve de sort se faisait en parallèle de la fermeture
de fenêtre des TMRs, qui modifiait la fatigue. Du coup, l'update de
la dépense de rêve ne se faisait pas
2025-11-27 01:02:09 +01:00
764f9f81c8 Centrage logo pause 2025-11-26 23:39:15 +01:00
70e8cd74a2 Correction feuille méditation joueur 2025-11-26 21:27:39 +01:00
e96f4e01bd Majuscule Survie en désert 2025-11-24 18:04:43 +01:00
c44c2d7c96 Ajout d'un statut "malade/empoisonné" 2025-11-24 18:04:43 +01:00
e2ee73bc4e Empoignade V2
Correction, de l'empoignade en mode jet V2

- le défenseur diminue le nombre de points d'empoignade
- amélioration des messages liés à l'empoignade
- ajout de choix de pertes d'endurance à infliger
2025-11-24 18:04:43 +01:00
3f19886342 Fix affichage sur perte d'endurance
décaller l'ajout d'effets après l'update permet
d'éviter les résultats "invisibles"
2025-11-24 18:04:43 +01:00
9a5afc918e Fix suppression effets 2025-11-24 18:04:43 +01:00
2ac35ef5d1 Corrections de styles incorrects
- combo de sélection des dommages d'empoignade
- boutons de navigation dans les journaux
- boutons de blessures dans la feuille de personnage
2025-11-24 18:04:42 +01:00
33c6b35601 Merge pull request '## 13.0.19 - L'introspection d'Illysis' (#784) from feature/v13-combats-v2 into v13
All checks were successful
Release Creation / build (release) Successful in 2m10s
Reviewed-on: https, #784
2025-11-14 17:46:26 +01:00
82f870db05 Bouton pour jet de résistance
Ajout d'un bouton à côté de la carac rêve
2025-11-13 01:13:47 +01:00
878efab321 Correction expérience sur résistance 2025-11-13 00:10:08 +01:00
659ddbd0a4 Jet V2 - Ajout des écailles 2025-11-12 23:09:10 +01:00
22b9e11021 Correction particulières 2025-11-12 22:21:27 +01:00
02ec8880fc Correction combat V2 avec plusieurs joueurs
Les messages de défense fonctionnent sur les jets V2
2025-11-12 22:10:51 +01:00
521cf50b7b Pas de suppression surenc/demireve
L'icône surencombrement ne peut plus être supprimée si on est
sur-encombré.
2025-11-12 22:10:51 +01:00
1cc6fab3a9 Autoriser attaque sans initiative 2025-11-12 22:10:51 +01:00
7baccbabb9 Gestion des droits jets V2 2025-11-12 22:10:42 +01:00
d9b24b0f97 Correction sur changelog
All checks were successful
Release Creation / build (release) Successful in 2m37s
2025-11-12 15:21:43 +01:00
d504a0e131 Merge pull request '13.0.17 - Le reflet d'Illysis' (#783) from feature/v13-mineurs into v13
Reviewed-on: https, #783
2025-11-12 15:19:43 +01:00
09ca86a7fd Suppression de message d'erreur
Si un acteur n'a pas toutes les compétences (ie: invocation), les
messages indiquant que les compétences sont manquantes ne
sont plus affichés
2025-11-11 23:09:28 +01:00
5b68837023 Ajout icone service écuries 2025-11-11 23:09:28 +01:00
7452c54c04 Feuille personnage avec police 2025-11-11 23:09:28 +01:00
1270 changed files with 41140 additions and 11485 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><linearGradient x1="0" x2="1" y1="1" y2="0" id="lorc-shattered-sword-gradient-4"><stop offset="0%" stop-color="#4a4a4a" stop-opacity="1"></stop><stop offset="100%" stop-color="#c9c9c9" stop-opacity="1"></stop></linearGradient><radialGradient id="lorc-shattered-sword-gradient-5"><stop offset="0%" stop-color="#9013fe" stop-opacity="1"></stop><stop offset="100%" stop-color="#85562c" stop-opacity="1"></stop></radialGradient><radialGradient id="lorc-shattered-sword-gradient-7"><stop offset="0%" stop-color="#9013fe" stop-opacity="1"></stop><stop offset="100%" stop-color="#85562c" stop-opacity="1"></stop></radialGradient></defs><g class="" transform="translate(1,-2)" style=""><path d="m496.223 16.818-48.475 44.205 48.475 4.575v-48.78zm-41.55 1.22-68.91 11.28-7.04 65.547 75.95-76.828zM352.26 77.907l-87.887 50.3 15.447 41.026 82.662-16.87-10.222-74.456zm64.34 25.022-32.967 67.443 24.842 70.684 54.314-134.19-46.19-3.937zm-271.362 72.808c-10.02.155-20.714 3.165-30.79 9.057 4.143 8.863 3.382 18.708-2.776 24.873-6.158 6.165-15.993 6.927-24.846 2.78-12.923 22.167-11.88 47.34 2.485 61.73l29.84-29.87c58.655 42.87 109.37 92.94 150.57 151.24l-36.19 36.23 6.61-6.604c14.283 14.298 39.192 15.42 61.23 2.732-4.88-9.197-4.366-19.74 2.107-26.22 6.47-6.478 17-6.993 26.185-2.112 12.66-22.062 11.54-47-2.732-61.3l-28.248 28.28c-57.035-42.41-107.91-92.665-151.426-150.386l35.455-35.492-6.61 6.603c-7.834-7.843-18.863-11.726-30.862-11.542zm108.45 4.512c-17.61 17.41-39.674 39.21-62.22 61.375a728.952 728.952 0 0 0 27.407 30.094l59.063-59.126-24.25-32.344zm78.28 32.688L297 219.968l-65 65.063a728.12 728.12 0 0 0 35 32.376c22.02-23.134 43.764-46.41 64.97-69.406v-35.063zM173.47 313.25c-31.146 40.858-67.877 74.323-108.905 101.875 4.13 13.708 16.394 26.374 30.624 30.563 29.466-41.26 61.113-79.902 100.97-109.97a637.777 637.777 0 0 0-22.688-22.468zM44.5 410.28l-20.844 20.845c7.133 24.65 27.843 44.912 53.72 53.438l19.28-19.313c-26.948-4.28-48.314-26.91-51.875-52.938l-.28-2.03z" fill="#fff" fill-opacity="1" transform="translate(51.2, 51.2) scale(0.8, 0.8) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><defs><linearGradient x1="0" x2="1" y1="1" y2="0" id="delapouite-sparkles-gradient-4"><stop offset="0%" stop-color="#4a4a4a" stop-opacity="1"></stop><stop offset="100%" stop-color="#c9c9c9" stop-opacity="1"></stop></linearGradient><radialGradient id="delapouite-sparkles-gradient-5"><stop offset="0%" stop-color="#9013fe" stop-opacity="1"></stop><stop offset="100%" stop-color="#85562c" stop-opacity="1"></stop></radialGradient><radialGradient id="delapouite-sparkles-gradient-7"><stop offset="0%" stop-color="#9013fe" stop-opacity="1"></stop><stop offset="100%" stop-color="#85562c" stop-opacity="1"></stop></radialGradient></defs><g class="" transform="translate(1,-2)" style=""><path d="M237.4 20.73c-6.1 42.1-26.8 64.2-63.9 64 31.6 4.5 63.8 8 63.9 64.07-.6-46.1 24.5-63.07 64.1-64.07-38-1.5-64.9-16.3-64.1-64zm127.8 11.58c-9.1 14.25-20.8 21.29-38.9 10.28 14.9 11.79 18.6 24.76 10.2 38.97 8.9-11.18 17.5-22.73 39-10.27-17.8-10.06-18.8-23.57-10.3-38.98zM59.68 41.69c-2.7 18.8-12 28.6-28.5 28.5 14.1 2 28.4 3.6 28.5 28.52-.3-20.5 10.9-28.12 28.5-28.52-16.9-.7-28.9-7.3-28.5-28.5zM431 66.28c-2.7 18.8-12 28.6-28.5 28.5 14.1 2 28.4 3.6 28.5 28.52-.3-20.5 10.9-28.12 28.5-28.52-16.9-.7-28.9-7.3-28.5-28.5zM120.3 116.4c-15.8 53.7-47.76 48-79.35 43.4C76.6 170 90.3 197.1 84.28 239.2c12.66-46 42.62-52.6 79.42-43.4-37.6-12.1-56.9-35.4-43.4-79.4zm187 5c-8.8 61.6-39.3 94-93.6 93.7 46.2 6.5 93.6 11.7 93.6 93.7-.8-67.3 35.9-92.2 93.8-93.7-55.5-2.2-94.9-23.9-93.8-93.7zm136.8 38.3c-13.1 21.6-29.5 28.8-49.7 20.1 16.3 9.7 33 19.1 20.1 49.6 10.3-25.2 27.9-28.7 49.7-20-20.3-9.7-31.6-23.9-20.1-49.7zM50.7 243.2c9.16 16.7 7.63 30.1-5.61 40 12.46-6.9 24.85-14.3 39.91 5.6-12.57-16.2-8.2-29 5.61-40-13.92 9.7-27.47 11.6-39.91-5.6zm137.2.3c11.4 26.8-.5 41.3-21.7 50.9 22.7-8.5 40.8-4.5 50.9 21.7-12.7-31.8 4.8-41.2 21.7-50.9-21 8.5-37.8.9-50.9-21.7zm228 12.6c-26.6 64.7-68.7 91.7-127.8 76.4 48.6 19.8 98.8 38.5 76.4 127.9 17.5-73.7 64.4-90.7 127.9-76.5-59.9-17.5-96.9-52-76.5-127.8zM99.94 295.5c15.66 57.8.86 98.1-47.32 118.5 43.46-11.8 87.38-25.2 118.68 47.4-26.4-59.3-3.4-95.4 47.3-118.8-50 19.2-93.1 15-118.66-47.1zm169.36 61c-21.8 20.6-43 23.6-63.2 7.3 15.5 16.3 31.6 32.4 7.2 63.3 19.8-25.6 41.2-24.1 63.3-7.3-20.2-17.4-28.6-37.5-7.3-63.3zM443.2 404c-2.7 18.8-12 28.6-28.5 28.5 14.1 2 28.4 3.6 28.5 28.5-.3-20.5 10.9-28.1 28.5-28.5-16.9-.7-28.9-7.3-28.5-28.5zm-169.7 36c-2.7 18.8-12 28.6-28.5 28.5 14.1 2 28.4 3.6 28.5 28.5-.3-20.5 10.9-28.1 28.5-28.5-16.9-.7-28.9-7.3-28.5-28.5z" fill="#fff" transform="translate(51.2, 51.2) scale(0.8, 0.8) rotate(0, 256, 256) skewX(0) skewY(0)" fill-opacity="1"></path></g></svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,0)" style=""><path d="M256.25 20.313c-108.64 0-196.78 90.592-196.78 202.937 0 84.615 49.994 156.904 121.093 187.438v-16.375c0-25.638-6.2-40.132-13.875-48.47-7.675-8.336-17.567-11.4-27.72-11.937-18.252-.97-32.4-12.266-40.905-27-6.47-11.205-5.975-24.767-.532-36.97 5.444-12.2 15.49-23.71 29.19-33.905 27.394-20.39 69.79-35.56 122.436-35.56 52.702 0 98.475 15.648 129.344 36.218 15.435 10.284 27.24 21.746 34.22 33.968 6.976 12.222 8.93 26.41 2.186 38.094-4.19 7.257-11.026 11.988-18.687 15.938-7.663 3.95-16.085 6.78-24.595 6.78-11.865 0-20.63 2.214-27.438 10.157s-12.437 23.63-12.437 52.688v16.437c71.195-30.488 121.28-102.814 121.28-187.5 0-112.347-88.14-202.938-196.78-202.938zm-76.656 86.718c1.53.02 3.05.078 4.562.157 14.525.766 28.29 4.3 41.063 9.97l17.31 7.687-16.624 9.062-84.062 45.875-8.938-16.405 65.156-35.563c-24.195-5.513-50.92-1.877-82.062 17.532l-9.875-15.844c25.778-16.066 50.528-22.75 73.47-22.47zm150.312 0c22.944-.28 47.722 6.404 73.5 22.47l-9.875 15.844c-31.14-19.41-57.865-23.045-82.06-17.53l65.155 35.56-8.938 16.407-84.062-45.874L267 124.844l17.313-7.688c12.772-5.67 26.506-9.203 41.03-9.97 1.514-.078 3.034-.136 4.563-.155zm-73.594 170.282c-68.947 0-113.104 15.367-116.843 37.907l.5.03c13.487.714 28.843 5.31 40.468 17.938 11.624 12.627 18.812 32.418 18.812 61.125v100.312h113.813V394.312c0-31.4 5.766-51.81 16.937-64.843 11.17-13.034 27.003-16.69 41.625-16.69.352 0 .76-.03 1.156-.06-6.417-22.614-49.872-35.408-116.467-35.408z" fill="#fff" fill-opacity="1"></path></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><polygon points="256,512,0,256,256,0,512,256" fill="#000" fill-opacity="1"></polygon><g class="" transform="translate(8,-12)" style=""><path d="M282.83 18.877c21.567 6.146 36.328 15.205 40.572 28.77a71.007 71.007 0 0 0-4.066 2.363c-25.655 5.807-53.084 18.634-81.047 34.363 20.225-4.69 36.705-4.42 47.544 3.324-5.712 10.3-10.797 22.294-15.123 36.06-21.343 67.922-125.678-80.577-189.065-5.255C41.47 166.24 92.702 212.342 26.5 294.29c35.583-4.14 45.11-9.47 62.416-36.21 10.44-16.13 28.52-22.1 44.668-21.45-12.718 11.206-25.786 30.354-38.21 59.895 19.832-18.528 44.927-38.68 71.603-40.005.912 6.354-2.408 13.74-12.008 21.418C93.21 327.327 15.58 364.185 19.83 476.504c5.558-11.267 11.646-20.31 17.574-28.617 5.98 29.582 28.2 53.8 92.99 40.482-46.928-6.407-76.268-59.586-45.355-82.528 62.716-46.544 128.82 1.436 269.9-75.342a79.832 79.832 0 0 1 7.164-3.46c-2.246 19.6-12.367 39.84-22.362 57.14 14.26-10.38 25.415-20.147 33.928-29.262 2.14 26.14-11.748 54.65-25.393 78.268 43.26-31.49 61.19-57.976 63.207-78.422 9.334 36.678-1.895 95.547-25.03 123.492 77.553-39.433 106.608-77.127 109.76-190.664 1.662-59.824-66.23-60.536-56.435-101.344 11.945-49.756 6.768-84.69-7.565-107.947-19.6-49.73-79.99-59.74-149.385-59.423zM89.8 47.684C54.69 47.534 45.233 83.056 55.724 117c17.146-51.504 70.414-44.24 111.17-34.367-33.282-25.005-58.707-34.87-77.096-34.95zm254.595 30.742c18.643 21.37 29.373 43.02 10.105 65.732-26.562-16.677-26.985-39.252-10.105-65.732zm74.494 48.6c3.655-.013 7.78.35 12.473 1.09-1.706 30.506-14.4 33-46.634 32.154 8.335-22.146 14.416-33.176 34.16-33.245zm-84.677 40.316c9.652.1 20.258 2.84 30.598 8.918 44.65 26.246 21.934 73.314-4.1 74.78-15.174.855 1.443-23.842-16.17-38.476-15.258-12.678-38.596 12.53-45.204-5.78-8.218-22.693 10.21-39.696 34.877-39.442zm60.18 246.168c-24.195 27.825-58.89 60.1-99.444 31.41 16.625 45.643 68.87 70.465 99.443-31.41z" fill="#fff" fill-opacity="1" transform="translate(102.4, 102.4) scale(0.6, 0.6) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

110
assets/ui/resistance.svg Normal file
View File

@@ -0,0 +1,110 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
viewBox="0 0 378.00079 384.97681"
version="1.1"
id="svg23"
sodipodi:docname="resistance.svg"
width="378.00079"
height="384.97681"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
<metadata
id="metadata27">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:title></dc:title>
</cc:Work>
</rdf:RDF>
</metadata>
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1875"
inkscape:window-height="1352"
id="namedview25"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1.4355469"
inkscape:cx="186.7504"
inkscape:cy="196.1768"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg23" />
<defs
id="defs17">
<linearGradient
x1="0"
x2="1"
y1="1"
y2="0"
id="lorc-aura-gradient-4">
<stop
offset="0%"
stop-color="#4a4a4a"
stop-opacity="1"
id="stop2" />
<stop
offset="100%"
stop-color="#c9c9c9"
stop-opacity="1"
id="stop4" />
</linearGradient>
<radialGradient
id="lorc-aura-gradient-5">
<stop
offset="0%"
stop-color="#9013fe"
stop-opacity="1"
id="stop7" />
<stop
offset="100%"
stop-color="#85562c"
stop-opacity="1"
id="stop9" />
</radialGradient>
<radialGradient
id="lorc-aura-gradient-7">
<stop
offset="0%"
stop-color="#9013fe"
stop-opacity="1"
id="stop12" />
<stop
offset="100%"
stop-color="#85562c"
stop-opacity="1"
id="stop14" />
</radialGradient>
</defs>
<g
class=""
transform="translate(-68.2496,-61.8232)"
id="g21">
<path
d="m 320.938,13.28 c -16.646,34.584 -38.466,60.157 -63.094,60.157 -24.522,0 -47.035,-25.275 -63.656,-59.593 0.366,39.358 -9.71,90.884 -30.938,105.125 -21.228,14.24 -49.64,-12.002 -78.844,-32.126 17.455,34.04 42.095,67.5 29.78,92.28 -12.21,24.576 -59.172,35.96 -92.874,35.626 29.338,19.29 78.842,45.803 78.844,74.188 0.002,28.384 -49.504,53.71 -78.844,73 33.702,-0.333 80.663,11.612 92.876,36.187 12.227,24.61 -9.03,56.31 -33.75,85.563 44.826,-15.413 65.142,-5.735 85.374,10.812 h 31.75 C 154.822,459.086 125.5,386.671 125.5,302.936 125.498,184.316 184.42,88.03 256.906,88.03 c 72.488,0 131.406,96.29 131.406,214.907 0,83.74 -29.317,156.153 -72.062,191.563 h 27.313 c 19.847,-14.62 39.796,-25.65 89.687,-9.28 -26.233,-30.264 -42.2,-62.484 -29.97,-87.095 12.257,-24.665 56.658,-36.612 90.533,-36.188 -29.4,-19.297 -75.344,-44.584 -75.344,-73 0,-28.415 45.943,-54.89 75.342,-74.187 -33.874,0.424 -78.273,-10.962 -90.53,-35.625 -12.315,-24.78 9.982,-58.24 27.437,-92.28 -29.202,20.12 -57.583,46.385 -78.845,32.124 -21.262,-14.263 -31.382,-66.13 -30.938,-105.69 z m -68.97,93.75 c -19.56,2.543 -37.343,25.564 -37.343,55.407 0,16.447 5.67,30.986 14,41.032 l 10.156,12.218 -15.593,2.937 c -10.815,2.035 -18.743,7.737 -25.53,17.063 -6.79,9.325 -11.984,22.344 -15.626,37.343 -6.585,27.128 -8.078,60.24 -8.31,89.47 h 36.093 l 0.656,8.656 9.124,122.563 h 76.187 l 8.095,-122.5 0.563,-8.72 h 34.375 c -0.026,-29.592 -0.44,-63.166 -6.407,-90.5 -3.295,-15.095 -8.287,-28.096 -15.156,-37.313 -6.87,-9.216 -15.133,-14.897 -27.28,-16.78 l -15.94,-2.47 10.064,-12.593 c 7.97,-9.996 13.375,-24.36 13.375,-40.406 -0.002,-31.817 -19.884,-55.313 -41.44,-55.313 -2.54,0 -3.96,-0.103 -4.03,-0.094 h -0.03 z"
fill="#ffffff"
fill-opacity="1"
transform="matrix(0.8,0,0,0.8,51.2,51.2)"
id="path19" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -1,4 +1,91 @@
# 13.0
## 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
- concerne la danse, musique, chant, jeu, les oeuvres, la nourriture, les services
- gestion des compétences d'appréciation pour les oeuvres
- pas de jet de moral si la qualité n'est pas suffisante (inférieure au moral,
à la compétence, moral déjà gagné pour la même raison)
- jet d'appréciation avec en option la compétence et la qualité
- jet de moral très heureux (pour Spasme)
- les jets de moral sont liés à des "bon moments"
- la liste des bons moments passés par un acteur est remise à zéro à Château Dormant
- Fenêtre de jet v2
- les possessions sont maintenant gérées avec les fenêtres V2
- on peut choisir sa voie de draconic pour contrer une possession ou conjurer
- La zone de saisie dans les journaux est mieux adaptée
- Correction des bonus de caractéristiques des cyans
## 13.0.20 - L'immobilisme d'Illysis
- Centrage du logo de pause
- Ajout d'un statut malade/empoisonné
- Fenêtre de jet v2
- correction du compteur empoignade
- amélioration des messages liés à l'empoignade
- amélioration des choix de perte d'endurance
- correction de la dépense de rêve sur lancement de sort
- ajustement astrologique sur rituels
## 13.0.19 - L'introspection d'Illysis
- Ajout d'un bouton pour les jets de résistance sous rêve actuel
- Fenêtre de jet v2
- restrictions au propriétaire du personnage
- ouverture de la fenêtre de jets
- appel à la chance
- appel à la destinée
- fermeture par défaut selon le type de jets:
- jets d'attaque
- jets de défense
- jets imposés par un choix d'action
- lancer de sorts
- jets suite à appel à la chance
- gestion des écailles d'efficacité sur les armes
- permettre de faire une attaque même si l'initiative n'est pas faite
- les messages de défense s'affichent correctement avec plusieurs joueurs
- les particulières en force/rapidité sont correctement affichées dans le tchat
- l'expérience sur jet de résistance est limitée à 1 point
## 13.0.18 - Le reflet d'Illysis
- Mise à jour de la feuille de personnage pdf template (avec police correcte)
- Ajout d'une icône "écurie" pour les services des commerces & auberges
- Suppression de message d'erreur sur compétence
manquante à l'ouverture des acteurs d'invocation
## 13.0.17 - Le chant d'Illysis
- Corrections CSS
- Migration Uberwald -> Scriptarium
## 13.0.16 - La paix d'Illysis
- Export de personnages sous forme de feuille de personnage pdf
@@ -98,7 +185,7 @@
- ajout d'un status "Force insuffisante"
- clarification des maladresses à l'attaque (en demi surprise, ou à cause d'un échec total)
- Nouvelle fenêtre de jets de dés
- ajout du statut "Force insuffisante" aux acteurs si la
- ajout du statut "Force insuffisante" aux acteurs si la
force est insuffisante pour l'arme
- avancement du mode attaque
- choix de tactique

View File

@@ -60,10 +60,14 @@
/* Fonts */
.sheet header.sheet-header h1 input,
.window-app .window-header,
#actors .directory-list,
#navigation #scene-list .scene.nav-item {
#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,
@@ -71,17 +75,16 @@
.sheet header.sheet-header .flex-group-center.flex-fatigue,
select,
.item-checkbox,
#sidebar,
#players,
#navigation #nav-toggle {
#players {
font-family: "CaslonAntique";
/* For sheet parts; For nav and title */
}
:root {
body {
/* =================== 2. DEBUGGING HIGHLIGHTERS ============ */
/* =================== 3. some constants ============ */
--fieldset-background: url(/ui/parchment.jpg);
--rdd-color-text-primary: hsla(0, 0%, 4%, 0.9);
--color-text-primary: hsla(0, 0%, 4%, 0.9);
--rdd-input-background: hsla(0, 0%, 0%, 0.1);
--rdd-color-border-input: hsla(0, 0%, 0%, 0.2);
--rdd-bg-input: hsla(0, 0%, 100%, 0.1);
@@ -99,7 +102,9 @@ select,
--gradient-warning: linear-gradient(150deg, hsla(32, 100%, 50%, 0.3), hsla(52, 60%, 50%, 0.1), hsla(32, 60%, 50%, 0.1), hsla(32, 100%, 50%, 0.3));
--gradient-silver-light: linear-gradient(30deg, rgba(61, 55, 93, 0.2), rgba(178, 179, 196, 0.1), rgba(59, 62, 63, 0.2), rgba(206, 204, 199, 0.1), rgba(61, 46, 49, 0.2));
--gradient-daylight: conic-gradient(from 0deg, hsla(50, 100%, 80%, 0.7), hsla(30, 30%, 40%, 0.1) 25%, hsla(250, 50%, 40%, 0.1) 25%, hsla(250, 30%, 30%, 0.7) 50%, hsla(250, 50%, 40%, 0.1) 75%, hsla(30, 30%, 40%, 0.1) 75%, hsla(50, 100%, 80%, 0.7));
--background-custom-button: linear-gradient(to bottom, hsla(208, 38%, 21%, 0.988) 5%, hsla(202, 42%, 14%, 0.671) 100%);
--background-color-button: hsl(25, 5%, 60%);
--background-color-custom-button: hsla(208, 38%, 21%, 0.988);
--background-custom-button: linear-gradient(to bottom, var(--background-color-custom-button) 5%, hsla(202, 42%, 14%, 0.671) 100%);
--background-custom-button-hover: linear-gradient(to bottom, hsl(0, 100%, 25%) 5%, hsl(0, 97%, 12%) 100%);
--background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%);
--background-tooltip: hsla(60, 12%, 85%, 0.95);
@@ -593,6 +598,9 @@ select,
font-size: 1.2rem;
font-weight: bold;
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section[name="resistance"] {
align-items: flex-end;
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section {
display: flex;
flex-direction: row;
@@ -607,6 +615,12 @@ select,
margin: 0 1rem;
padding: 0;
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section img.flag-resistance {
max-width: 1.5rem;
max-height: 1.5rem;
text-align: right;
filter: invert(0.6);
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions {
display: flex;
flex-direction: column;
@@ -674,7 +688,7 @@ select,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat {
font-family: CaslonAntique;
display: grid;
grid-template-areas: "img header buttons" "img resume buttons" "details details details" "actions actions actions";
grid-template-areas: "img header buttons" "img resume buttons" "details details details" "description description description" "actions actions actions";
grid-template-columns: 3rem 1fr 1.4rem;
grid-template-rows: max-content max-content max-content max-content;
gap: 0 0.5rem;
@@ -730,6 +744,17 @@ select,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-actions a img {
margin-right: 0.5rem;
}
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-description,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-description {
grid-area: description;
text-align: justify;
display: flex;
flex-direction: column;
}
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-description div,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-description div {
display: block;
}
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-buttons {
grid-area: buttons;
@@ -938,6 +963,13 @@ select,
flex-basis: inherit;
flex: "flex-shrink";
}
.system-foundryvtt-reve-de-dragon :is(section.scenes-sidebar, section.compendium-sidebar) li.directory-item.folder a {
text-shadow: 1px 1px 2px var(--rdd-color-text-primary);
color: var(--color-background-chat-message);
}
.system-foundryvtt-reve-de-dragon :is(section.scenes-sidebar, section.compendium-sidebar) li.directory-item.folder a:hover {
text-shadow: 1px 0px 0px #ff6600;
}
.system-foundryvtt-reve-de-dragon .tabs .item.active,
.system-foundryvtt-reve-de-dragon .blessures-list li ul li:first-child:hover,
.system-foundryvtt-reve-de-dragon i.moral-radio-checkmark-off:hover,
@@ -1373,12 +1405,22 @@ select,
margin-inline: 0.1rem;
margin-block: 0.1rem;
}
.system-foundryvtt-reve-de-dragon .prosemirror menu {
background-color: var(--color-background-chat-message);
}
.system-foundryvtt-reve-de-dragon .app.sheet fieldset :is(label, input) {
font-family: CaslonAntique;
text-align: justify;
font-size: 1rem;
letter-spacing: 1px;
}
.system-foundryvtt-reve-de-dragon .app.sheet input.attribute-value {
background-color: rgba(0, 0, 0, 0.05);
border: 1px solid var(--color-border-light-tertiary);
padding: 1px 3px;
height: var(--form-field-height);
border-radius: 3px;
}
.system-foundryvtt-reve-de-dragon .app.sheet div.form-group {
clear: both;
display: flex;
@@ -1387,19 +1429,22 @@ select,
margin: 0.1rem 0;
align-items: center;
}
.system-foundryvtt-reve-de-dragon .prosemirror menu {
background-color: var(--color-background-chat-message);
}
.system-foundryvtt-reve-de-dragon .app.sheet .editor.prosemirror {
height: fit-content;
min-height: 5rem;
min-height: 6rem;
}
.system-foundryvtt-reve-de-dragon .app.sheet .editor.prosemirror .editor-container {
min-height: 5rem;
height: 8rem;
min-height: 6rem;
height: calc(100% - 3rem);
margin: 0;
flex: none;
}
.system-foundryvtt-reve-de-dragon .app.sheet.journal-entry-page .editor.prosemirror {
height: 100%;
}
.system-foundryvtt-reve-de-dragon .app.sheet.journal-entry-page .editor.prosemirror .editor-container {
height: calc(100% - 6rem);
}
.system-foundryvtt-reve-de-dragon .large-editor {
border: 2;
height: fit-content;
@@ -1409,18 +1454,18 @@ select,
.system-foundryvtt-reve-de-dragon .editor {
border: 2;
height: fit-content;
min-height: 5rem;
min-height: 6rem;
padding: 0 3px;
}
.system-foundryvtt-reve-de-dragon .medium-editor {
border: 2;
min-height: 8rem;
min-height: 9rem;
padding: 0 3px;
align-items: top;
}
.system-foundryvtt-reve-de-dragon .small-editor {
border: 2;
min-height: 2rem;
min-height: 4rem;
padding: 0 3px;
}
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon.sheet :is(.large-editor, .editor, .medium-editor, .small-editor) {
@@ -1598,28 +1643,18 @@ select,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar .permissions-list,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs,
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs button,
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs button,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs button,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs button .count,
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs button .count,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs button .count,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs {
color: var(--rdd-color-text-primary);
}
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body button .count,
.system-foundryvtt-reve-de-dragon .application .window-content button .count,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar button .count,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body button,
.system-foundryvtt-reve-de-dragon .application .window-content button,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar button {
background-color: var(--background-color-button);
color: var(--rdd-color-text-primary);
}
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body a,
.system-foundryvtt-reve-de-dragon .application .window-content a,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar a {
color: var(--color-dark-3);
}
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body a.filter.active,
.system-foundryvtt-reve-de-dragon .application .window-content a.filter.active,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar a.filter.active {
color: var(--color-dark-1);
}
.system-foundryvtt-reve-de-dragon .window-app .window-content {
background: url(../assets/ui/bg_left.webp) no-repeat left top;
color: var(--rdd-color-text-primary);
@@ -2191,7 +2226,7 @@ select,
.system-foundryvtt-reve-de-dragon #sidebar-tabs > .collapsed,
.system-foundryvtt-reve-de-dragon #chat-controls .chat-control-icon {
color: rgba(220, 220, 220, 0.75);
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.75);
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.75);
}
.system-foundryvtt-reve-de-dragon .sidebar-tab .directory-list .entity {
border-top: 1px dashed rgba(0, 0, 0, 0.25);
@@ -2800,24 +2835,6 @@ select,
.system-foundryvtt-reve-de-dragon aside#tooltip .toolclip p.faint {
color: var(--color-tooltip-faint);
}
.system-foundryvtt-reve-de-dragon .chat-card-button,
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed {
border-radius: 0.2rem;
cursor: pointer;
font-family: CaslonPro;
font-size: 0.9rem;
padding: 0.2rem 0.4rem 0rem 0.4rem;
text-decoration: none;
position: relative;
margin: 0.3rem;
border: 2px ridge #846109;
display: inline-block;
}
.system-foundryvtt-reve-de-dragon .chat-card-button img,
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed img {
max-width: 1rem;
max-height: 1rem;
}
.system-foundryvtt-reve-de-dragon .chat-card-info {
font-size: 1.1rem;
display: flex;
@@ -2832,14 +2849,42 @@ select,
.system-foundryvtt-reve-de-dragon .jet-astrologie {
color: var(--major-button-color) !important;
}
.system-foundryvtt-reve-de-dragon .chat-card-button,
.system-foundryvtt-reve-de-dragon .chat-card-button-checked,
.system-foundryvtt-reve-de-dragon select.chat-card-select {
border-radius: 0.2rem;
cursor: pointer;
font-family: CaslonPro;
font-size: 0.9rem;
padding: 0.2rem 0.4rem 0rem 0.4rem;
text-decoration: none;
position: relative;
margin: 0.3rem;
border: 2px ridge #846109;
display: inline-block;
}
.system-foundryvtt-reve-de-dragon .chat-card-button img,
.system-foundryvtt-reve-de-dragon .chat-card-button-checked img,
.system-foundryvtt-reve-de-dragon select.chat-card-select img {
max-width: 1rem;
max-height: 1rem;
}
.system-foundryvtt-reve-de-dragon select.chat-card-select {
width: calc(100% - 0.6rem);
color: var(--major-button-color);
background-color: var(--background-color-custom-button);
}
.system-foundryvtt-reve-de-dragon select.chat-card-select option {
background-color: var(--background-color-custom-button);
}
.system-foundryvtt-reve-de-dragon .chat-card-button {
text-shadow: 1px 1px #4d3534;
box-shadow: inset 1x 1px #a6827e;
color: var(--major-button-color) !important;
color: var(--major-button-color);
background: var(--background-custom-button);
background-color: #7d5d3b00;
background-color: var(--background-color-custom-button);
}
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed {
.system-foundryvtt-reve-de-dragon .chat-card-button-checked {
text-shadow: 1px 1px hsla(202, 30%, 70%, 0.5);
box-shadow: inset -1px -1px #a6827e;
color: hsla(202, 42%, 14%, 0.7);
@@ -2849,11 +2894,11 @@ select,
.system-foundryvtt-reve-de-dragon .chat-card-button:hover {
background: var(--background-custom-button-hover);
}
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed:hover {
.system-foundryvtt-reve-de-dragon .chat-card-button-checked:hover {
background: var(--background-custom-button-hover);
}
.system-foundryvtt-reve-de-dragon .chat-card-button:active,
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed:active {
.system-foundryvtt-reve-de-dragon .chat-card-button-checked:active {
position: relative;
top: 1px;
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.3 KiB

View File

@@ -63,6 +63,7 @@
"StatusUnarmed": "Désarmé",
"StatusGrappling": "Empoignade",
"StatusGrappled": "Empoigné",
"StatusMalade": "Malade",
"StatusRestrained": "Immobilisé",
"StatusComma": "Comma",
"StatusDead": "Mort",

View File

@@ -1,4 +1,4 @@
:root {
body {
/* =================== 2. DEBUGGING HIGHLIGHTERS ============ */
// --debug-background-color-red: #ff000054;
@@ -13,6 +13,7 @@
/* =================== 3. some constants ============ */
--fieldset-background: url(/ui/parchment.jpg);
--rdd-color-text-primary: hsla(0, 0%, 4%, 0.9);
--color-text-primary: hsla(0, 0%, 4%, 0.9);
--rdd-input-background:hsla(0, 0%, 0%, 0.1);
--rdd-color-border-input: hsla(0, 0%, 0%, 0.2);
--rdd-bg-input: hsla(0, 0%, 100%, 0.1);
@@ -44,7 +45,9 @@
hsla(50, 100%, 80%, 0.7)
);
--background-custom-button: linear-gradient(to bottom, hsla(208, 38%, 21%, 0.988) 5%, hsla(202, 42%, 14%, 0.671) 100%);
--background-color-button: hsl(25, 5%, 60%);
--background-color-custom-button: hsla(208, 38%, 21%, 0.988);
--background-custom-button: linear-gradient(to bottom, var(--background-color-custom-button) 5%, hsla(202, 42%, 14%, 0.671) 100%);
--background-custom-button-hover: linear-gradient(to bottom, hsla(0, 100%, 25%, 1) 5%, hsla(0, 97%, 12%, 1) 100%);
--background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%);
--background-tooltip: hsla(60, 12%, 85%, 0.95);

View File

@@ -70,9 +70,12 @@
/* Fonts */
.sheet header.sheet-header h1 input,
.window-app .window-header,
#actors .directory-list,
#navigation #scene-list .scene.nav-item {
font-family: "GoudyAcc"
#sidebar {
font-family: "GoudyAcc";
.chat-message{
font-family: "CaslonAntique";
}
}
/* For title, sidebar character and scene */
@@ -80,6 +83,6 @@
.window-app input,
.sheet header.sheet-header .header-compteurs,
.sheet header.sheet-header .flex-group-center.flex-fatigue,
select, .item-checkbox, #sidebar, #players, #navigation #nav-toggle {
select, .item-checkbox, #players {
font-family: "CaslonAntique"; /* For sheet parts; For nav and title */
}

View File

@@ -216,7 +216,15 @@
}
/* =================== Autres ============ */
:is(section.scenes-sidebar, section.compendium-sidebar) li.directory-item.folder {
a {
text-shadow: 1px 1px 2px var(--rdd-color-text-primary);
color: var( --color-background-chat-message);
}
a:hover {
text-shadow: 1px 0px 0px #ff6600;
}
}
.tabs .item.active,
.blessures-list li ul li:first-child:hover,
i.moral-radio-checkmark-off:hover,
@@ -681,6 +689,7 @@
}
}
}
fieldset {
border-style: groove;
border-width: 0.1rem;
@@ -689,36 +698,56 @@
margin-inline: 0.1rem;
margin-block: 0.1rem;
}
.app.sheet fieldset :is(label, input) {
font-family: CaslonAntique;
text-align: justify;
font-size: 1rem;
letter-spacing: 1px;
}
.app.sheet div.form-group {
clear: both;
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0.1rem 0;
align-items: center;
}
.prosemirror {
menu {
background-color: var(--color-background-chat-message);
}
}
.app.sheet .editor.prosemirror {
height: fit-content;
min-height: 5rem;
}
.app.sheet .editor.prosemirror .editor-container {
min-height: 5rem;
height: 8rem;
margin: 0;
flex: none;
.app.sheet{
fieldset :is(label, input) {
font-family: CaslonAntique;
text-align: justify;
font-size: 1rem;
letter-spacing: 1px;
}
input.attribute-value {
background-color: rgba(0, 0, 0, 0.05);
border: 1px solid var(--color-border-light-tertiary);
padding: 1px 3px;
height: var(--form-field-height);
border-radius: 3px;
}
div.form-group {
clear: both;
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin: 0.1rem 0;
align-items: center;
}
.editor.prosemirror {
height: fit-content;
min-height: 6rem;
.editor-container {
min-height: 6rem;
height: calc(100% - 3rem);
margin: 0;
flex: none;
}
}
}
.app.sheet.journal-entry-page .editor.prosemirror{
height: 100%;
.editor-container {
height: calc(100% - 6rem);
}
}
.large-editor {
border: 2;
@@ -730,20 +759,20 @@
.editor {
border: 2;
height: fit-content;
min-height: 5rem;
min-height: 6rem;
padding: 0 3px;
}
.medium-editor {
border: 2;
min-height: 8rem;
min-height: 9rem;
padding: 0 3px;
align-items: top;
}
.small-editor {
border: 2;
min-height: 2rem;
min-height: 4rem;
padding: 0 3px;
}
@@ -934,20 +963,14 @@
.journal-entry .journal-sidebar {
background: url(../assets/ui/bg_left.webp) no-repeat left top;
color: var(--rdd-color-text-primary);
label,
.hint,
.permissions-list,
nav.tabs,
nav.tabs button,
nav.tabs button .count,
button {
label, .hint, .permissions-list, nav.tabs {
color: var(--rdd-color-text-primary);
}
a {
color: var(--color-dark-3);
}
a.filter.active {
color: var(--color-dark-1);
button .count,
button {
background-color: var(--background-color-button);
color: var(--rdd-color-text-primary);
}
}
@@ -1590,7 +1613,7 @@
#sidebar-tabs > .collapsed,
#chat-controls .chat-control-icon {
color: rgba(220, 220, 220, 0.75);
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.75);
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.75);
}
.sidebar-tab .directory-list .entity {
@@ -2264,24 +2287,6 @@
color: var(--color-tooltip-faint);
}
.chat-card-button,
.chat-card-button-pushed {
border-radius: 0.2rem;
cursor: pointer;
font-family: CaslonPro;
font-size: 0.9rem;
padding: 0.2rem 0.4rem 0rem 0.4rem;
text-decoration: none;
position: relative;
margin: 0.3rem;
border: 2px ridge #846109;
display: inline-block;
img {
max-width: 1rem;
max-height: 1rem;
}
}
.chat-card-info {
font-size: 1.1rem;
display: flex;
@@ -2298,16 +2303,47 @@
.jet-astrologie {
color: var(--major-button-color) !important;
}
.chat-card-button,
.chat-card-button-checked,
select.chat-card-select {
border-radius: 0.2rem;
cursor: pointer;
font-family: CaslonPro;
font-size: 0.9rem;
padding: 0.2rem 0.4rem 0rem 0.4rem;
text-decoration: none;
position: relative;
margin: 0.3rem;
border: 2px ridge #846109;
display: inline-block;
img {
max-width: 1rem;
max-height: 1rem;
}
}
select.chat-card-select {
width: calc(100% - 0.6rem);
color: var(--major-button-color);
background-color: var(--background-color-custom-button);
option {
background-color: var(--background-color-custom-button);
}
}
.chat-card-button {
text-shadow: 1px 1px #4d3534;
box-shadow: inset 1x 1px #a6827e;
color: var(--major-button-color) !important;
color: var(--major-button-color);
background: var(--background-custom-button);
background-color: #7d5d3b00;
background-color: var(--background-color-custom-button);
}
.chat-card-button-pushed {
.chat-card-button-checked {
text-shadow: 1px 1px hsla(202, 30%, 70%, 0.5);
box-shadow: inset -1px -1px #a6827e;
color: hsla(202, 42%, 14%, 0.7);
@@ -2319,12 +2355,12 @@
background: var(--background-custom-button-hover);
}
.chat-card-button-pushed:hover {
.chat-card-button-checked:hover {
background: var(--background-custom-button-hover);
}
.chat-card-button:active,
.chat-card-button-pushed:active {
.chat-card-button-checked:active {
position: relative;
top: 1px;
}

View File

@@ -6,7 +6,9 @@
"img header buttons"
"img resume buttons"
"details details details"
"actions actions actions";
"description description description"
"actions actions actions"
;
grid-template-columns: 3rem 1fr 1.4rem;
grid-template-rows: max-content max-content max-content max-content;
gap: 0 0.5rem;
@@ -53,6 +55,15 @@
}
}
}
div.chat-description {
grid-area: description;
text-align: justify;
display: flex;
flex-direction: column;
div {
display: block;
}
}
div.chat-buttons {
grid-area: buttons;

View File

@@ -160,6 +160,9 @@
font-size: 1.2rem;
font-weight: bold;
roll-section[name="resistance"] {
align-items: flex-end;
}
roll-section {
display: flex;
flex-direction: row;
@@ -174,6 +177,12 @@
margin: 0 1rem;
padding: 0;
}
img.flag-resistance {
max-width: 1.5rem;
max-height: 1.5rem;
text-align: right;
filter: invert(0.6);
}
}
}

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";
@@ -18,6 +18,7 @@ import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js";
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";
/* -------------------------------------------- */
/**
@@ -57,7 +58,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
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);
@@ -208,7 +209,8 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
}
// Points de reve actuel
this.html.find('.roll-reve-actuel').click(async event => await this.actor.rollCarac(CARACS.REVE_ACTUEL, { resistance: true }))
this.html.find('.roll-reve-actuel').click(async event => await this.actor.rollReveActuel({ resistance: false }))
this.html.find('.button-reve-resistance').click(async event => await this.actor.rollReveActuel({ diff: -8, resistance: true }))
this.html.find('.action-empoignade').click(async event => await RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor)))
this.html.find('.roll-arme').click(async event => {
@@ -274,9 +276,9 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
this.html.find('.seuil-reve-value').change(async event => await this.actor.setPointsDeSeuil(event.currentTarget.value))
this.html.find('.stress-test').click(async event => await this.actor.transformerStress())
this.html.find('.moral-malheureux').click(async event => await this.actor.jetDeMoral('malheureuse'))
this.html.find('.moral-neutre').click(async event => await this.actor.jetDeMoral('neutre'))
this.html.find('.moral-heureux').click(async event => await this.actor.jetDeMoral('heureuse'))
this.html.find('.moral-malheureux').click(async event => await this.actor.jetDeMoral(MORAL.MALHEUREUX))
this.html.find('.moral-neutre').click(async event => await this.actor.jetDeMoral(MORAL.NEUTRE))
this.html.find('.moral-heureux').click(async event => await this.actor.jetDeMoral(MORAL.HEUREUX))
this.html.find('.button-ethylisme').click(async event => await this.actor.jetEthylisme())
this.html.find('.ptreve-actuel-plus').click(async event => await this.actor.reveActuelIncDec(1))

View File

@@ -41,18 +41,20 @@ import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemSigneDraconique } from "./item/signedraconique.js";
import { RdDRencontre } from "./item/rencontre.js";
import { DialogSelect } from "./dialog-select.js";
import { PAS_DE_DRACONIC, POSSESSION_SANS_DRACONIC } from "./item/base-items.js";
import { CATEGORIES_COMPETENCES, PAS_DE_DRACONIC, POSSESSION_SANS_DRACONIC } from "./item/base-items.js";
import { RdDRollResult } from "./rdd-roll-result.js";
import { RdDInitiative } from "./initiative.mjs";
import RollDialog from "./roll/roll-dialog.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2, ROLL_DIALOG_V2_TEST } from "./settings/options-avancees.js";
import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
import { ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_SORT } from "./roll/roll-constants.mjs";
import { PART_TACHE } from "./roll/roll-part-tache.mjs";
import { PART_COMP } from "./roll/roll-part-comp.mjs";
import { PART_OEUVRE } from "./roll/roll-part-oeuvre.mjs";
import { PART_CUISINE } from "./roll/roll-part-cuisine.mjs";
import { PART_SORT } from "./roll/roll-part-sort.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']
@@ -131,11 +133,6 @@ export class RdDActor extends RdDBaseActorSang {
return etatGeneral
}
/* -------------------------------------------- */
getActivePoisons() {
return foundry.utils.duplicate(this.items.filter(item => item.type == 'poison' && item.system.active))
}
/* -------------------------------------------- */
getMalusArmure() {
return this.itemTypes[ITEM_TYPES.armure].filter(it => it.system.equipe)
@@ -166,12 +163,15 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
getDemiReve() { return this.system.reve.tmrpos.coord }
getDraconics() { return this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == 'draconic') }
getDraconics() {
return this.isHautRevant()
? this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == CATEGORIES_COMPETENCES.draconic.key)
: []
}
getBestDraconic() { return foundry.utils.duplicate([...this.getDraconics(), PAS_DE_DRACONIC].sort(Misc.descending(it => it.system.niveau)).find(it => true)) }
getDraconicOuPossession() {
return [...this.getDraconics().filter(it => it.system.niveau >= 0), POSSESSION_SANS_DRACONIC]
.sort(Misc.descending(it => it.system.niveau))
.find(it => true)
getConjurationNaturelle() {
return new RdDItemCompetence(POSSESSION_SANS_DRACONIC)
}
isForceInsuffisante(forceRequise) {
@@ -190,7 +190,10 @@ export class RdDActor extends RdDBaseActorSang {
const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
const ecaillesEfficacite = arme.system.magique ? arme.system.ecaille_efficacite : 0;
const comp = this.getCompetence(arme.getCompetenceAction(main))
const comp = this.getCompetence(arme.getCompetenceAction(main), { onMessage: message => { console.info(message) } })
if (!comp) {
return
}
const unique = [comp.id, arme.name, dommages, forceRequise, ecaillesEfficacite].join('|');
if (uniques.includes(unique)) {
return
@@ -203,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,
@@ -215,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)
@@ -330,10 +335,6 @@ export class RdDActor extends RdDBaseActorSang {
await this._recupererVie(message, isMaladeEmpoisonne);
}
getMaladiesPoisons() {
return this.items.filter(item => item.type == 'maladie' || (item.type == 'poison' && item.system.active));
}
_messageRecuperationMaladiePoisons(maladiesPoisons, message) {
if (maladiesPoisons.length > 0) {
const identifies = maladiesPoisons.filter(it => it.system.identifie);
@@ -365,15 +366,15 @@ export class RdDActor extends RdDBaseActorSang {
content: ""
};
await this._recuperationSante(message);
await this._recupereMoralChateauDormant(message);
await this._recupereChance();
await this.transformerStress();
await this.retourSeuilDeReve(message);
await this.setBonusPotionSoin(0);
await this.retourSust(message);
await this.$perteReveEnchantementsChateauDormants();
await this.$suppressionLancementsSort();
await this._recuperationSante(message)
await this._recupereMoralChateauDormant(message)
await this._recupereChance()
await this.transformerStress()
await this.retourSeuilDeReve(message)
await this.setBonusPotionSoin(0)
await this.retourSust(message)
await this.$perteReveEnchantementsChateauDormants()
await this.$suppressionLancementsSort()
await RdDCoeur.applyCoeurChateauDormant(this, message);
if (message.content != "") {
message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`;
@@ -417,11 +418,13 @@ export class RdDActor extends RdDBaseActorSang {
}
async _recupereMoralChateauDormant(message) {
await this.update({ 'system.compteurs.bonmoments': [] }, { render: false })
if (!ReglesOptionnelles.isUsing("recuperation-moral")) { return }
const etatMoral = this.system.sommeil?.moral ?? 'neutre';
const jetMoral = await this._jetDeMoral(etatMoral);
message.content += ` -- le jet de moral est ${etatMoral}, le moral ` + this._messageAjustementMoral(jetMoral.ajustement);
const etatMoral = this.system.sommeil?.moral ?? MORAL.NEUTRE
const jetMoral = await this._jetDeMoral(etatMoral)
message.content += ` -- le jet de moral est ${etatMoral}, le moral ` + this._messageAjustementMoral(jetMoral.ajustement)
}
_messageAjustementMoral(ajustement) {
@@ -695,7 +698,7 @@ export class RdDActor extends RdDBaseActorSang {
const rencontre = await game.system.rdd.rencontresTMR.getReveDeDragon(force);
let rollData = {
actor: this,
competence: this.getDraconicOuPossession(),
competence: this.getDraconicOuPossession().find(it => true),
canClose: false,
rencontre: rencontre,
tmr: true,
@@ -1089,12 +1092,13 @@ export class RdDActor extends RdDBaseActorSang {
}
$createSortReserve(sort) {
const ptReve = Number.isInteger(sort.system.ptreve) ? Number(sort.system.ptreve) :Number(sort.system.ptreve.match(/\d+/))
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 })
}
@@ -1198,17 +1202,21 @@ export class RdDActor extends RdDBaseActorSang {
}
/* -------------------------------------------- */
async jetDeMoral(situation, messageReussi = undefined, messageManque = undefined) {
const jetMoral = await this._jetDeMoral(situation);
const finMessage = (jetMoral.succes ? messageReussi : messageManque) ?? (jetMoral.ajustement == 0 ? "Vous gardez votre moral" : jetMoral.ajustement > 0 ? "Vous gagnez du moral" : "Vous perdez du moral");
async jetDeMoral(situation, bonmoment = "") {
if (bonmoment != "" && bonmoment != undefined && this.system.compteurs.bonmoments.includes(bonmoment)) {
ui.notifications.info(`${this.name} a déjà gagné du moral après avoir passé un bon moment (${bonmoment}) pendant la journée, pas de gain de moral`)
return
}
const jetMoral = await this._jetDeMoral(situation, bonmoment)
const finMessage = (jetMoral.ajustement == 0 ? "Vous gardez votre moral" : jetMoral.ajustement > 0 ? "Vous gagnez du moral" : "Vous perdez du moral");
ChatMessage.create({
whisper: ChatUtility.getOwners(this),
content: `${finMessage} - jet ${jetMoral.succes ? "réussi" : "manqué"} en situation ${situation} (${jetMoral.jet}/${jetMoral.difficulte}).`
});
return jetMoral.ajustement;
content: `${finMessage} - jet ${jetMoral.succes ? "réussi" : "manqué"} en situation ${SITUATION_MORAL[situation] ?? situation} (${jetMoral.jet}/${jetMoral.difficulte}).`
})
return jetMoral.ajustement
}
async _jetDeMoral(situation) {
async _jetDeMoral(situation, bonmoment = "") {
const moralActuel = Misc.toInt(this.system.compteurs.moral.value);
const jet = await RdDDice.rollTotal("1d20");
const difficulte = 10 + moralActuel;
@@ -1220,14 +1228,18 @@ export class RdDActor extends RdDBaseActorSang {
difficulte: difficulte,
succes: succes,
ajustement: this._calculAjustementMoral(succes, moralActuel, situation)
};
await this.moralIncDec(jetMoral.ajustement);
}
await this.moralIncDec(jetMoral.ajustement, bonmoment);
return jetMoral;
}
/* -------------------------------------------- */
async moralIncDec(ajustementMoral) {
async moralIncDec(ajustementMoral, bonmoment = "") {
if (ajustementMoral != 0) {
if (ajustementMoral > 0 && bonmoment != "" && bonmoment != undefined) {
const bonmoments = [...this.system.compteurs.bonmoments, bonmoment]
await this.update({ 'system.compteurs.bonmoments': bonmoments }, { render: false })
}
const startMoral = parseInt(this.system.compteurs.moral.value)
const moralTheorique = startMoral + ajustementMoral
if (moralTheorique > 3) { // exaltation
@@ -1248,13 +1260,14 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
_calculAjustementMoral(succes, moral, situation) {
switch (situation) {
case 'heureux': case 'heureuse': return succes ? 1 : 0;
case 'malheureuse': case 'malheureux': return succes ? 0 : -1;
case 'neutre':
if (succes && moral < 0) return 1;
if (!succes && moral > 0) return -1;
case MORAL.TRESHEUREUX: return succes ? 2 : 1
case MORAL.HEUREUX: case 'heureuse': return succes ? 1 : 0
case MORAL.MALHEUREUX: case 'malheureuse': return succes ? 0 : -1
case MORAL.NEUTRE:
if (succes && moral < 0) return 1
if (!succes && moral > 0) return -1
}
return 0;
return 0
}
/* -------------------------------------------- */
@@ -1313,33 +1326,31 @@ export class RdDActor extends RdDBaseActorSang {
}
const item = this.getItem(itemId)
if (!item.getUtilisationCuisine()) {
return;
return
}
if (choix.doses > item.system.quantite) {
ui.notifications.warn(`Il n'y a pas assez de ${item.name} pour manger ${choix.doses}`)
return;
return
}
if (!this._apprecierCuisine(item, choix.seForcer)) {
ui.notifications.info(`${this.name} ne n'arrive pas à manger de ${item.name}`)
return;
}
await this.manger(item, choix.doses, { diminuerQuantite: false });
await this.boire(item, choix.doses, { diminuerQuantite: false });
await item.diminuerQuantite(choix.doses, choix);
}
async _apprecierCuisine(item, seForcer) {
const surmonteExotisme = await this._surmonterExotisme(item, seForcer);
if (surmonteExotisme) {
await this.apprecier(CARACS.ODORATGOUT, 'cuisine', item.system.qualite, item.system.boisson ? "apprécie la boisson" : "apprécie le plat");
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 (await this._surmonterExotisme(item)) {
const appreciation = item.system.appreciation;
new Apprecier(this, appreciation, item.system.qualite)
.apprecier(onManger)
}
else if (seForcer) {
await this.jetDeMoral('malheureux');
else if (choix.seForcer) {
await this.jetDeMoral(MORAL.MALHEUREUX)
await Promise.all(onManger.map(async callback => await callback()))
}
else {
return false;
ui.notifications.info(`${this.name} ne n'arrive pas à manger de ${item.name}`)
}
return true;
}
/* -------------------------------------------- */
@@ -1365,7 +1376,7 @@ export class RdDActor extends RdDBaseActorSang {
}
const rolled = await this.doRollCaracCompetence(carac, undefined, 0, { title });
if (rolled?.isSuccess) {
await this.jetDeMoral('heureux');
await this.jetDeMoral(MORAL.HEUREUX);
}
}
@@ -1432,7 +1443,7 @@ export class RdDActor extends RdDBaseActorSang {
ethylismeData.perteEndurance = await this.santeIncDec("endurance", -perte);
if (!ethylisme.jet_moral) {
ethylismeData.jetMoral = await this._jetDeMoral('heureuse');
ethylismeData.jetMoral = await this._jetDeMoral(MORAL.HEUREUX, "Ethylisme");
if (ethylismeData.jetMoral.ajustement == 1) {
ethylismeData.moralAlcool = 'heureux';
ethylisme.jet_moral = true;
@@ -1440,7 +1451,7 @@ export class RdDActor extends RdDBaseActorSang {
ethylismeData.jetMoral.ajustement = -1;
ethylismeData.moralAlcool = 'triste';
ethylisme.jet_moral = true;
await this.moralIncDec(-1);
await this.moralIncDec(-1, "Ethylisme");
}
}
if (ethylisme.value < 0) {
@@ -1634,7 +1645,8 @@ export class RdDActor extends RdDBaseActorSang {
return
}
hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM)
let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence, rollData.jetResistance);
let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence,
rollData.v2 ? rollData.type.resistance : rollData.jetResistance);
if (xpData.length) {
const content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-gain-xp.hbs`, {
actor: this,
@@ -1732,16 +1744,16 @@ export class RdDActor extends RdDBaseActorSang {
type: { allowed: [ROLL_TYPE_SORT], current: ROLL_TYPE_SORT }
};
const dialog = await RollDialog.create(rollData, {
callbacks: [roll => {
this.tmrApp?.restoreTMRAfterAction();
callbacks: [async roll => {
await this.tmrApp?.restoreTMRAfterAction();
if (roll.closeTMR) {
this.tmrApp?.close();
await this.tmrApp?.close();
this.tmrApp = undefined;
}
}],
onRollDone: RollDialog.onRollDoneClose,
onClose: () => {
this.tmrApp?.restoreTMRAfterAction();
onClose: async () => {
await this.tmrApp?.restoreTMRAfterAction();
}
});
this.tmrApp?.setTMRPendingAction(dialog);
@@ -1942,8 +1954,7 @@ export class RdDActor extends RdDBaseActorSang {
diff: { value: diff ?? 0 }
}
}
RollDialog.create(rollData, foundry.utils.mergeObject(options, { onRollDone: RollDialog.onRollDoneClose }))
return
return await RollDialog.create(rollData, options)
}
RdDEmpoignade.checkEmpoignadeEnCours(this)
@@ -1977,8 +1988,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { tache: { key: tache.id, forced: options.forced } },
type: { allowed: [PART_TACHE], current: PART_TACHE }
}
RollDialog.create(rollData, options)
return
return await RollDialog.create(rollData)
}
const compData = this.getCompetence(tache.system.competence)
@@ -2037,8 +2047,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { jeu: { key: jeu.id } },
type: { allowed: [ROLL_TYPE_JEU], current: ROLL_TYPE_JEU }
}
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return
return await RollDialog.create(rollData)
}
const listCarac = jeu.system.caraccomp.toLowerCase().split(/[.,:\/-]/).map(it => it.trim());
@@ -2066,8 +2075,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { meditation: { key: id } },
type: { allowed: [ROLL_TYPE_MEDITATION], current: ROLL_TYPE_MEDITATION }
}
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return
return await RollDialog.create(rollData)
}
const competence = foundry.utils.duplicate(this.getCompetence(meditation.system.competence));
@@ -2266,7 +2274,7 @@ export class RdDActor extends RdDBaseActorSang {
const xpCompetence = competence ? xp - xpCarac : 0;
if (jetResistance) {
const message = `Jet de résistance ${jetResistance}, l'expérience est limitée à 1`;
const message = `Jet de résistance, l'expérience est limitée à 1`;
ui.notifications.info(message);
console.log(message)
// max 1 xp sur jets de résistance
@@ -2574,7 +2582,12 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */
conjurerPossession(possession) {
RdDPossession.onConjurerPossession(this, possession)
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
RdDPossessionV2.rollConjurerPossession(this, possession)
}
else {
RdDPossession.onConjurerPossession(this, possession)
}
}
/* -------------------------------------------- */
@@ -3146,7 +3159,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { oeuvre: { key: oeuvre.id } },
type: { allowed: [PART_OEUVRE], current: PART_OEUVRE, },
}
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return await RollDialog.create(rollData)
}
/* -------------------------------------------- */
@@ -3251,8 +3264,7 @@ export class RdDActor extends RdDBaseActorSang {
cuisine: { key: recette.id }
}
}
RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return
return await RollDialog.create(rollData)
}
const artData = {
@@ -3302,8 +3314,7 @@ export class RdDActor extends RdDBaseActorSang {
cuisine: { key: item.id }
}
}
RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
return
return await RollDialog.create(rollData)
}
if (item.getUtilisationCuisine() == 'brut') {

View File

@@ -1,4 +1,4 @@
import { renderTemplate, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
import { RDD_CONFIG, renderTemplate, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
import { Grammar } from "../grammar.js";
import { Misc } from "../misc.js";
import { RdDResolutionTable } from "../rdd-resolution-table.js";
@@ -22,13 +22,16 @@ import { DialogValidationEncaissement } from "../dialog-validation-encaissement.
import { RdDCombat } from "../rdd-combat.js";
import { RdDEmpoignade } from "../rdd-empoignade.js";
import { RdDPossession } from "../rdd-possession.js";
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, POSSESSION_SANS_DRACONIC } from "../item/base-items.js";
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES_CREATURES } from "../item/base-items.js";
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, ROLL_TYPE_COMP, ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_OEUVRE, ROLL_TYPE_TACHE } from "../roll/roll-constants.mjs";
import { ATTAQUE_ROLL_TYPES, 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";
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs";
/**
* Classe de base pour les acteurs disposant de rêve (donc, pas des objets)
@@ -114,11 +117,54 @@ export class RdDBaseActorReve extends RdDBaseActor {
return this.system.carac[competence.system.defaut_carac].value;
}
getDraconics() { return [] }
getDraconicOuPossession() {
return [
...this.getDraconics(),
...this.itemTypes[ITEM_TYPES.competencecreature].filter(it => it.isCompetencePossession()),
this.getConjurationNaturelle()
].sort(Misc.descending(it => it.system.niveau));
}
getConjurations() {
return this.getDraconicOuPossession()
.map(it => this.toActionConjuration(it))
}
getConjurationNaturelle() {
return new RdDItemCompetenceCreature({
name: 'Sans compétence',
type: ITEM_TYPES.competencecreature,
img: RDD_CONFIG.icons.possession,
system: {
carac_value: this.getReveActuel(),
niveau: 0,
default_diffLibre: 0,
categorie: CATEGORIES_COMPETENCES_CREATURES.possession.key,
ispossession: true,
}
})
}
toActionConjuration(comp) {
const caracCode = this.isPersonnage() ? CARACS.REVE_ACTUEL : CARACS.REVE
const caracValue = this.getReveActuel()
const ajustement = this.getEtatGeneral()
return {
label: `Conjuration (${comp.name})`,
action: 'possession',
initOnly: false,
comp: comp,
carac: { key: caracCode, value: caracValue },
initiative: RdDInitiative.getRollInitiative(caracValue, comp.system.niveau, ajustement)
}
}
listActions({ isAttaque = false, isEquipe = false }) {
return this.itemTypes[ITEM_TYPES.competencecreature]
.filter(it => it.isAttaque())
.map(it => it.attaqueCreature())
.filter(it => it != undefined);
.filter(it => it != undefined)
}
async computeArmure(dmg) { return this.getProtectionNaturelle() }
@@ -130,13 +176,14 @@ export class RdDBaseActorReve extends RdDBaseActor {
async santeIncDec(name, inc, isCritique = false) { }
async finDeRound(options = { terminer: false }) {
await this.$finDeRoundSuppressionEffetsTermines(options);
await this.finDeRoundBlessures();
await this.$finDeRoundSupprimerObsoletes();
await this.$finDeRoundEmpoignade();
await this.finDeRoundSuppressionEffetsTermines(options)
await this.finDeRoundBlessures()
await this.finDeRoundSupprimerObsoletes()
await this.finDeRoundEmpoignade()
await this.finDeRoundPossession()
}
async $finDeRoundSuppressionEffetsTermines(options) {
async finDeRoundSuppressionEffetsTermines(options) {
for (let effect of this.getEffects()) {
if (effect.duration.type !== 'none' && (effect.duration.remaining <= 0 || options.terminer)) {
await effect.delete();
@@ -148,20 +195,22 @@ export class RdDBaseActorReve extends RdDBaseActor {
async finDeRoundBlessures() {
}
async $finDeRoundSupprimerObsoletes() {
async finDeRoundSupprimerObsoletes() {
const obsoletes = []
.concat(this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp <= 0))
.concat(this.itemTypes[ITEM_TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2))
.map(it => it.id);
.map(it => it.id)
await this.deleteEmbeddedDocuments('Item', obsoletes);
}
async $finDeRoundEmpoignade() {
const immobilisations = this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id);
immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this,
game.actors.get(emp.system.empoigneid),
emp
))
async finDeRoundEmpoignade() {
await Promise.all(this.itemTypes[ITEM_TYPES.empoignade]
.filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id)
.map(async it => await RdDEmpoignade.onImmobilisation(this, it)))
}
async finDeRoundPossession(){
await Promise.all(this.itemTypes[ITEM_TYPES.possession]
.map(async it => await RdDPossessionV2.onPossession(this, it)))
}
async setSonne(sonne = true) { }
@@ -200,8 +249,6 @@ export class RdDBaseActorReve extends RdDBaseActor {
return false
}
getDraconicOuPossession() { return POSSESSION_SANS_DRACONIC }
getPossession(possessionId) {
return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId);
}
@@ -284,8 +331,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
diff: { value: diff }
}
}
RollDialog.create(rollData, options)
return
return await RollDialog.create(rollData, options)
}
const competence = this.getCompetence(compName);
@@ -339,6 +385,19 @@ export class RdDBaseActorReve extends RdDBaseActor {
/* -------------------------------------------- */
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()
@@ -359,6 +418,26 @@ export class RdDBaseActorReve extends RdDBaseActor {
})
}
/* -------------------------------------------- */
async rollReveActuel({ diff = 0, resistance = false }) {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
type: {
allowed: [PART_COMP],
current: PART_COMP,
resistance: resistance
},
selected: {
carac: { key: CARACS.REVE_ACTUEL, forced: true },
comp: resistance ? { key: undefined, forced: true } : undefined,
diff: { type: DIFF.DEFAUT, value: diff }
}
}
return await RollDialog.create(rollData)
}
return this.rollCarac(CARACS.REVE_ACTUEL, { diff, resistance })
}
async rollCarac(caracName, options = {}) {
if (Grammar.equalsInsensitive(caracName, CARACS.TAILLE)) {
return
@@ -366,14 +445,18 @@ export class RdDBaseActorReve extends RdDBaseActor {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
type: { allowed: DEFAULT_ROLL_TYPES, current: PART_COMP },
type: {
allowed: options.resistance ? [PART_COMP] : DEFAULT_ROLL_TYPES,
current: PART_COMP,
resistance: options.resistance
},
selected: {
carac: { key: caracName },
comp: options.resistance ? { key: undefined, forced: true } : undefined
comp: options.resistance ? { key: undefined, forced: true } : undefined,
diff: { type: DIFF.DEFAUT, value: options.diff ?? 0 }
}
}
RollDialog.create(rollData, options)
return
return await RollDialog.create(rollData, options)
}
foundry.utils.mergeObject(options, { resistance: false, diff: 0 }, { overwrite: false })
@@ -487,7 +570,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE
}
};
return await RollDialog.create(rollData)
return await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
}
})
}
@@ -534,6 +617,10 @@ export class RdDBaseActorReve extends RdDBaseActor {
})
}
rollPossession() {
RdDPossessionV2.rollAttaquePossession(this)
}
verifierForceMin(item) { }
/* -------------------------------------------- */

View File

@@ -130,7 +130,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
let 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));
@@ -145,16 +145,10 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
if (inc > 0) { // le max d'endurance s'applique seulement à la récupération
result.newValue = Math.min(result.newValue, this._computeEnduranceMax())
}
const perte = compteur.value - result.newValue;
result.perte = perte;
if (perte > 1) {
// Peut-être sonné si 2 points d'endurance perdus d'un coup
foundry.utils.mergeObject(result, await this.jetEndurance(result.newValue));
} else if (inc > 0) {
await this.setSonne(false);
}
perteEndurance = compteur.value - result.newValue;
result.perte = perteEndurance
if (sante.fatigue && inc < 0) { // Each endurance lost -> fatigue lost
fatigue = perte;
fatigue = perteEndurance;
}
}
compteur.value = result.newValue;
@@ -163,6 +157,14 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
sante.fatigue.value = Math.max(sante.fatigue.value + fatigue, this.getFatigueMin());
}
await this.update({ "system.sante": sante }, { render: true })
if (perteEndurance > 1) {
// Peut-être sonné si 2 points d'endurance perdus d'un coup
foundry.utils.mergeObject(result, await this.jetEndurance(result.newValue));
} else if (name == "endurance" && inc > 0) {
await this.setSonne(false);
}
if (this.isDead()) {
await this.setEffect(STATUSES.StatusComma, true);
}
@@ -181,28 +183,46 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
}
async onCreateItem(item, options, id) {
switch (item.type) {
case ITEM_TYPES.blessure:
await this.changeBleedingState()
break
}
await this.changeItemEffects(item)
await super.onCreateItem(item, options, id)
}
async onUpdateItem(item, options, id) {
switch (item.type) {
case ITEM_TYPES.blessure:
await this.changeBleedingState()
break
}
await this.changeItemEffects(item);
await super.onUpdateItem(item, options, id)
}
async changeBleedingState() {
async onDeleteItem(item, options, id) {
await this.changeItemEffects(item);
await super.onDeleteItem(item, options, id)
}
async changeItemEffects(item) {
switch (item.type) {
case ITEM_TYPES.blessure:
await this.changeStateBleeding();
break;
case ITEM_TYPES.maladie:
case ITEM_TYPES.poison:
await this.changeStateMalade();
break;
}
}
async changeStateBleeding() {
const bleeding = this.itemTypes[ITEM_TYPES.blessure].find(it => it.isBleeding())
await this.setEffect(STATUSES.StatusBleeding, bleeding ? true : false)
}
async changeStateMalade() {
const maladiePoisons = this.getMaladiesPoisons()
await this.setEffect(STATUSES.StatusMalade, maladiePoisons.length > 0)
}
getMaladiesPoisons() {
return this.items.filter(it => [ITEM_TYPES.maladie, ITEM_TYPES.poison].includes(it.type))
}
/* -------------------------------------------- */
async ajouterBlessure(encaissement, attackerToken = undefined) {
if (encaissement.gravite < 0) return;

View File

@@ -11,6 +11,7 @@ import { RdDUtility } from "../rdd-utility.js";
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";
export class RdDBaseActor extends Actor {
@@ -67,19 +68,23 @@ export class RdDBaseActor extends Actor {
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);
@@ -220,6 +225,7 @@ export class RdDBaseActor extends Actor {
isEntite() { return false }
isEntiteIncarnee() { return false }
isEntiteNonIncarnee() { return false }
isEntiteBlurette() { return false }
isHautRevant() { return false }
isVehicule() { return false }
isPersonnage() { return false }
@@ -279,11 +285,24 @@ export class RdDBaseActor extends Actor {
async removeEffects(filter = e => true) {
if (game.user.isGM) {
const effectsToRemove = this.getEffects(filter);
const ids = effectsToRemove.map(it => it.id);
await this.deleteEmbeddedDocuments('ActiveEffect', ids);
const ids = this.getEffects(filter)
.filter(it => this.canRemoveEffects(it))
.map(it => it.id)
if (ids.length > 0) {
await this.deleteEmbeddedDocuments('ActiveEffect', ids)
}
}
}
canRemoveEffects(effect) {
if (effect.statuses.has(STATUSES.StatusSurEnc)) {
return !this.isSurenc()
}
if (effect.statuses.has(STATUSES.StatusDemiReve)) {
return !this.tmrApp
}
return true
}
/* -------------------------------------------- */
async updateCarac(caracName, to) {
@@ -446,7 +465,7 @@ export class RdDBaseActor extends Actor {
ui.notifications.info("Inutile de se vendre à soi-même");
return;
}
if (!Misc.isFirstConnectedGM()) {
if (!game.user.isGM) {
RdDBaseActor.remoteActorCall({
actorId: achat.vendeurId ?? achat.acheteurId,
method: 'achatVente', args: [achat]
@@ -503,10 +522,13 @@ export class RdDBaseActor extends Actor {
async acheter(item, quantite, cout, achat) {
await this.depenserSols(cout)
const createdItemId = await this.creerQuantiteItem(item, quantite)
if (achat.choix.consommer && item.type == 'nourritureboisson' && createdItemId != undefined) {
if (item.type == ITEM_TYPES.nourritureboisson && achat.choix.consommer && createdItemId != undefined) {
achat.choix.doses = achat.choix.nombreLots;
await this.consommerNourritureboisson(createdItemId, achat.choix, achat.vente.actingUserId);
}
if (item.type == ITEM_TYPES.service) {
new Apprecier(this, item.system.appreciation, item.system.qualite).apprecier()
}
}
verifierFortune(cout) {
@@ -576,7 +598,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) {
@@ -835,6 +857,7 @@ export class RdDBaseActor extends Actor {
listActionsPossessions() {
return this.itemTypes[ITEM_TYPES.possession]
.filter(it => !it.system.possede)
.map(p => {
return {
label: p.name,
@@ -843,9 +866,4 @@ export class RdDBaseActor extends Actor {
}
})
}
listActionsCombat() {
const possessions = this.listActionsPossessions()
return possessions.length > 0 ? possessions : this.listActions({})
}
}

View File

@@ -19,8 +19,8 @@ export class RdDEntite extends RdDBaseActorReve {
isEntite() { return true }
isEntiteNonIncarnee() { return this.system.definition.typeentite == ENTITE_NONINCARNE }
isEntiteIncarnee() { return [ENTITE_INCARNE, ENTITE_BLURETTE].includes(this.system.definition.typeentite) }
isEntiteBlurette() { return this.system.definition.typeentite !== ENTITE_BLURETTE }
isEntiteIncarnee() { return !this.isEntiteNonIncarnee() }
isEntiteBlurette() { return this.system.definition.typeentite == ENTITE_BLURETTE }
getReveActuel() {
return Misc.toInt(this.system.carac.reve?.value)
@@ -41,13 +41,6 @@ export class RdDEntite extends RdDBaseActorReve {
getChance() { return this.getReve() }
getEnduranceMax() { return Math.max(1, this.getTaille() + this.getReve()) }
getDraconicOuPossession() {
return this.itemTypes[ITEM_TYPES.competencecreature]
.filter(it => it.system.categorie == 'possession')
.sort(Misc.descending(it => it.system.niveau))
.find(it => true);
}
async remiseANeuf() {
if (!this.isEntiteNonIncarnee()) {
await this.update({
@@ -108,6 +101,15 @@ export class RdDEntite extends RdDBaseActorReve {
return true
}
listActionsPossessions() {
if (this.isEntiteNonIncarnee()) {
return this.itemTypes[ITEM_TYPES.competencecreature]
.filter(it => it.system.ispossession)
.map(it => it.attaqueCreature())
.filter(it => it != undefined)
}
return super.listActionsPossessions()
}
/* -------------------------------------------- */
async setEntiteReveAccordee(actor) {
if (this.isEntiteIncarnee()) {

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

@@ -76,6 +76,15 @@ export class ChatUtility {
ChatUtility.removeMessages({ part: part });
}
static remover(chatMessage) {
const messageId = chatMessage.id;
if (messageId) {
return (..._) => ChatUtility.removeMessages({ messageId: messageId });
}
return (..._) => { }
}
static removeChatMessageId(messageId) {
if (messageId) {
ChatUtility.removeMessages({ messageId: messageId });

View File

@@ -1,6 +1,7 @@
import { RdDBaseActor } from "../actor/base-actor.js";
import { ChatUtility } from "../chat-utility.js";
import { renderTemplate } from "../constants.js";
import { MORAL } from "../moral/apprecier.mjs";
const INFO_COEUR = 'info-coeur';
@@ -122,7 +123,7 @@ export class RdDCoeur {
const diff = Math.abs(infoCoeur.source.jetTendre - infoCoeur.target.jetTendre)
for (let amoureux of [infoCoeur.source, infoCoeur.target]) {
const actorAmoureux = game.actors.get(amoureux.actor.id);
amoureux.situation = diff <= amoureux.coeur ? 'heureux' : 'neutre'
amoureux.situation = diff <= amoureux.coeur ? MORAL.HEUREUX : MORAL.NEUTRE
amoureux.gainMoral = await actorAmoureux.jetDeMoral(amoureux.situation)
}
const chatHtml = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/coeur/chat-accepter-tendre-moment.hbs`, infoCoeur)

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

@@ -0,0 +1,119 @@
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 (token instanceof Token && defenderToken instanceof Token) {
const ray = new foundry.canvas.geometry.Ray(
token.getCenterPoint(),
defenderToken.getCenterPoint()
)
return Number(canvas.grid.measureDistances([{ ray }], { gridSpaces: false }))
}
return -1 /* distance indéterminée */
}
static isVisible(token, defenderToken) {
// TODO: regarder les StatusEffect aveuglé?
if (token instanceof Token && defenderToken instanceof Token) {
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 (defenderToken instanceof Token) {
if (defenderToken.actor?.getSurprise(true) != '') return { msg: "immobile (surprise)", diff: 0 };
if (defenderToken.inCombat) return { msg: "en mouvement (combat)", diff: -4 };
}
return { msg: "à déterminer (0 immobile, -3 actif, -4 en mouvement, -5 en zig-zag)", 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
}
}

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

@@ -61,8 +61,12 @@ export const RDD_CONFIG = {
armesDisparates: 'systems/foundryvtt-reve-de-dragon/assets/actions/armes-disparates.svg',
demiReve: 'systems/foundryvtt-reve-de-dragon/assets/actions/sort.svg',
empoignade: 'systems/foundryvtt-reve-de-dragon/assets/actions/empoignade.svg',
possession: 'systems/foundryvtt-reve-de-dragon/assets/actions/possession.svg',
forceWeak: 'systems/foundryvtt-reve-de-dragon/assets/actions/weak.svg',
surenc: 'systems/foundryvtt-reve-de-dragon/assets/actions/surenc.svg',
magique: 'systems/foundryvtt-reve-de-dragon/assets/actions/magique.svg',
armebrisee: 'systems/foundryvtt-reve-de-dragon/assets/actions/arme-brisee.svg',
malade: 'systems/foundryvtt-reve-de-dragon/assets/actions/malade.svg',
},
encaissement: {
mortel: 'mortel',

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

@@ -3,6 +3,7 @@ import { renderTemplate } from "./constants.js"
export class DialogSelect extends Dialog {
static extractIdNameImg(it) { return { id: it.id, name: it.name, img: it.img } }
static async select(selectionData, onSelectChoice) {
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-select.hbs", selectionData)

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"],

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

@@ -14,6 +14,8 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js";
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";
/**
* Extend the basic ItemSheet for RdD specific items
@@ -89,6 +91,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
/* -------------------------------------------- */
async getData() {
const competences = (await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage))
let formData = {
title: this.item.name,
id: this.item.id,
@@ -101,8 +104,9 @@ 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: await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage),
competences: [new RdDItemCompetence(SANS_COMPETENCE), ...competences],
categories: RdDItem.getCategories(this.item.type),
isAppreciable: Apprecier.isAppreciable(this.item)
}
if (this.item.type == ITEM_TYPES.competencecreature) {

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))
@@ -62,7 +63,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

@@ -28,7 +28,7 @@ const typesInventaireMateriel = [
]
const typesInventaire = {
materiel: typesInventaireMateriel,
all: ['service'].concat(typesInventaireMateriel),
all: [ITEM_TYPES.service].concat(typesInventaireMateriel),
}
const typesObjetsOeuvres = [ITEM_TYPES.oeuvre, ITEM_TYPES.recettecuisine, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.jeu]
@@ -36,6 +36,10 @@ const typesObjetsDraconiques = [ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.s
const typesObjetsConnaissance = [ITEM_TYPES.meditation, ITEM_TYPES.recettealchimique, ITEM_TYPES.sort]
const typesObjetsEffet = [ITEM_TYPES.possession, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.blessure]
const typesObjetsCompetence = [ITEM_TYPES.competence, ITEM_TYPES.competencecreature]
const typesAppreciable = [
ITEM_TYPES.oeuvre, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.nourritureboisson,
ITEM_TYPES.jeu, ITEM_TYPES.service
]
const typesObjetsTemporels = [ITEM_TYPES.blessure, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.signedraconique, ITEM_TYPES.rencontre]
const typesObjetsEquipable = [ITEM_TYPES.arme, ITEM_TYPES.armure, ITEM_TYPES.objet];
const typesEnvironnement = typesInventaireMateriel;
@@ -96,14 +100,14 @@ export class RdDItem extends Item {
switch (field) {
case 'quantite':
if (ITEM_TYPES.conteneur == type) {
return false;
return false
}
break;
case 'cout':
if (ITEM_TYPES.monnaie == type) {
return game.user.isGM;
}
break;
break
}
return true;
}
@@ -180,10 +184,10 @@ 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; }
isMonnaie() { return this.type == ITEM_TYPES.monnaie; }
isConteneur() { return this.type == ITEM_TYPES.conteneur }
isMonnaie() { return this.type == ITEM_TYPES.monnaie }
isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; }
isService() { return this.type == ITEM_TYPES.service; }
isService() { return this.type == ITEM_TYPES.service }
isAttaque() { return false }
isParade() { return false }
isBouclier() { return false }
@@ -205,7 +209,7 @@ export class RdDItem extends Item {
return this.isCompetence() && ['melee', 'tir', 'lancer'].includes(this.system.categorie)
}
isCompetencePossession() { return ITEM_TYPES.competencecreature == this.type && this.system.categorie == "possession" }
isCompetencePossession() { return ITEM_TYPES.competencecreature == this.type && this.system.categorie == CATEGORIES_COMPETENCES_CREATURES.possession.key }
isTemporel() { return typesObjetsTemporels.includes(this.type) }
isOeuvre() { return typesObjetsOeuvres.includes(this.type) }
isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
@@ -214,6 +218,7 @@ export class RdDItem extends Item {
isConnaissance() { return typesObjetsConnaissance.includes(this.type) }
isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); }
isAppreciable() { return typesAppreciable.includes(this.type) }
isBoisson() { return this.isNourritureBoisson() && this.system.boisson; }
isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; }
isHerbeAPotion() { return this.type == ITEM_TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
@@ -364,11 +369,11 @@ export class RdDItem extends Item {
getEnc() {
switch (this.type) {
case ITEM_TYPES.service:
return 0;
return 0
case ITEM_TYPES.herbe:
return this.getEncHerbe();
return this.getEncHerbe()
}
return Math.max(this.system.encombrement ?? 0, 0);
return Math.max(this.system.encombrement ?? 0.0, 0.0);
}
getEncContenu() {
@@ -384,9 +389,9 @@ export class RdDItem extends Item {
getEncHerbe() {
switch (this.system.categorie) {
case 'Repos': case 'Soin': case 'Alchimie':
return encBrin;
return encBrin
}
return this.system.encombrement;
return this.system.encombrement
}

View File

@@ -278,6 +278,10 @@ export class RdDItemArme extends RdDItem {
return this.system.mortalite == RDD_CONFIG.encaissement.empoignade
}
isPossession() {
return this.system.mortalite == RDD_CONFIG.encaissement.possession
}
isUtilisableEmpoigne() {
return this.system.baseInit == 3 || this.system.baseInit == 4 || this.system.competence == "Dague"
}

View File

@@ -1,22 +1,5 @@
export const POSSESSION_SANS_DRACONIC = { name: 'Sans draconic', type: 'competence', system: { niveau: 0, defaut_carac: "reve-actuel", }, img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp' }
export const PAS_DE_DRACONIC = { name: 'Pas de draconic', type: 'competence', system: { niveau: -11, defaut_carac: "reve" }, img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp' }
export const BASE_CORPS_A_CORPS = { name: 'Corps à Corps', type: 'competence', system: { niveau: -6, defaut_carac: "melee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' }
export const BASE_ESQUIVE = { name: 'Esquive', type: 'competence', system: { niveau: -6, defaut_carac: "derobee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp' }
export const SANS_COMPETENCE = {
name: "Sans compétence",
type: 'competence',
system: {
niveau: 0,
default_diffLibre: 0,
base: 0,
categorie: "Aucune",
description: "",
descriptionmj: "",
defaut_carac: "",
},
img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp"
}
import { ITEM_TYPES, RDD_CONFIG } from "../constants.js"
import { CARACS } from "../rdd-carac.js"
export const CATEGORIES_COMPETENCES = {
generale: { key: 'generale', base: -4, label: "Générales" },
@@ -39,3 +22,25 @@ export const CATEGORIES_COMPETENCES_CREATURES = {
lancer: { key: 'lancer', base: 0, label: "Lancer" },
possession: { key: 'possession', base: 0, label: "Possession" },
}
export const POSSESSION_SANS_DRACONIC = {
name: 'Sans draconic',
type: ITEM_TYPES.competence,
img: RDD_CONFIG.icons.possession,
system: { niveau: 0, defaut_carac: CARACS.REVE_ACTUEL, categorie: CATEGORIES_COMPETENCES.draconic.key }
}
export const PAS_DE_DRACONIC = { name: 'Pas de draconic', type: 'competence', system: { niveau: -11, defaut_carac: "reve" }, img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp' }
export const BASE_CORPS_A_CORPS = { name: 'Corps à Corps', type: 'competence', system: { niveau: -6, defaut_carac: "melee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' }
export const BASE_ESQUIVE = { name: 'Esquive', type: 'competence', system: { niveau: -6, defaut_carac: "derobee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp' }
export const SANS_COMPETENCE = {
name: "Sans compétence",
type: ITEM_TYPES.competence,
img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp",
system: {
niveau: 0,
default_diffLibre: 0,
categorie: CATEGORIES_COMPETENCES.generale.key,
}
}

View File

@@ -76,7 +76,7 @@ export class RdDItemRace extends RdDItem {
ui.notifications.warn("La Taille est inférieur au minimum racial")
return min
}
const raceMax = this.system.carac.taille.max;
const raceMax = this.system.carac.taille.max == undefined ? 15 + this.system.carac.taille.value : this.system.carac.taille.max
const max = raceMax < 0 ? taille + 1 : raceMax
if (max < taille) {
ui.notifications.warn("La Taille est supérieure au maximum racial")

View File

@@ -68,7 +68,7 @@ export class RdDRencontre extends RdDItem {
}
static async appliquer(codes, tmrDialog, rencData) {
for(const effet of RdDRencontre.mapEffets(codes)){
for(let effet of RdDRencontre.mapEffets(codes)){
await effet.method(tmrDialog, rencData);
}
}

View File

@@ -8,6 +8,7 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { RdDRaretes } from "./item/raretes.js";
import { VOIES_DRACONIC } from "./item-sort.js";
import { SystemCompendiums } from "./settings/system-compendiums.js";
import { APPRECIATION } from "./moral/apprecier.mjs";
class Migration {
get code() { return "sample"; }
@@ -33,7 +34,6 @@ class Migration {
await Item.updateDocuments(itemUpdates);
}
}
}
class _1_5_34_migrationPngWebp {
@@ -662,6 +662,57 @@ class _13_0_7_FixNiveauOeuvres extends Migration {
}
}
class _13_0_21_AjoutAppreciation extends Migration {
get code() { return "ajout-appreciation" }
get version() { return "13.0.21" }
async migrate() {
await this.applyItemsUpdates(items => items
.filter(it => it.isAppreciable())
.filter(it => this.getBaseAppreciation(it))
.map(it => {
return { _id: it.id, 'system.appreciation': this.getBaseAppreciation(it) }
})
)
}
getBaseAppreciation(item) {
switch (item.type) {
case ITEM_TYPES.nourritureboisson: return APPRECIATION.CUISINE
case ITEM_TYPES.service: return APPRECIATION.SERVICE
case ITEM_TYPES.musique: return APPRECIATION.MUSIQUE
case ITEM_TYPES.chant: return APPRECIATION.CHANT
case ITEM_TYPES.danse: return APPRECIATION.DANSE
case ITEM_TYPES.oeuvre: {
const appreciation = foundry.utils.duplicate(APPRECIATION.OEUVRE)
appreciation.competence = item.system.competence
return appreciation
}
}
return undefined
}
}
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 [
@@ -687,6 +738,8 @@ export class Migrations {
new _12_0_38_TachesEcriture(),
new _13_0_4_FixReveActuel(),
new _13_0_7_FixNiveauOeuvres(),
new _13_0_21_AjoutAppreciation(),
new _13_0_22_PoidsDesMonnaies(),
];
}
@@ -707,7 +760,10 @@ export class Migrations {
}
if (foundry.utils.isNewerVersion(game.system.version, currentVersion)) {
// if (true) { /* comment previous and uncomment here to test before upgrade */
const migrations = Migrations.getMigrations().filter(m => foundry.utils.isNewerVersion(m.version, currentVersion));
const migrations = Migrations.getMigrations().filter(m => foundry.utils.isNewerVersion(m.version, currentVersion)
/* uncomment and set the version to migrate to to force a migration */
// ||m.version == "13.0.21"
)
if (migrations.length > 0) {
migrations.sort((a, b) => this.compareVersions(a, b));
migrations.forEach(async (m) => {

View File

@@ -200,10 +200,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() {
@@ -223,18 +220,26 @@ export class Misc {
* and there is no connected GM
*/
static documentIfResponsible(document) {
if (Misc.isFirstConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isFirstOwnerPlayer(document))) {
if (game.users.activeGM || (Misc.connectedGMs().length == 0 && Misc.isFirstOwnerPlayer(document))) {
return document
}
return undefined
}
static async doIfOwner(document, action, orElse = async it => { ui.notifications.warn(`Vous n'avez pas le droit d'agir pour ${it.name}`) }) {
if (Misc.isOwnerPlayer(document)) {
return await action(document)
} else {
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 && document.testUserPermission && document.testUserPermission(game.user, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
}
static isFirstOwnerPlayer(document) {
if (!document.testUserPermission) {
if (!document?.testUserPermission) {
return false
}
return game.users.find(u => document.testUserPermission(u, CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)) == game.user
@@ -244,15 +249,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.user == game.users.activeGM
}
static hasConnectedGM() {
return Misc.firstConnectedGM();
return game.users.activeGM
}
static firstConnectedGMId() {
return Misc.firstConnectedGM()?.id;
return game.users.activeGM?.id;
}
/* -------------------------------------------- */

182
module/moral/apprecier.mjs Normal file
View File

@@ -0,0 +1,182 @@
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"
import { CARACS } from "../rdd-carac.js"
import { RdDUtility } from "../rdd-utility.js"
import { DIFF } from "../roll/roll-constants.mjs"
import RollDialog from "../roll/roll-dialog.mjs"
import { PART_COMP } from "../roll/roll-part-comp.mjs"
export const MORAL = {
MALHEUREUX: "malheureux",
NEUTRE: "neutre",
HEUREUX: "heureux",
TRESHEUREUX: "très heureux"
}
export const SITUATION_MORAL = {
[MORAL.MALHEUREUX]: "malheureuse",
[MORAL.NEUTRE]: "neutre",
[MORAL.HEUREUX]: "heureuse",
[MORAL.TRESHEUREUX]: "très heureuse",
}
export const APPRECIATION = {
CUISINE: {
bonmoment: "Cuisine", carac: CARACS.ODORATGOUT, competence: "Cuisine",
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
},
MUSIQUE: {
bonmoment: "Musique", carac: CARACS.OUIE, competence: "Musique",
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
},
CHANT: {
bonmoment: "Musique", carac: CARACS.OUIE, competence: "Chant",
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
},
DANSE: {
bonmoment: "Spectacle", carac: CARACS.EMPATHIE, competence: "Danse",
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
},
JEU: {
bonmoment: "Jeu", carac: CARACS.EMPATHIE, competence: "Jeu",
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
},
OEUVRE: {
bonmoment: "Spectacle", carac: CARACS.EMPATHIE, competence: "",
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: true
},
SERVICE: {
bonmoment: "Confort", carac: CARACS.EMPATHIE, competence: "",
moral: MORAL.HEUREUX, jetComp: false, jetQualite: false, compMinimum: false
},
}
export class Apprecier {
static isAppreciable(item) {
switch (item.type) {
case ITEM_TYPES.nourritureboisson:
case ITEM_TYPES.service:
return item.system.qualite > 0
case ITEM_TYPES.chant:
case ITEM_TYPES.musique:
case ITEM_TYPES.danse:
case ITEM_TYPES.oeuvre:
case ITEM_TYPES.jeu:
return true
}
return false
}
static qualite(qualite, roll = undefined, comp = undefined) {
if (roll && comp) {
return roll.rolled.isSuccess ? qualite : Math.min(qualite, comp.system.niveau)
}
return
}
static getAppreciation(qualite, appreciable, roll = undefined, comp = undefined) {
return {
qualite: (roll?.rolled.ptQualite ?? 0) + Apprecier.qualite(qualite, roll, comp),
appreciation: foundry.utils.duplicate(appreciable.system.appreciation),
messages: []
}
}
static onClickApprecier(roll) {
const appreciation = roll.result.appreciation
if (appreciation.moral == "") {
return
}
RdDUtility.doWithSelectedActor(
actor => new Apprecier(actor, appreciation, roll.result.qualite).apprecier(),
actor => actor.isPersonnage())
}
constructor(actor, appreciation, qualite) {
this.actor = actor
this.appreciation = foundry.utils.duplicate(appreciation)
this.appreciation.situation = SITUATION_MORAL[appreciation.moral]
this.qualite = qualite
this.raisons = []
}
apprecier(callbacks = []) {
if (this.qualite <= 0) {
this.raisons.push(`la qualité ${this.qualite} est négative.`)
}
if (this.qualite <= this.actor.getMoralTotal()) {
this.raisons.push(`la qualité de ${this.qualite} est inférieure au moral de ${this.actor.getMoralTotal()}.`)
}
const competence = this.getCompetenceAppreciation()
if (this.appreciation.compMinimum && this.qualite <= competence.system.niveau && competence.system.niveau > 0 && competence.id) {
this.raisons.push(`la qualité ${this.qualite} est insuffisante pour le niveau ${competence.system.niveau} en ${competence.name}`)
}
const bonmoment = this.appreciation.bonmoment
if (!["", undefined].includes(bonmoment) && this.actor.system.compteurs.bonmoments.includes(bonmoment)) {
this.raisons.push(`du moral a déjà été gagné pour cause de ${bonmoment}`)
}
if (this.appreciation.carac != "") {
this.rollAppreciation(callbacks)
}
else {
this.rollMoral()
}
}
getCompetenceAppreciation() {
return [SANS_COMPETENCE.name, ""].includes(this.appreciation.competence) ? SANS_COMPETENCE : this.actor.getCompetence(this.appreciation.competence)
}
rollAppreciation(rollCallbacks = []) {
const competence = (this.appreciation.jetComp && this.appreciation.competence) ? this.appreciation.competence : ""
const rollData = {
ids: { actorId: this.actor.id },
type: { allowed: [PART_COMP], current: PART_COMP, appreciation: true },
selected: {
carac: { key: this.appreciation.carac, forced: true },
comp: { key: competence, forced: true },
diff: { type: DIFF.IMPOSEE },
apprecier: {
appreciation: this.appreciation,
qualite: this.qualite,
raisons: this.raisons
}
}
}
RollDialog.create(rollData, {
callbacks: [
async r => await this.onRollAppreciation(r),
...rollCallbacks
],
onRollDone: RollDialog.onRollDoneClose
})
}
async onRollAppreciation(roll) {
if (roll.rolled.isSuccess) {
await this.rollMoral()
}
else {
if (this.appreciation.moral == MORAL.TRESHEUREUX) {
await this.rollMoral(MORAL.HEUREUX)
}
}
}
async rollMoral(moral = undefined) {
if (this.raisons.length > 0) {
ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor),
content: 'Pas de jet de moral:' + Misc.concat(this.raisons.map(r => `<br> - ${r}`))
})
return
}
moral = moral ?? this.appreciation.moral
// TODO: jet de moral
await this.actor.jetDeMoral(moral, this.appreciation.bonmoment)
}
}

View File

@@ -64,7 +64,7 @@ export class RdDBonus {
const dmg = {
total: 0,
dmgArme: dmgArme,
penetration: arme?.penetration() ?? 0,
penetration: arme?.system.penetration ?? 0,
diff: attaque.diff,
dmgTactique: attaque.tactique?.dmg ?? 0,
dmgParticuliere: RdDBonus._dmgParticuliere(rollData),

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 = [
@@ -105,7 +106,7 @@ export class RdDCombatManager extends Combat {
}
else if (!combatant.actor.isActorCombat()) {
if (options.warning) {
ui.notifications.warn(`${combatant.name} ne peut pas combattre!`)
ui.notifications.warn(`L'acteur ${combatant.name} ne peut pas combattre!`)
}
return undefined
}
@@ -153,7 +154,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 });
@@ -315,6 +316,7 @@ export class RdDCombat {
switch (sockmsg.msg) {
case "msg_encaisser": return RdDCombat.onMsgEncaisser(sockmsg.data);
case "msg_defense": return RdDCombat.onMsgDefense(sockmsg.data);
case "msg_defense_v2": return RdDCombat.onMsgDefenseV2(sockmsg.data);
}
}
@@ -367,6 +369,18 @@ export class RdDCombat {
return new RdDCombat(attacker, attackerTokenId, defender, defenderTokenId, target)
}
static rddCombatForAttackV2(attackerRoll) {
return RdDCombat.rddCombatForDefenseV2(RollBasicParts.prepareDefense(attackerRoll))
}
static rddCombatForDefenseV2(defenderRoll) {
let defenderToken = canvas.tokens.get(defenderRoll.active.tokenId)
if (defenderToken) {
return RdDCombat.rddCombatForAttackerAndDefender(defenderRoll.opponent.id, defenderRoll.opponent.tokenId, defenderRoll.active.tokenId)
}
}
/* -------------------------------------------- */
static onMsgEncaisser(msg) {
let defender = canvas.tokens.get(msg.defenderToken.id).actor;
@@ -612,63 +626,22 @@ 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() {
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
return
@@ -686,8 +659,7 @@ export class RdDCombat {
}
async doRollAttaque(rollData, callbacks = []) {
// TODO V2 await this.proposerAjustementTirLancer(rollData)
await RollDialog.create(rollData, {
return await RollDialog.create(rollData, {
onRollDone: RollDialog.onRollDoneClose,
callbacks: [
async (roll) => await this.onAttaqueV2(roll),
@@ -722,11 +694,26 @@ export class RdDCombat {
await this._chatMessageDefenseV2(paramChatDefense);
}
else {
this._socketSendMessageDefense(paramChatDefense, {});
this._socketSendMessageDefenseV2(paramChatDefense);
}
}
_socketSendMessageDefenseV2(paramChatDefense) {
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_defense_v2", data: { paramChatDefense } })
}
static async onMsgDefenseV2(msg) {
if (Misc.isFirstConnectedGM()) {
const paramChatDefense = msg.paramChatDefense
RollBasicParts.restore(paramChatDefense.attackerRoll)
const rddCombat = RdDCombat.rddCombatForAttackV2(paramChatDefense.attackerRoll)
rddCombat?.removeChatMessageActionsPasseArme(paramChatDefense.attackerRoll.passeArme)
await rddCombat?._chatMessageDefenseV2(paramChatDefense)
}
}
async _chatMessageDefenseV2(paramDemandeDefense) {
const attackerRoll = paramDemandeDefense.attackerRoll;
const attackerRoll = paramDemandeDefense.attackerRoll
RollBasicParts.loadSurprises(attackerRoll)
attackerRoll.dmg = RdDBonus.dmgRollV2(attackerRoll, attackerRoll.current.attaque)
@@ -1056,8 +1043,7 @@ export class RdDCombat {
}
async defenseV2(attackerRoll, callbacks = []) {
// this._prepareParade(attackerRoll, arme, competence);
RollDialog.loadRollData(attackerRoll)
await this.doRollDefense({
ids: {
actorId: this.defender.id,
@@ -1072,7 +1058,7 @@ export class RdDCombat {
}
async doRollDefense(rollData, callbacks = []) {
await RollDialog.create(rollData, {
return await RollDialog.create(rollData, {
onRollDone: RollDialog.onRollDoneClose,
callbacks: [
async (roll) => {

View File

@@ -127,7 +127,7 @@ export class RdDCommands {
<br><strong>/rdd 15 -2</strong> effectue un jet 15 à -2
<br><strong>/rdd 15 0 s</strong> effectue un jet 15 à 0, avec significative requise
<br><strong>/rdd Vue Vigilance -2</strong> effectue un jet de Vue/Vigilance à -2 pour les tokens sélectionnés
<br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés
<br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en Désert à +2 pour les tokens sélectionnés
`
});
this.registerCommand({
@@ -137,7 +137,7 @@ export class RdDCommands {
<br><strong>/jet Vue</strong> poste une demande de jet de VUE à 0
<br><strong>/jet Vue -2</strong> poste une demande de jet de VUE à -2
<br><strong>/jet Vue Vigilance -2</strong> poste une demande de jet de VUE / Vigilance à -2
<br><strong>/jet vol déser +2</strong> poste une demande de jet de VOLONTÉ / Survie en désert à +2
<br><strong>/jet vol déser +2</strong> poste une demande de jet de VOLONTÉ / Survie en Désert à +2
`
});
this.registerCommand({ path: ["/ddr"], func: (content, msg, params) => this.rollDeDraconique(msg), descr: "Lance un Dé Draconique" });

View File

@@ -17,18 +17,25 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static isCombatantEmpoignade(actorId, tokenId) {
const combatant = RdDCombatManager.getCombatant(actorId, tokenId)
return MAP_PHASE.empoignade.rang == combatant?.system.init.rang
return MAP_PHASE.empoignade.rang == combatant?.system.init?.rang
}
static async ajustementEmpoignade(attacker, defender, adjust = 1) {
const empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
const empId = empoignade?.system.empoignadeid ?? foundry.utils.randomID(16)
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
if (empoignade?.system.empoigneurid == defender.id) {
let 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
if (empoignade) {
if (empoignade.system.empoigneurid == defender.id) {
adjust = - adjust
}
empoignade.system.pointsemp += adjust
await RdDEmpoignade.$updateEtatEmpoignade(empoignade, attacker, defender)
empoignade.system.pointsemp = empFin;
await RdDEmpoignade.$updateEtatEmpoignade(empoignade, attacker, defender);
}
else {
await RdDEmpoignade.$createEtatEmpoignade({
@@ -39,24 +46,26 @@ export class RdDEmpoignade {
empoignadeid: empId,
empoigneurid: attacker.id,
empoigneid: defender.id,
pointsemp: adjust,
pointsemp: empFin,
empoigneurname: attacker.name,
empoignename: defender.name
}
}, attacker, defender)
}, attacker, defender);
}
if (adjust != 0 && empFin == 2) {
await RdDEmpoignade.proposerEntrainerAuSol(attacker, defender, empoignade);
}
const result = RdDEmpoignade.getEmpoignadeById(defender, empId);
const defGrappled = result.system.pointsemp == (result.system.empoigneid == defender.id ? 2 : -2)
const attGrappled = result.system.pointsemp == (result.system.empoigneurid == attacker.id ? -2 : 2)
const grappling = Math.abs(result.system.pointsemp) > 0
await defender.setEffect(STATUSES.StatusGrappling, grappling && !defGrappled)
await attacker.setEffect(STATUSES.StatusGrappling, grappling && !attGrappled)
await defender.setEffect(STATUSES.StatusGrappled, defGrappled)
await attacker.setEffect(STATUSES.StatusGrappled, attGrappled)
const defGrappled = result.system.pointsemp == (result.system.empoigneid == defender.id ? 2 : -2);
const attGrappled = result.system.pointsemp == (result.system.empoigneurid == attacker.id ? -2 : 2);
const grappling = Math.abs(result.system.pointsemp) > 0;
await defender.setEffect(STATUSES.StatusGrappling, grappling && !defGrappled);
await attacker.setEffect(STATUSES.StatusGrappling, grappling && !attGrappled);
await defender.setEffect(STATUSES.StatusGrappled, defGrappled);
await attacker.setEffect(STATUSES.StatusGrappled, attGrappled);
return result
}
/* -------------------------------------------- */
static registerChatCallbacks(html) {
$(html).on("click", '.defense-empoignade-cac', event => {
@@ -80,20 +89,20 @@ export class RdDEmpoignade {
const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
RdDEmpoignade.entrainerAuSol(rollData)
ChatUtility.removeChatMessageId(chatMessage.id)
ChatUtility.remover(chatMessage)()
});
$(html).on("click", '.empoignade-projeter-sol', event => {
const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
RdDEmpoignade.projeterAuSol(rollData)
ChatUtility.removeChatMessageId(chatMessage.id)
ChatUtility.remover(chatMessage)()
});
$(html).on("change", '.empoignade-perte-endurance', event => {
const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
if (event.currentTarget.value && event.currentTarget.value != "none") {
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
ChatUtility.removeChatMessageId(chatMessage.id)
ChatUtility.remover(chatMessage)()
}
});
}
@@ -138,8 +147,7 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static getEmpoignadeById(actor, id) {
let emp = actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id)
return emp && foundry.utils.duplicate(emp) || undefined;
return actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id)
}
/* -------------------------------------------- */
@@ -233,12 +241,24 @@ export class RdDEmpoignade {
MappingCreatureArme.setRollDataCreature(rollData)
}
if (empoignade.system.pointsemp >= 2) {
if (!empoignade.system.ausol) {
let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
}
await RdDEmpoignade.proposerEntrainerAuSol(attacker, defender, empoignade)
} else {
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle);
await RdDEmpoignade.$rollAttaqueEmpoignade(attacker, rollData, isNouvelle)
}
}
static async proposerEntrainerAuSol(attacker, defender, empoignade) {
if (!empoignade.system.ausol) {
const mode = (empoignade && empoignade.system.empoigneurid == attacker.id) ? "empoigner" : "liberer"
const rollData = {
mode, empoignade, attacker, defender,
isEmpoignade: true,
competence: attacker.getCompetenceCorpsACorps(),
selectedCarac: attacker.system.carac.melee,
malusTaille: RdDEmpoignade.getMalusTaille(empoignade, attacker, defender)
}
const msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
}
}
@@ -249,7 +269,14 @@ export class RdDEmpoignade {
await this.onAttaqueEmpoignadeValidee(attacker, defender)
}
static async onImmobilisation(attacker, defender, empoignade) {
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,
@@ -372,29 +399,35 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static async $updateEtatEmpoignade(empoignade, attacker, defender) {
console.log("UPDATE Empoignade", empoignade)
const belligerants = [
attacker ?? game.actors.get(empoignade.system.empoigneurid),
defender ?? game.actors.get(empoignade.system.empoigneid)]
const removeEmp = empoignade.system.pointsemp == 0
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 (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
}])
}))
}
}
/* -------------------------------------------- */
static async $deleteEmpoignade(empoignade) {
console.log("DELETE Empoignade", empoignade)
let defender = game.actors.get(empoignade.system.empoigneid)
let emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
await defender.deleteEmbeddedDocuments('Item', [emp._id])
const defender = game.actors.get(empoignade.system.empoigneid)
const emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
await defender.deleteEmbeddedDocuments('Item', [emp.id])
}
/* -------------------------------------------- */
@@ -436,29 +469,28 @@ export class RdDEmpoignade {
static async perteEndurance(rollData, perteMode) {
let attacker = game.actors.get(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id)
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
if (perteMode == "none" || !RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return
}
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
//console.log("Perte d'endurance :!!!", perteMode)
let endValue = defender.system.sante.endurance.value
if (perteMode == "end0") {
await defender.santeIncDec("endurance", -endValue);
}
if (perteMode == "end1") {
await defender.santeIncDec("endurance", -(endValue - 1));
}
if (perteMode == "endmoitie") {
await defender.santeIncDec("endurance", -Math.floor(endValue / 2));
}
if (perteMode == "endquart") {
await defender.santeIncDec("endurance", -(3 * Math.floor(endValue / 4)));
}
let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-perte-endurance.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
const perteEndurance = await RdDEmpoignade.$calcPerteEnd(perteMode, defender.system.sante.endurance.value)
await defender.santeIncDec("endurance", -perteEndurance)
await RdDRollResult.displayRollData({ attacker, defender, perteEndurance },
attacker,
'chat-empoignade-perte-endurance.hbs')
}
static async $calcPerteEnd(perteMode, endValue) {
switch (perteMode) {
case "none": return 0
case "end0": return endValue
case "end1": return (endValue - 1)
case "3/4": return Math.floor(3 * endValue / 4)
case "1/2": return Math.floor(endValue / 2)
case "1/4": return Math.floor(endValue / 4)
}
const rolled = await (new Roll(perteMode).evaluate())
return rolled.total
}
/* -------------------------------------------- */
static async deleteAllEmpoignades() {
for (let actor of game.actors) {
@@ -473,7 +505,7 @@ export class RdDEmpoignade {
let actor = game.actors.get(actorDeleteId)
let emp = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
if (emp) {
await actor.deleteEmbeddedDocuments('Item', [emp._id])
await actor.deleteEmbeddedDocuments('Item', [emp.id])
}
}

View File

@@ -0,0 +1,261 @@
import { ITEM_TYPES, RDD_CONFIG } from "./constants.js";
import { RollBasicParts } from "./roll/roll-basic-parts.mjs";
import { ChatUtility } from "./chat-utility.js";
import RollDialog from "./roll/roll-dialog.mjs";
import { Targets } from "./targets.js";
import { RdDUtility } from "./rdd-utility.js";
import { ROLL_TYPE_POSSESSION } from "./roll/roll-constants.mjs";
import { TokenActor } from "./technical/actor-token.mjs";
export const ACTIONS_POSSESSION = {
ATTAQUE: 'attaque',
POSSEDER: 'posseder',
CONJURER: 'conjurer',
DEFENSE: 'defense',
DEFENSE_POSSESSION: 'defense-possession',
DEFENSE_CONJURATION: 'defense-conjuration'
}
export class RdDPossessionV2 {
static init() {
}
static $isInverse(entite, victime) {
return !entite.actor.isEntiteNonIncarnee() && victime.actor.isEntiteNonIncarnee()
}
/* -------------------------------------------- */
static findPossession(entite, victime) {
if (RdDPossessionV2.$isInverse(entite, victime)) {
return RdDPossessionV2.findPossession(victime, entite)
}
return victime.actor.itemTypes[ITEM_TYPES.possession].find(it => it.system.entiteid == entite.id)
}
static async createPossessionIfMissing(entite, victime) {
if (RdDPossessionV2.$isInverse(entite, victime)) {
return await RdDPossessionV2.createPossessionIfMissing(victime, entite)
}
const existing = RdDPossessionV2.findPossession(entite, victime)
if (!existing) {
await victime.actor.createEmbeddedDocuments('Item', [{
name: `Possession de ${entite.name}`,
type: ITEM_TYPES.possession,
img: RDD_CONFIG.icons.possession,
system: {
entiteid: entite.actor.id,
entitetokenid: entite.token.id,
victimeid: victime.actor.id,
victimetokenid: victime.token.id,
compteur: 0
}
}])
}
}
static getTypePossession(active, opponent) {
const itemPossession = RdDPossessionV2.findPossession(active, opponent)
const isEntite = active.actor.isEntiteNonIncarnee() && !opponent.actor.isEntiteNonIncarnee()
const compteur = itemPossession?.system.compteur ?? 0
return {
isEntite: isEntite,
isPersonnage: active.actor.isPersonnage(),
isCompteurPossession: Math.sign(compteur) >= 0,
compteur: Math.abs(compteur)
}
}
static getTypePossessionAction(active, opponent, action) {
const possession = RdDPossessionV2.getTypePossession(active, opponent)
possession.isAttaque = RdDPossessionV2.isAttaque(action)
possession.action = RdDPossessionV2.$getAction(possession.isAttaque, possession.isEntite)
return possession
}
static $getAction(isAttaque, isEntite) {
if (isAttaque) {
return isEntite ? ACTIONS_POSSESSION.POSSEDER : ACTIONS_POSSESSION.CONJURER
}
return isEntite ? ACTIONS_POSSESSION.DEFENSE_CONJURATION : ACTIONS_POSSESSION.DEFENSE_POSSESSION
}
static actionTitle(action) {
switch (action) {
case ACTIONS_POSSESSION.POSSEDER: return "tente de posséder"
case ACTIONS_POSSESSION.CONJURER: return "tente de conjurer"
case ACTIONS_POSSESSION.DEFENSE_POSSESSION: return "résiste à la possession de"
case ACTIONS_POSSESSION.DEFENSE_CONJURATION: return "résiste à la conjuration de"
case ACTIONS_POSSESSION.DEFENSE: return "résiste à "
}
return "lutte contre"
}
static isDefense(action) {
return [ACTIONS_POSSESSION.DEFENSE, ACTIONS_POSSESSION.DEFENSE_POSSESSION, ACTIONS_POSSESSION.DEFENSE_CONJURATION].includes(action)
}
static isAttaque(action) {
return [ACTIONS_POSSESSION.ATTAQUE, ACTIONS_POSSESSION.POSSEDER, ACTIONS_POSSESSION.CONJURER].includes(action)
}
static async rollAttaquePossession(actor) {
const selectedToken = RdDUtility.getSelectedToken(actor)
Targets.selectOneTargetToken(async target => {
RollDialog.create(
{
ids: {
actorId: actor.id,
actorTokenId: selectedToken.id,
opponentId: target.actor.id,
opponentTokenId: target.id
},
passeArme: foundry.utils.randomID(16),
type: { allowed: [ROLL_TYPE_POSSESSION], current: ROLL_TYPE_POSSESSION, possession: { action: ACTIONS_POSSESSION.ATTAQUE } },
},
{
onRollDone: RollDialog.onRollDoneClose,
callbacks: [
async (roll) => await RdDPossessionV2.createPossessionIfMissing(roll.active, roll.opponent),
async (roll) => RdDPossessionV2.$setParticuliereFinesse(roll),
async (roll) => await RdDPossessionV2.chatMessageDefensePossession(roll)
]
})
})
}
static async rollConjurerPossession(actor, possession) {
if (possession.system.possede){
ui.notifications.warn(`${actor.name} est totalement possédé, impossible de conjurer l'entité`)
return
}
RollDialog.create(
{
ids: {
actorId: possession.system.victimeid,
actorTokenId: possession.system.victimetokenid,
opponentId: possession.system.entiteid,
opponentTokenId: possession.system.entitetokenid
},
passeArme: foundry.utils.randomID(16),
type: { allowed: [ROLL_TYPE_POSSESSION], current: ROLL_TYPE_POSSESSION, possession: { action: ACTIONS_POSSESSION.ATTAQUE } },
},
{
onRollDone: RollDialog.onRollDoneClose,
callbacks: [
async (roll) => await RdDPossessionV2.createPossessionIfMissing(roll.active, roll.opponent),
async (roll) => RdDPossessionV2.$setParticuliereFinesse(roll),
async (roll) => await RdDPossessionV2.chatMessageDefensePossession(roll)
]
})
}
static $setParticuliereFinesse(roll) {
if (roll.rolled.isPart) {
roll.particuliere = RDD_CONFIG.particuliere.finesse.key
}
}
static async rollDefensePossession(savedRoll, chatMessage) {
RollBasicParts.restore(savedRoll)
const attackerRoll = savedRoll.attackerRoll
RollDialog.create(
{
ids: savedRoll.ids,
passeArme: attackerRoll.passeArme,
type: { allowed: [ROLL_TYPE_POSSESSION], current: ROLL_TYPE_POSSESSION, possession: { action: ACTIONS_POSSESSION.DEFENSE } },
selected: { diff: { value: attackerRoll.selected?.diff?.value ?? 0 } },
attackerRoll: attackerRoll
},
{
onRollDone: RollDialog.onRollDoneClose, callbacks: [
async roll => await RdDPossessionV2.onRollDefense(roll),
ChatUtility.remover(chatMessage)
]
});
}
static async onRollDefense(defense) {
if (defense.rolled.isEchec) {
await RdDPossessionV2.addPointPossession(defense.opponent, defense.active)
}
RdDPossessionV2.resetPossession(defense)
}
static async onMarquerPointPossession(roll) {
roll.type = {}
await RdDPossessionV2.addPointPossession(roll.opponent, roll.active)
RdDPossessionV2.resetPossession(roll)
await ChatMessage.create({
// message privé: du défenseur à lui même (et aux GMs)
speaker: ChatMessage.getSpeaker({ actor: roll.active.actor, token: roll.active.token }),
alias: roll.opponent.name,
whisper: ChatUtility.getOwners(roll.active.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/possession/chat-message-marquer.hbs`, roll)
})
}
static resetPossession(roll) {
roll.type.possession = foundry.utils.mergeObject(
roll.type.possession ?? {},
RdDPossessionV2.getTypePossession(roll.opponent, roll.active))
}
static async addPointPossession(entite, victime, points = 1) {
if (RdDPossessionV2.$isInverse(entite, victime)) {
return await RdDPossessionV2.addPointPossession(victime, entite, - points)
}
const existing = RdDPossessionV2.findPossession(entite, victime)
if (existing) {
const compteur = (existing.system.compteur ?? 0) + points
await victime.actor.updateEmbeddedDocuments('Item', [{ _id: existing.id, 'system.compteur': compteur }])
}
}
static async chatMessageDefensePossession(attackerRoll) {
const defense = RollBasicParts.prepareDefense(attackerRoll)
defense.type = {
possession: RdDPossessionV2.getTypePossessionAction(defense.active, defense.opponent, ACTIONS_POSSESSION.DEFENSE)
}
const chatDemandeDefense = await ChatMessage.create({
// message privé: du défenseur à lui même (et aux GMs)
speaker: ChatMessage.getSpeaker({ actor: defense.active.actor, token: defense.active.token }),
alias: attackerRoll.active.name,
whisper: ChatUtility.getOwners(defense.active.actor),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/possession/chat-demande-defense.hbs', defense)
});
ChatUtility.setMessageData(chatDemandeDefense, 'demande-defense', true)
// // flag pour garder les jets d'attaque/defense
ChatUtility.setMessageData(chatDemandeDefense, 'rollData', {
ids: defense.ids,
attackerRoll: RollDialog.saveParts(attackerRoll),
passeArme: defense.passeArme
})
}
static async onPossession(actor, possession) {
if (Math.abs(possession.system.compteur) >= 2) {
await ChatMessage.create({
alias: actor.getAlias(),
whisper: ChatUtility.getOwners(actor),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/possession/chat-fin-possession.hbs', {
possession,
active: TokenActor.fromActor(actor),
opponent: TokenActor.fromActor(game.actors.get(possession.system.entiteid))
})
})
if (possession.system.compteur <= -2) {
await actor.deleteEmbeddedDocuments('Item', [possession.id])
}
if (possession.system.compteur >= 2) {
await actor.updateEmbeddedDocuments('Item', [{ _id: possession.id, 'system.possede': true }])
}
}
}
}

View File

@@ -18,9 +18,9 @@ export class RdDPossession {
/* -------------------------------------------- */
static searchPossessionFromEntite(attacker, defender) {
let poss = attacker.items.find(poss => poss.type == ITEM_TYPES.possession && poss.system.victime.actorid == defender.id);
let poss = attacker.itemTypes[ITEM_TYPES.possession].find(poss => poss.system.victime.actorid == defender.id);
if (!poss) {
poss = defender.items.find(poss => poss.type == ITEM_TYPES.possession && poss.system.victime.actorid == defender.id);
poss = defender.itemTypes[ITEM_TYPES.possession].find(poss => poss.system.victime.actorid == defender.id);
}
return poss && foundry.utils.duplicate(poss) || undefined;
}
@@ -94,7 +94,7 @@ export class RdDPossession {
}
static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
rollData.competence = rollingActor.getDraconicOuPossession();
rollData.competence = rollingActor.getDraconicOuPossession().find(it => true);
if (rollingActor.isCreatureOuEntite()) {
const carac = rollingActor.system.carac
rollData.carac = carac
@@ -132,7 +132,7 @@ export class RdDPossession {
}
const possession = (rollData.isECNIDefender ? rollData.attacker : rollData.defender).getPossession(rollData.possession.system.possessionid)
RdDPossession.storePossessionAttaque(possession, rollData)
await RdDRollResult.displayRollData(rollData, rollData.defender, 'chat-resultat-possession.hbs');
await RdDRollResult.displayRollData(rollData, rollData.defender, 'chat-resultat-possession-v1.hbs');
}
/* -------------------------------------------- */
@@ -172,7 +172,7 @@ export class RdDPossession {
rollData.possession = possession
RdDPossession.$updateEtatPossession(rollData.possession)
await RdDRollResult.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession.hbs')
await RdDRollResult.displayRollData(rollData, rollData.attacker, 'chat-resultat-possession-v1.hbs')
if (rollData.possession.isPosseder || rollData.possession.isConjurer) {
// conjuration
await victime.deleteEmbeddedDocuments("Item", [rollData.possession._id])
@@ -226,15 +226,18 @@ export class RdDPossession {
/* -------------------------------------------- */
static async createPossession(attacker, defender) {
return await Item.create({
name: "Possession en cours de " + attacker.name, type: 'possession',
img: "systems/foundryvtt-reve-de-dragon/icons/entites/possession2.webp",
name: `Possession de ${entite.name}`,
type: ITEM_TYPES.possession,
img: RDD_CONFIG.icons.possession,
system: {
description: "", typepossession: attacker.name,
typepossession: attacker.name,
possede: false,
possessionid: foundry.utils.randomID(16),
entiteid: attacker.id,
victimeid: defender.id,
compteur: 0,
entite: { actorid: attacker.id },
victime: { actorid: defender.id },
compteur: 0
victime: { actorid: defender.id }
}
},
{

View File

@@ -16,7 +16,7 @@ export class RdDEncaisser extends Dialog {
/* -------------------------------------------- */
constructor(html, actor) {
if (actor.isEntiteNonIncarnee([ENTITE_NONINCARNE])) {
if (actor.isEntiteNonIncarnee()) {
throw `${actor.name} est une entité non incarnée et ne peut pas subnir de dommages`
}

View File

@@ -13,7 +13,6 @@ 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";
@@ -187,7 +186,9 @@ export class RdDTMRDialog extends Dialog {
async restoreTMRAfterAction() {
this.subdialog = undefined
await this.maximize()
this.bringToFront()
if (this.rendered) {
this.bringToFront()
}
}
forceTMRContinueAction() {
@@ -348,10 +349,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
}

View File

@@ -34,7 +34,7 @@ export class RdDTokenHud {
const actor = RdDCombatManager.getActorCombatant(combatant, { warning: false })
if (actor) {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
await RdDTokenHud.addExtensionHudCombat(html, combatant, actor, token)
await RdDTokenHud.addExtensionHudCombatV2(html, combatant, actor, token)
}
else {
const actions = RdDCombatManager.listActionsActorCombatant(actor)
@@ -47,17 +47,28 @@ export class RdDTokenHud {
}
}
static async addExtensionHudCombat(html, combatant, actor, token) {
const actionsActor = actor.listActionsCombat();
static async addExtensionHudCombatV2(html, combatant, actor, token) {
const isPossession = actor.listActionsPossessions().length > 0;
const actionsCombat = isPossession ? [] : actor.listAttaques()
const ajustements = combatant?.initiative ?
[
{ label: 'Initiative +1', action: 'delta', value: 1 },
{ label: 'Initiative -1', action: 'delta', value: -1 }
] : []
const autres = [{ label: "Autre action", action: 'autre' }]
const actions = Misc.indexed(actionsActor.concat(ajustements).concat(autres))
const actions = Misc.indexed([
...actionsCombat,
...ajustements,
...autres
])
const hudData = { combatant, token, actions };
const hudData = {
combatant,
token,
isPossession,
isEntiteNonIncarnee: actor.isEntiteNonIncarnee(),
actions,
};
const hud = $(await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/hud-actor-combat.hbs', hudData))
$(html).find('div.col.left').append(hud)
@@ -84,6 +95,7 @@ export class RdDTokenHud {
}
})
list.find('.rdd-attaque-v2').click(event => combatant.actor.rollAttaque(token))
list.find('.rdd-possession-v2').click(event => combatant.actor.rollPossession())
}
static async addExtensionHudInit(html, combatant, actions) {

View File

@@ -18,7 +18,7 @@ import { RdDEmpoignade } from "./rdd-empoignade.js";
import { ExperienceLog } from "./actor/experience-log.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { APP_ASTROLOGIE_REFRESH } from "./sommeil/app-astrologie.js";
import { ITEM_TYPES, RDD_CONFIG, SYSTEM_RDD } from "./constants.js";
import { ACTOR_TYPES, ITEM_TYPES, RDD_CONFIG, SYSTEM_RDD } from "./constants.js";
import { RdDBaseActor } from "./actor/base-actor.js";
import { RdDCarac } from "./rdd-carac.js";
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
@@ -26,6 +26,8 @@ import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
import { RdDItemCompetence } from "./item-competence.js";
import { Monnaie } from "./item-monnaie.js";
import { ItemAction } from "./item/item-actions.js";
import { Targets } from "./targets.js";
import { DialogSelect } from "./dialog-select.js";
/* -------------------------------------------- */
// This table starts at 0 -> niveau -10
@@ -180,9 +182,14 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/item/partial-inventaire.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-environnement.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-tab-environnement.hbs',
'systems/foundryvtt-reve-de-dragon/templates/header-item.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/queue-sheet.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-header.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-hautrevant.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-frequence.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-description.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/partial-appreciable.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/enum-appreciation-bonmoment.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/enum-appreciation-carac.hbs',
'systems/foundryvtt-reve-de-dragon/templates/item/enum-appreciation-moral.hbs',
// partial enums
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.hbs',
@@ -232,9 +239,6 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-item-hautrevant.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-item-frequence.hbs',
'systems/foundryvtt-reve-de-dragon/templates/partial-item-description.hbs',
'systems/foundryvtt-reve-de-dragon/templates/roll/explain.hbs',
'systems/foundryvtt-reve-de-dragon/templates/resolution-table.hbs',
// Dialogs
@@ -776,8 +780,9 @@ export class RdDUtility {
let sommeAPayer = Number(event.currentTarget.attributes['data-somme-a-payer']?.value ?? 0);
let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:");
if (actor) {
actor.payerSols(sommeAPayer);
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget));
actor.payerSols(sommeAPayer)
const chatMessage = RdDUtility.findChatMessageId(event.currentTarget)
ChatUtility.remover(chatMessage)()
}
});
$(html).on("click", '.rdd-world-content-link', async event => {
@@ -846,6 +851,26 @@ export class RdDUtility {
return undefined;
}
static doWithSelectedActor(onSelected = () => { }, filter = actor => true) {
const selected = RdDUtility.getSelectedActor()
if (selected) {
onSelected(selected)
}
else {
const actors = game.actors
.filter(it => it.getUserLevel(game.user) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER)
.filter(it => ![ACTOR_TYPES.commerce, ACTOR_TYPES.vehicule].includes(it.type))
.filter(filter)
const selectData = {
title: "Choisir un acteur",
label: "Choisir un acteur",
list: actors.map(it => Targets.extractActorData(it))
};
DialogSelect.select(selectData, it => onSelected(game.actors.get(it.id)))
}
}
/* -------------------------------------------- */
static createMonnaie(name, cout, img = "", enc = 0.01) {
let piece = {

View File

@@ -12,6 +12,10 @@ import { PART_DEFENSE } from "./roll-part-defense.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.mjs"
import { RdDRollTables } from "../rdd-rolltables.js"
import { RdDEmpoignade } from "../rdd-empoignade.js"
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"
export default class ChatRollResult {
static init() {
@@ -22,14 +26,16 @@ export default class ChatRollResult {
static onReady() {
foundry.applications.handlebars.loadTemplates({
'partial-infojet': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-infojet.hbs',
'partial-appel-chance': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-appel-chance.hbs',
'partial-apprecier': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-apprecier.hbs',
'partial-appreciation': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-appreciation.hbs',
'partial-attaque-particuliere': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-attaque-particuliere.hbs',
'partial-choix-maladresse': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-choix-maladresse.hbs',
'partial-maladresse': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-maladresse.hbs',
'partial-encaissement': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-encaissement.hbs',
'partial-recul-choc': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-recul-choc.hbs',
'partial-infojet': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-infojet.hbs',
'partial-info-appel-moral': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-info-appel-moral.hbs',
'partial-maladresse': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-maladresse.hbs',
'partial-recul-choc': 'systems/foundryvtt-reve-de-dragon/templates/roll/result/partial-recul-choc.hbs',
})
}
@@ -52,19 +58,20 @@ export default class ChatRollResult {
prepareDisplay(roll) {
roll.done = roll.done ?? {}
roll.show = roll.show ?? {}
roll.show.chance = this.isAppelChancePossible(roll)
roll.show.encaissement = this.isShowEncaissement(roll)
roll.show.recul = this.getRecul(roll)
roll.show.maladresse = this.getMaladresse(roll)
roll.show.chance = this.$isAppelChancePossible(roll)
roll.show.encaissement = this.$isShowEncaissement(roll)
roll.show.recul = this.$getRecul(roll)
roll.show.maladresse = this.$getMaladresse(roll)
}
isAppelChancePossible(roll) {
$isAppelChancePossible(roll) {
return roll.active.actor.isPersonnage() &&
roll.rolled.isEchec &&
RdDCarac.isActionPhysique(roll.current.carac?.key)
RdDCarac.isActionPhysique(roll.current.carac?.key) &&
!roll.type.appreciation
}
isShowEncaissement(roll) {
$isShowEncaissement(roll) {
switch (roll.type.current) {
case ROLL_TYPE_DEFENSE:
return roll.rolled.isEchec
@@ -72,7 +79,7 @@ export default class ChatRollResult {
return false
}
getMaladresse(roll) {
$getMaladresse(roll) {
switch (roll.type.current) {
case ROLL_TYPE_DEFENSE:
if (roll.rolled.isETotal) {
@@ -90,7 +97,7 @@ export default class ChatRollResult {
return undefined
}
getRecul(roll, defender = roll.active.actor, attacker = roll.opponent?.actor) {
$getRecul(roll, defender = roll.active.actor, attacker = roll.opponent?.actor) {
switch (roll.type.current) {
case ROLL_TYPE_DEFENSE:
{
@@ -133,10 +140,13 @@ export default class ChatRollResult {
$(html).on("click", '.appel-chance', event => this.onClickAppelChance(event))
$(html).on("click", '.appel-destinee', event => this.onClickAppelDestinee(event))
$(html).on("click", '.button-defense', event => this.onClickDefense(event))
$(html).on("click", '.button-defense-possession', event => this.onClickDefensePossession(event))
$(html).on("click", '.marquer-point-possession', event => this.onClickMarquerPointPossession(event))
$(html).on("click", '.encaissement', event => this.onClickEncaissement(event))
$(html).on("click", '.resister-recul', event => this.onClickRecul(event))
$(html).on("click", '.choix-particuliere', event => this.onClickChoixParticuliere(event))
$(html).on("click", '.faire-gouter', event => this.onClickFaireGouter(event))
$(html).on("click", '.apprecier', event => this.onClickApprecier(event))
$(html).on("click", '.monter-tmr-normale', event => this.onClickMonteeTMR(event, 'normal'))
$(html).on("click", '.monter-tmr-rapide', event => this.onClickMonteeTMR(event, 'rapide'))
$(html).on("click", '.tirer-maladresse', event => this.onClickTirerMaladresse(event))
@@ -152,12 +162,18 @@ export default class ChatRollResult {
return undefined
}
getActiveActor(roll) {
return roll.active?.actor ?? (roll.ids?.actorId ? game.actors.get(roll.ids.actorId) : undefined)
}
async saveChatMessageRoll(chatMessage, savedRoll) {
await ChatUtility.setMessageData(chatMessage, 'rollData', savedRoll)
}
loadChatMessageRoll(chatMessage) {
return ChatUtility.getMessageData(chatMessage, 'rollData')
const savedRoll = ChatUtility.getMessageData(chatMessage, 'rollData')
RollBasicParts.restore(savedRoll)
return savedRoll
}
async updateChatMessage(chatMessage, savedRoll) {
@@ -171,136 +187,178 @@ export default class ChatRollResult {
}
onClickAppelChance(event) {
event.preventDefault()
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
const actor = game.actors.get(savedRoll.ids.actorId)
actor.rollAppelChance(
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, it => it.rollAppelChance(
() => this.onAppelChanceSuccess(savedRoll, chatMessage),
() => this.onAppelChanceEchec(savedRoll, chatMessage))
event.preventDefault()
)
}
async onAppelChanceSuccess(savedRoll, chatMessage) {
const reRoll = foundry.utils.duplicate(savedRoll)
console.log('onAppelChanceSuccess savedRoll', savedRoll)
async onAppelChanceSuccess(reRoll, chatMessage) {
reRoll.type.retry = true
await this.updateChatMessage(chatMessage, reRoll)
const callbacks = [r => ChatUtility.removeChatMessageId(chatMessage.id)]
// TODO: annuler les effets
const callbacks = [ChatUtility.remover(chatMessage)]
// TODO: annuler les effets...
switch (reRoll.type.current) {
case ROLL_TYPE_DEFENSE:
this.getCombat(reRoll)?.doRollDefense(reRoll, callbacks)
break
case ROLL_TYPE_ATTAQUE:
// TODO
this.getCombat(reRoll)?.doRollAttaque(reRoll, callbacks)
break
default: {
RollDialog.create(reRoll, { callbacks: callbacks })
await RollDialog.create(reRoll, { onRollDone: RollDialog.onRollDoneClose, callbacks })
}
}
}
async onAppelChanceEchec(savedRoll, chatMessage) {
savedRoll.type.retry = true
await this.updateChatMessage(chatMessage, savedRoll)
async onAppelChanceEchec(reRoll, chatMessage) {
reRoll.type.retry = true
await this.updateChatMessage(chatMessage, reRoll)
}
onClickAppelDestinee(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)
actor.appelDestinee(async () => {
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)
})
}))
}
async onClickDefense(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
const attackerRoll = savedRoll.attackerRoll
this.getCombat(attackerRoll)?.defenseV2(attackerRoll,
[roll => { ChatUtility.removeChatMessageId(chatMessage.id) }]
)
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)
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)
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 attackerToken = savedRoll.ids.opponentTokenId ? canvas.tokens.get(savedRoll.ids.opponentTokenId) : undefined
switch (attaque.dmg.mortalite) {
case RDD_CONFIG.encaissement.empoignade:
savedRoll.done = savedRoll.done ?? {}
savedRoll.done.empoignade = await RdDEmpoignade.ajustementEmpoignade(attackerToken.actor, defenderToken.actor)
break
case RDD_CONFIG.encaissement.entiteincarnee:
case RDD_CONFIG.encaissement.nonmortel:
case RDD_CONFIG.encaissement.mortel:
const defender = defenderToken?.actor ?? game.actors.get(savedRoll.ids.actorId)
const attacker = attackerToken?.actor ?? game.actors.get(savedRoll.ids.opponentId)
await defender?.encaisserDommages(attaque.dmg, attacker, undefined, attackerToken, defenderToken)
break
}
if (isMessageDemande) {
ChatUtility.removeChatMessageId(chatMessage.id)
} else {
savedRoll.done.encaissement = true
await this.updateChatMessage(chatMessage, savedRoll)
}
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) {
case RDD_CONFIG.encaissement.empoignade:
savedRoll.done = savedRoll.done ?? {}
savedRoll.done.empoignade = await RdDEmpoignade.ajustementEmpoignade(attackerToken.actor, defenderToken.actor)
break
case RDD_CONFIG.encaissement.entiteincarnee:
case RDD_CONFIG.encaissement.nonmortel:
case RDD_CONFIG.encaissement.mortel:
await defender?.encaisserDommages(attaque.dmg, attacker, undefined, attackerToken, defenderToken)
break
}
if (isMessageDemande) {
ChatUtility.remover(chatMessage)()
} else {
savedRoll.done.encaissement = true
await this.updateChatMessage(chatMessage, savedRoll)
}
})
}
async onClickRecul(event) {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
const defender = game.actors.get(savedRoll.ids.actorId)
const attacker = game.actors.get(savedRoll.ids.opponentId)
savedRoll.done.recul = await defender.encaisserRecul(attacker.getForce(), savedRoll.attackerRoll.dmg.dmgArme)
// const reculChoc = this.getReculChoc(savedRoll, defender, attacker)
await this.updateChatMessage(chatMessage, savedRoll)
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)
})
}
async onClickChoixParticuliere(event) {
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)
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

@@ -11,7 +11,7 @@ export class RollBasicParts {
rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id
rollData.active = RollBasicParts.getTokenActor(rollData)
rollData.opponent = RollBasicParts.getTokenActorOpponent(rollData)
if (rollData.type.opposed == undefined) {
if (rollData.type && rollData.type.opposed == undefined) {
rollData.type.opposed = rollData.opponent != null
}
}
@@ -46,10 +46,10 @@ export class RollBasicParts {
type: rollData.type,
ids: {
sceneId: rollData.ids.sceneId,
actorId: rollData.active.id,
actorTokenId: rollData.active.tokenId,
opponentId: isOpposed ? rollData.opponent.id : undefined,
opponentTokenId: isOpposed ? rollData.opponent.tokenId : undefined,
actorId: rollData.ids.actorId,
actorTokenId: rollData.ids.actorTokenId,
opponentId: isOpposed ? rollData.ids.opponentId : undefined,
opponentTokenId: isOpposed ? rollData.ids.opponentTokenId : undefined,
}
}
}

View File

@@ -1,5 +1,6 @@
export const ROLL_TYPE_ATTAQUE = 'attaque'
export const ROLL_TYPE_POSSESSION = 'possession'
export const ROLL_TYPE_COMP = 'comp'
export const ROLL_TYPE_CUISINE = 'cuisine'
export const ROLL_TYPE_DEFENSE = 'defense'
@@ -12,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',
@@ -27,8 +27,8 @@ export const DIFF = {
export const DIFFS = {
[DIFF.LIBRE]: { key: DIFF.LIBRE, label: "Difficulté libre", libre: true, visible: true, max: 0 },
[DIFF.ATTAQUE]: { key: DIFF.ATTAQUE, label: "Difficulté d'attaque", libre: true, visible: true, max: 0 },
[DIFF.IMPOSEE]: { key: DIFF.IMPOSEE, label: "Diffficulté imposée", libre: false, visible: true, max: 0 },
[DIFF.DEFENSE]: { key: DIFF.DEFENSE, label: "Diffficulté défense", libre: false, visible: true, max: 0 },
[DIFF.IMPOSEE]: { key: DIFF.IMPOSEE, label: "Difficulté imposée", libre: false, visible: true, max: 20 },
[DIFF.DEFENSE]: { key: DIFF.DEFENSE, label: "Difficulté défense", libre: false, visible: true, max: 0 },
[DIFF.DEFAUT]: { key: DIFF.DEFAUT, label: "Difficulté", libre: true, visible: true, max: 5 },
[DIFF.AUCUN]: { key: DIFF.AUCUN, label: "", libre: false, visible: false, max: 0 },
}

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
}
@@ -77,7 +77,7 @@ export class RollDialogAdapter {
const compKey = rollData.current.comp?.key
if (compKey) {
rollData.competence = rollData.refs[PART_COMP].all.find(it => it.key == compKey)?.comp
rollData.jetResistance = rollData.type.jetResistance
rollData.jetResistance = rollData.type.resistance
}
if (rollData.type.current == ROLL_TYPE_OEUVRE) {
const oeuvreKey = rollData.current.oeuvre?.key
@@ -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

@@ -46,6 +46,11 @@ import { OptionsAvancees, ROLL_DIALOG_V2_TEST } from "../settings/options-avance
import { ActorImpacts } from "../technical/actor-impacts.mjs";
import { RollPartEmpoignade } from "./roll-part-empoignade.mjs";
import { RollPartEmpoignadeTaille } from "./roll-part-empoignade-taille.mjs";
import { RollPartEcailles } from "./roll-part-ecailles.mjs";
import { RollPartResistance } from "./roll-part-resistance.mjs";
import { RollTypePossession } from "./roll-type-possession.mjs";
import { RollPartPossession } from "./roll-part-possession.mjs";
import { RollPartApprecier } from "./roll-part-apprecier.mjs";
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
@@ -54,6 +59,7 @@ export const ALL_ROLL_TYPES = [
new RollTypeComp(),
new RollTypeTache(),
new RollTypeAttaque(),
new RollTypePossession(),
new RollTypeDefense(),
new RollTypeSort(),
new RollTypeMeditation(),
@@ -68,11 +74,14 @@ const ROLL_PARTS = [
new RollPartActor(),
new RollPartAction(),
new RollPartOpponent(),
new RollPartResistance(),
new RollPartCarac(),
new RollPartComp(),
new RollPartDiff(),
new RollPartApprecier(),
new RollPartAttaque(),
new RollPartPossession(),
new RollPartDefense(),
new RollPartMeditation(),
new RollPartSort(),
@@ -83,6 +92,7 @@ const ROLL_PARTS = [
new RollPartSign(),
new RollPartEcailles(),
new RollPartEtat(),
new RollPartConditions(),
new RollPartEthylisme(),
@@ -177,19 +187,25 @@ const ROLL_PARTS = [
/* -------------------------------------------- */
export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2)
{
static onCloseDoNothing() {
}
static onCloseDoNothing() { }
static onRollDoneDoNothing(dialog, roll) {
dialog.render()
}
static onRollDoneClose(dialog, roll) {
if (roll.type.retry || !OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST))
if (roll.type.retry) {
dialog.close()
}
else {
dialog.render()
}
}
static init() {
static onRollDoneClose(dialog, roll) {
if (roll.type.retry || !OptionsAvancees.isUsing(ROLL_DIALOG_V2_TEST)) {
dialog.close()
}
}
static init() { }
static onReady() {
foundry.applications.handlebars.loadTemplates({
@@ -239,9 +255,14 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
static async create(rollData, rollOptions = {}) {
const rollDialog = new RollDialog(rollData, rollOptions)
rollDialog.render(true)
return rollDialog
rollData = RollDialog.$prepareRollData(rollData)
return Misc.doIfOwner(rollData.active.actor,
actor => {
const rollDialog = new RollDialog(rollData, rollOptions)
rollDialog.render(true)
return rollDialog
}
)
}
static get PARTS() {
@@ -289,8 +310,10 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
rollData.refs = foundry.utils.mergeObject(rollData.refs ?? {}, Object.fromEntries(ROLL_PARTS.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))
ROLL_PARTS.forEach(p => RollDialog.$initializeRollPart(rollData, p.code))
ROLL_PARTS
.filter(p => RollDialog.$isIntersecting(allowed, p.rollTypes))
.filter(p => p.isValid(rollData))
.forEach(p => {
p.restore(rollData)
p.loadRefs(rollData)
@@ -299,15 +322,41 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
return rollData
}
static saveParts(rollData, impacts) {
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
}
function saveBasics(from, to) {
if (from) {
to.ids = from.ids
to.passeArme = from.passeArme
to.rolled = from.rolled
to.particuliere = from.particuliere
to.result = from.result
to.done = from.done ?? {}
to.dmg = from.dmg
if (from.attackerRoll) {
to.attackerRoll = {}
saveBasics(from.attackerRoll, to.attackerRoll)
}
if (from.current) {
// stockage de current
ROLL_PARTS.filter(p => p.isActive(from))
.forEach(p => p.storeClean(from, target))
}
}
}
const target = RollBasicParts.initFrom(rollData)
ROLL_PARTS.filter(p => p.isActive(rollData))
.forEach(p => p.storeClean(rollData, target))
target.attackerRoll = rollData.attackerRoll
target.rolled = rollData.rolled
target.result = rollData.result
target.done = rollData.done ?? {}
target.dmg = rollData.dmg
saveBasics(rollData, target)
if (impacts) {
target.reverse = {
active: impacts.active?.reverseImpacts(),
@@ -315,13 +364,14 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
}
}
return target
}
constructor(rollData, rollOptions) {
super()
this.hooks = []
this.rollData = RollDialog.$prepareRollData(rollData)
this.rollData = rollData
this.rollOptions = {
callbacks: [
async r => await r.active.actor.appliquerAjoutExperience(r),
@@ -333,7 +383,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
}
this.chatRollResult = new ChatRollResult()
this.selectType()
this.registerHooks(rollData);
this.registerHooks(rollData)
}
registerHooks(rollData) {
@@ -351,10 +401,11 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
selectType() {
const selectedType = this.getSelectedType();
this.rollData.type.label = selectedType.title(this.rollData)
const selectedType = this.getSelectedType()
selectedType.prepare(this.rollData)
selectedType.setRollDataType(this.rollData)
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)
@@ -499,6 +550,9 @@ 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

View File

@@ -0,0 +1,32 @@
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs";
export const PART_APPRECIER = "apprecier"
export class RollPartApprecier extends RollPart {
get code() { return PART_APPRECIER }
get section() { return ROLLDIALOG_SECTION.CHOIX }
restore(rollData) {
this.setCurrent(rollData, this.getSaved(rollData))
}
store(rollData, targetData) {
this.setSaved(targetData, this.getCurrent(rollData))
}
visible(rollData) {
return rollData.type.appreciation
}
getAjustements(rollData) {
const current = this.getCurrent(rollData)
if (current.appreciation.jetQualite){
return [{
label: 'Qualité',
value: Math.abs(current.qualite)
}]
}
return []
}
}

View File

@@ -1,5 +1,6 @@
import { Grammar } from "../grammar.js"
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
import { ROLL_TYPE_SORT } from "./roll-constants.mjs"
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
export const PART_ASTROLOGIQUE = "astrologique"
@@ -15,7 +16,7 @@ export class RollPartAstrologique extends RollPartCheckbox {
}
isLancementRituel(rollData) {
return false
return rollData.type.current == ROLL_TYPE_SORT && rollData.current.sort?.sort?.system.isrituel
}
isJetChance(rollData) {

View File

@@ -1,3 +1,4 @@
import { Distance } from "../combat/distance.mjs"
import { RDD_CONFIG } from "../constants.js"
import { ATTAQUE_TYPE_MELEE } from "../item/arme.js"
import { RdDBonus } from "../rdd-bonus.js"
@@ -10,7 +11,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_ATTAQUE = 'attaque'
@@ -25,12 +26,14 @@ 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))
refs.all = attaques.map(it => RollPartAttaque.$extractAttaque(it, rollData))
this.filterAttaquesEmpoignade(rollData)
refs.tactiques = TACTIQUES
if (refs.attaques.length > 0) {
@@ -64,10 +67,11 @@ export class RollPartAttaque extends RollPartSelect {
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)
return attaque
}
@@ -102,20 +106,22 @@ export class RollPartAttaque extends RollPartSelect {
}
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 +134,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) {
@@ -142,7 +150,8 @@ export class RollPartAttaque extends RollPartSelect {
comp: { key: 'Dague', forced: true },
diff: { type: DIFF.IMPOSEE, value: -4 }
}
})
},
{ onRollDone: RollDialog.onRollDoneClose })
}
impactOtherPart(part, rollData) {
@@ -152,8 +161,11 @@ export class RollPartAttaque extends RollPartSelect {
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

@@ -16,11 +16,9 @@ export class RollPartCarac extends RollPartSelect {
const selected = this.getSelected(rollData)
const actor = rollData.active.actor
refs.all = [...this.$getActorCaracs(actor), ...this.$getCaracCompetenceCreature(actor)]
.filter(c => !selected.forced ||
(selected.key ?
Grammar.includesLowerCaseNoAccent(c.label, selected.key)
: c.key == '')
)
if (selected.forced && selected.key) {
refs.all = refs.all.filter(c => c.key == selected.key || Grammar.includesLowerCaseNoAccent(c.label, selected.key))
}
refs.caracs = refs.all
this.$selectCarac(rollData)
}

View File

@@ -22,7 +22,12 @@ export class RollPartComp extends RollPartSelect {
if (selected.forced) {
refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selected.key))
if (refs.all.length == 0) {
refs.all = all.filter(comp => Grammar.includesLowerCaseNoAccent(comp.label, selected.key))
if (selected.key.length > 0) {
refs.all = all.filter(comp => Grammar.includesLowerCaseNoAccent(comp.label, selected.key))
}
else {
refs.all = all.filter(comp => comp == SANS_COMPETENCE)
}
}
}
else {

View File

@@ -4,7 +4,7 @@ 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"
@@ -16,8 +16,10 @@ export class RollPartCuisine extends RollPartSelect {
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)

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,59 @@ export class RollPartDefense extends RollPartSelect {
get code() { return PART_DEFENSE }
get section() { return ROLLDIALOG_SECTION.CHOIX }
isValid(rollData) { return rollData.attackerRoll != undefined }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_DEFENSE) }
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()))
: defenseur.items.filter(it => it.isParade() && (!refs.distance || it.isBouclier()))
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 {
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 +82,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,10 +118,11 @@ 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)
}
@@ -129,16 +141,19 @@ export class RollPartDefense extends RollPartSelect {
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

@@ -32,7 +32,7 @@ export class RollPartDiff extends RollPart {
}
visible(rollData) {
if (EXCLUDED_ROLL_TYPES.includes(rollData.type.current)) {
if (EXCLUDED_ROLL_TYPES.includes(rollData.type.current) || rollData.type.appreciation) {
return false
}
const current = this.getCurrent(rollData)

View File

@@ -0,0 +1,55 @@
import { RDD_CONFIG } from "../constants.js"
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"
export class RollPartEcailles extends RollPartCheckbox {
get code() { return ECAILLES }
get rollTypes() { return [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE] }
isValid(rollData) {
return RollPart.isRollType(rollData, ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE)
}
visible(rollData) {
return this.getEcailles(rollData) != 0
}
getEcailles(rollData) {
const arme = this.getArme(rollData)
return arme?.system.magique ? arme?.system.ecaille_efficacite : 0
}
getArme(rollData) {
return RollPart.isRollType(rollData, ROLL_TYPE_ATTAQUE)
? rollData.current[PART_ATTAQUE]?.arme
: RollPart.isRollType(rollData, ROLL_TYPE_DEFENSE)
? rollData.current[PART_DEFENSE]?.arme
: undefined
}
prepareContext(rollData) {
this.loadRefs(rollData)
super.prepareContext(rollData)
}
getCheckboxIcon(rollData) {
return this.getEcailles(rollData) > 0
? `<img src="${RDD_CONFIG.icons.magique}">`
: `<img src="${RDD_CONFIG.icons.armebrisee}">`
}
getCheckboxLabel(rollData) {
return this.getEcailles(rollData) > 0
? "Efficacité"
: "Défauts"
}
getCheckboxValue(rollData) { return this.getEcailles(rollData) }
}

View File

@@ -1,9 +1,8 @@
import { RDD_CONFIG } from "../constants.js"
import { ATTAQUE_TYPE_MELEE } from "../item/arme.js"
import { RdDEmpoignade } from "../rdd-empoignade.js"
import { COMBAT_ROLL_TYPES } from "./roll-constants.mjs"
import { PART_ATTAQUE } from "./roll-part-attaque.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"
@@ -11,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

@@ -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"
@@ -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

@@ -0,0 +1,86 @@
import { CATEGORIES_COMPETENCES_CREATURES } from "../item/base-items.js"
import { CARACS } from "../rdd-carac.js"
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs"
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, RollPart } from "./roll-part.mjs"
export const PART_POSSESSION = "possession"
export class RollPartPossession extends RollPartSelect {
/** TODO: remplacer selectOption par un sélecteur plus sympa (avec image de compétence, par exemple? */
get code() { return PART_POSSESSION }
get name() { return 'Possession' }
get section() { return ROLLDIALOG_SECTION.CHOIX }
get rollTypes() { return [ROLL_TYPE_POSSESSION] }
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_POSSESSION) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
refs.all = this.$getActorConjurations(rollData)
this.$selectPossession(rollData)
}
choices(refs) { return refs.all }
$getActorConjurations(rollData) {
const competences = rollData.active.actor.getDraconicOuPossession()
return competences.map(RollPartPossession.extractPossession)
}
static extractPossession(comp) {
return {
key: comp.id ?? comp.name,
label: `${comp.system.categorie == CATEGORIES_COMPETENCES_CREATURES.possession.key ? 'Possession' : 'Conjuration'} (${comp.name})`,
value: comp.system.niveau,
comp: comp
}
}
prepareContext(rollData) {
this.$selectPossession(rollData)
}
getAjustements(rollData) {
return []
}
async _onRender(rollDialog, context, options) {
const rollData = rollDialog.rollData
const select = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-possession"]`)
const button = rollDialog.element.querySelector(`roll-section[name="${this.code}"] button[name="creer-possession"]`)
select?.addEventListener("change", e => {
const selectOptions = e.currentTarget.options
const index = selectOptions.selectedIndex
this.$selectPossession(rollData, selectOptions[index]?.value)
rollDialog.render()
})
button?.addEventListener("click", async e => {
e.preventDefault()
await RdDPossessionV2.createPossessionIfMissing(rollData.active, rollData.opponent)
rollDialog.render()
})
}
$selectPossession(rollData, key) {
this.selectByKey(rollData, key, 0)
}
impactOtherPart(part, rollData) {
if (this.visible(rollData)) {
const current = this.getCurrent(rollData)
switch (part.code) {
case PART_CARAC: return part.filterCaracs(rollData, [rollData.type.possession.isPersonnage ? CARACS.REVE_ACTUEL : CARACS.REVE])
case PART_COMP: return part.filterComps(rollData, [current.comp?.name])
}
}
return undefined
}
}

View File

@@ -0,0 +1,12 @@
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
export const PART_RESISTANCE = "resistance"
export class RollPartResistance extends RollPart {
get code() { return PART_RESISTANCE }
get section() { return ROLLDIALOG_SECTION.ACTION }
isValid(rollData) { return rollData.type.resistance == true }
title(rollData) { return "de résistance" }
}

View File

@@ -1,8 +1,9 @@
import { RDD_CONFIG } from "../constants.js"
import { Misc } from "../misc.js"
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs"
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
import { demiReveStatusEffect, StatusEffects } from "../settings/status-effects.js"
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll-constants.mjs"
import { StatusEffects } from "../settings/status-effects.js"
import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE, ROLL_TYPE_POSSESSION } from "./roll-constants.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
export const PART_SIGN = "sign"
@@ -25,7 +26,7 @@ export class RollPartSign extends RollPart {
}
isCombat(rollData) {
return [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE].includes(rollData.type.current) || rollData.type.isCombat
return [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE, ROLL_TYPE_POSSESSION].includes(rollData.type.current)
}
prepareContext(rollData) {
@@ -40,7 +41,7 @@ export class RollPartSign extends RollPart {
const isCombat = this.isCombat(rollData)
const current = this.getCurrent(rollData)
current.armeDisparate = isCombat && current.armeDisparate
current.surprise = actor.getSurprise(isCombat, current.forceRequise ?? 0)
current.surprise = actor.getSurprise(isCombat, current.forceRequise ?? 0)
current.reasons = actor.getEffects(it => StatusEffects.niveauSurprise(it, isCombat) > 0, current.forceRequise ?? 0)
.map(it => { return { img: it.img, label: game.i18n.localize(it.name) } })
current.diviseur = 1
@@ -67,7 +68,16 @@ export class RollPartSign extends RollPart {
}
isAttaqueFinesse(rollData) {
return ROLL_TYPE_DEFENSE == rollData.type.current && rollData.attaque?.particuliere == 'finesse'
const attackerRoll = rollData.attackerRoll
if (rollData.attackerRoll){
switch (rollData.type.current) {
case ROLL_TYPE_DEFENSE:
return attackerRoll?.particuliere == RDD_CONFIG.particuliere.finesse.key
case ROLL_TYPE_POSSESSION:
return RdDPossessionV2.isDefense(rollData.type.possession.action) && attackerRoll?.particuliere == RDD_CONFIG.particuliere.finesse.key
}
}
return false
}
isParadeArmeDisparate(current) {

View File

@@ -2,7 +2,7 @@ import { ITEM_TYPES } from "../constants.js"
import { ROLL_TYPE_SORT } from "./roll-constants.mjs"
import { PART_CARAC } from "./roll-part-carac.mjs"
import { PART_COMP } from "./roll-part-comp.mjs"
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
import { TMRUtility } from "../tmr-utility.js"
import { RdDItemSort } from "../item-sort.js"
import { RollPartSelect } from "./roll-part-select.mjs"
@@ -19,8 +19,9 @@ export class RollPartSort extends RollPartSelect {
get code() { return PART_SORT }
get section() { return ROLLDIALOG_SECTION.CHOIX }
get rollTypes() { return [ROLL_TYPE_SORT] }
isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_SORT) }
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_SORT) }
restore(rollData) {
const saved = this.getSaved(rollData)

View File

@@ -3,7 +3,7 @@ import { ROLL_TYPE_TACHE } 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_TACHE = "tache"
@@ -12,8 +12,9 @@ export class RollPartTache extends RollPartSelect {
get code() { return PART_TACHE }
get section() { return ROLLDIALOG_SECTION.CHOIX }
get rollTypes() { return [ROLL_TYPE_TACHE] }
isValid(rollData) { return rollData.active.actor.isPersonnage() }
visible(rollData) { return this.isRollType(rollData, ROLL_TYPE_TACHE) }
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_TACHE) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)

View File

@@ -1,3 +1,5 @@
import { ALL_ROLL_TYPES } from "./roll-dialog.mjs"
export const ROLLDIALOG_SECTION = {
ACTION: 'action',
CARAC: 'carac',
@@ -19,17 +21,6 @@ export class RollPart {
/** le template handlebars pour affichage */
get template() { return `systems/foundryvtt-reve-de-dragon/templates/roll/roll-part-${this.code}.hbs` }
initialize(rollData) {
if (rollData.refs[this.code] == undefined) {
rollData.refs[this.code] = {}
}
if (rollData.current[this.code] == undefined) {
rollData.current[this.code] = {}
}
if (rollData.selected[this.code] == undefined) {
rollData.selected[this.code] = {}
}
}
/** l'acteur actif du jet */
getActor(rollData) { return rollData.active.actor }
/** le conteneur de données du RollPart */
@@ -78,8 +69,8 @@ export class RollPart {
* @returns une chaîne vide si rien ne doit être affiché
*/
title() { return '' }
isRollType(rollData, type) { return rollData.type.current == type }
static isRollType(rollData, ...type) { return type.includes(rollData.type.current) }
get rollTypes() { return undefined }
isActive(rollData) { return this.isValid(rollData) && this.visible(rollData) }
isValid(rollData) { return true }
visible(rollData) { return true }

View File

@@ -5,7 +5,12 @@ export class RollTypeComp extends RollType {
get code() { return ROLL_TYPE_COMP }
get name() { return `Jet de caractéristique / compétence` }
title(rollData) { return `fait un jet ${rollData.type.opposed ? ' contre ' : ''}` }
title(rollData) {
if (rollData.type.appreciation) {
return "fait un jet d'appéciation"
}
return `fait un jet ${rollData.type.opposed ? ' contre ' : ''}`
}
onSelect(rollData) {

View File

@@ -1,4 +1,5 @@
import { ITEM_TYPES } from "../constants.js"
import { APPRECIATION } from "../moral/apprecier.mjs"
import { RollBasicParts } from "./roll-basic-parts.mjs"
import { DIFF, ROLL_TYPE_CUISINE } from "./roll-constants.mjs"
import { PART_CUISINE } from "./roll-part-cuisine.mjs"
@@ -49,7 +50,7 @@ export class RollTypeCuisine extends RollType {
return result
}
onApplyImpacts(roll, impacts) {
if (roll.result.plat) {
if (roll.result.plat) {
// le plat n'est pas créé immédiatement, il faut donc retrouver l'id
roll.result.plat.id = impacts.findCreatedId('Item', roll.result.plat.id)
}
@@ -69,6 +70,7 @@ export class RollTypeCuisine extends RollType {
quantite: current.proportions,
qualite: result.qualite,
cout: result.qualite > 0 ? (result.qualite * 0.01) : 0.01,
appreciation: APPRECIATION.CUISINE
}
}
}

View File

@@ -1,6 +1,7 @@
import { PART_JEU, RollPartJeu } from "./roll-part-jeu.mjs"
import { RollType } from "./roll-type.mjs"
import { DIFF, ROLL_TYPE_JEU } from "./roll-constants.mjs"
import { Apprecier } from "../moral/apprecier.mjs"
export class RollTypeJeu extends RollType {
@@ -20,4 +21,8 @@ export class RollTypeJeu extends RollType {
RollPartJeu.forceCompJeu(rollData)
}
}
getResult(rollData, impacts) {
const current = rollData.current[PART_JEU]
return Apprecier.getAppreciation(current.qualite, current.jeu, rollData, current.comp)
}
}

View File

@@ -11,7 +11,7 @@ export class RollTypeMeditation extends RollType {
visible(rollData) { return rollData.active.actor.isHautRevant() }
title(rollData) {
const current = rollData.current[PART_MEDITATION]
const theme = current?.meditation.system.theme
const theme = current?.meditation?.system.theme
return theme ? 'médite sur ' + theme : 'médite'
}
@@ -23,7 +23,7 @@ export class RollTypeMeditation extends RollType {
static async $onRollMeditation(rollData) {
const actor = rollData.active.actor
const meditation = rollData.current.meditation.meditation
const meditation = rollData.current.meditation?.meditation
const rolled = rollData.rolled
if (meditation && rolled) {
if (rolled.isSuccess) {

View File

@@ -1,3 +1,4 @@
import { Apprecier } from "../moral/apprecier.mjs"
import { DIFF, ROLL_TYPE_OEUVRE } from "./roll-constants.mjs"
import { PART_OEUVRE } from "./roll-part-oeuvre.mjs"
import { RollType } from "./roll-type.mjs"
@@ -9,7 +10,10 @@ export class RollTypeOeuvre extends RollType {
visible(rollData) { return rollData.active.actor.isPersonnage() }
title(rollData) {
const current = rollData.current[PART_OEUVRE]
return `${current.art.action} ${current.label}`
if (current.art) {
return `${current.art.action} ${current.label}`
}
return 'interprête une oeuvre'
}
onSelect(rollData) {
@@ -18,12 +22,7 @@ export class RollTypeOeuvre extends RollType {
getResult(rollData, impacts) {
const current = rollData.current[PART_OEUVRE]
const qualite = rollData.rolled.isSuccess ? current.qualite : Math.min(current.qualite, current.comp.system.niveau)
return {
qualite: qualite + rollData.rolled.ptQualite,
messages: []
}
return Apprecier.getAppreciation(current.qualite, current.oeuvre, rollData, current.comp)
}
}

View File

@@ -0,0 +1,28 @@
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs"
import { DIFF, ROLL_TYPE_POSSESSION } from "./roll-constants.mjs"
import { RollType } from "./roll-type.mjs"
export class RollTypePossession extends RollType {
get code() { return ROLL_TYPE_POSSESSION }
get name() { return "Posséder" }
prepare(rollData) {
rollData.type.possession = RdDPossessionV2.getTypePossessionAction(rollData.active, rollData.opponent, rollData.type.possession?.action)
}
title(rollData) {
return RdDPossessionV2.actionTitle(rollData.type.possession.action)
}
onSelect(rollData) {
this.setDiffType(rollData, this.isAttaque(rollData) ? DIFF.ATTAQUE : DIFF.DEFENSE)
}
isEntite(rollData) {
return rollData.active.actor.isEntiteNonIncarnee()
}
isAttaque(rollData) {
return RdDPossessionV2.isAttaque(rollData.type.possession.action)
}
}

View File

@@ -16,6 +16,7 @@ export class RollType {
return { code: this.code, name: this.name, icon: this.icon, section: 'type', template: this.template, selected: this.isSelected(rollData) }
}
prepare(rollData){}
isAllowed(rollData) { return rollData.type.allowed == undefined || rollData.type.allowed.includes(this.code) }
visible(rollData) { return true }
title(rollData) { return this.code }
@@ -23,7 +24,6 @@ export class RollType {
setRollDataType(rollData) {
rollData.type.opposed = rollData.opponent != undefined
rollData.type.resistance = false /** TODO */
}
onSelect(rollData) {

View File

@@ -16,6 +16,7 @@ export const STATUSES = {
StatusDemiReve: 'demi-reve',
StatusSurEnc: 'sur-encombrement',
StatusForceWeak: 'force insuffisante',
StatusMalade: 'malade',
}
export const forceWeakStatusEffect = { rdd: true, id: STATUSES.StatusForceWeak, name: 'EFFECT.StatusForceWeak', img: RDD_CONFIG.icons.forceWeak };
@@ -35,11 +36,12 @@ const rddStatusEffects = [
{ rdd: true, id: STATUSES.StatusComma, name: 'EFFECT.StatusComma', img: 'icons/svg/skull.svg' },
{ rdd: true, id: STATUSES.StatusBleeding, name: 'EFFECT.StatusBleeding', img: 'icons/svg/blood.svg' },
{ rdd: true, id: STATUSES.StatusMalade, name: 'EFFECT.StatusMalade', img: RDD_CONFIG.icons.malade },
{ rdd: true, id: STATUSES.StatusDead, name: 'EFFECT.StatusDead', img: 'icons/svg/skull.svg' },
surEncEffect,
demiReveStatusEffect,
forceWeakStatusEffect,
surEncEffect,
];
]
const statusDemiSurprise = new Set([STATUSES.StatusStunned, STATUSES.StatusProne, STATUSES.StatusRestrained, STATUSES.StatusForceWeak])
const statusSurpriseTotale = new Set([STATUSES.StatusUnconscious, STATUSES.StatusBlind, STATUSES.StatusComma])
@@ -73,7 +75,6 @@ export class StatusEffects extends FormApplication {
CONFIG.RDD.allEffects = rddStatusEffects.concat(CONFIG.statusEffects.filter(it => !rddEffectIds.includes(it.id)))
StatusEffects._setUseStatusEffects(StatusEffects._getUseStatusEffects());
console.log('statusEffects', CONFIG.statusEffects);
}
static isSurprise(effect) {

View File

@@ -68,18 +68,20 @@ export class SystemCompendiums extends FormApplication {
if (pack?.metadata.type == docType) {
return await pack.getDocuments();
}
return [];
return []
}
static async getCompetences(actorType) {
switch (actorType ?? 'personnage') {
case 'personnage':
return await SystemCompendiums.getWorldOrCompendiumItems('competence', 'competences')
.then(list => list.sort((a, b) => a.name.localeCompare(b.name)))
case 'entite':
case 'creature':
return await SystemCompendiums.getWorldOrCompendiumItems('competencecreature', 'competences-creatures')
case 'vehicule': return [];
.then(list => list.sort((a, b) => a.name.localeCompare(b.name)))
}
return []
}
/* -------------------------------------------- */

View File

@@ -9,12 +9,12 @@ export class DialogRepos extends Dialog {
return
}
if (!ReglesOptionnelles.isUsing("chateau-dormant-gardien") || !actor.hasPlayerOwner) {
actor.system.sommeil = {
foundry.utils.mergeObject(actor.system.sommeil, {
"nouveaujour": true,
"insomnie": EffetsDraconiques.isSujetInsomnie(actor),
"moral": "neutre",
"heures": 4
}
})
}
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/sommeil/dialog-repos.hbs", actor);
const dialog = new DialogRepos(html, actor);

View File

@@ -18,6 +18,14 @@ export class Targets {
}
}
static extractActorData(actor) {
return {
id: actor.id,
name: actor.prototypeToken?.name ?? actor.name,
img: actor.prototypeToken?.texture.src ?? actor.img ?? 'icons/svg/mystery-man.svg'
}
}
static buildActorTokenData(tokenId, actor) {
return { id: tokenId, name: actor.name, img: actor.img ?? 'icons/svg/mystery-man.svg' };
}
@@ -41,7 +49,7 @@ export class Targets {
label: "Choisir une seule des cibles",
list: targets.map(it => Targets.extractTokenData(it))
};
DialogSelect.select(selectData, t => onSelectTarget(t.target))
DialogSelect.select(selectData, target => onSelectTarget(targets.find(it => it.id == target.id)))
}
}
}

View File

@@ -1,3 +1,4 @@
import { RollBasicParts } from "../roll/roll-basic-parts.mjs"
const ACTOR_EMBEDDED_DOCTYPES = ['Item', 'ActiveEffect']
/**
@@ -62,14 +63,16 @@ export class ActorImpacts {
addDelta(document, path, value) {
ActorImpacts.$checkDocType(document)
const intValue = Number.parseInt(value)
if (Number.isInteger(intValue) && intValue != 0) {
const delta = [path, intValue]
const existing = this[docType].updates.find(it => it.id == document.id)
if (existing) {
existing.deltas.push(delta)
}
else {
this[docType].updates.push({ id: document.id, updates: [], deltas: [delta] })
if (Number.isInteger(intValue)) {
if (intValue != 0){
const delta = [path, intValue]
const existing = this[docType].updates.find(it => it.id == document.id)
if (existing) {
existing.deltas.push(delta)
}
else {
this[docType].updates.push({ id: document.id, updates: [], deltas: [delta] })
}
}
}
else {
@@ -96,7 +99,9 @@ export class ActorImpacts {
async applyImpacts() {
const actor = this.actorToken.actor
await Promise.all(ACTOR_EMBEDDED_DOCTYPES.map(async docType => await this.$applyDocumentsImpacts(actor, docType)))
for (let docType of ACTOR_EMBEDDED_DOCTYPES) {
await this.$applyDocumentsImpacts(actor, docType)
}
const updates = ActorImpacts.$computeUpdates(this, id => actor)
await actor.update(updates, { render: true })
}
@@ -122,8 +127,8 @@ export class ActorImpacts {
}
}
findCreatedId(docType, origId){
return this[docType].creates.find(it => it.id = origId)?.createdId
findCreatedId(docType, origId) {
return this[docType].creates.find(it => it.id = origId)?.createdId
}
$getEmbeddedDocument(docType, id) {

View File

@@ -173,10 +173,10 @@ export class RdDTimestamp {
}
filtered = DEFINITION_HEURES.filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label).includes(heure));
if (filtered.length > 0) {
filtered.sort(Misc.ascending(h => h.label.length));
filtered.sort(Misc.ascending(h => h.label.length))
return filtered[0]
}
return undefined;
return undefined
}
/**

View File

@@ -30,7 +30,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!Igt8XPaL7NQrGYlq.shsUV8UpU18c0RJK'
- _id: CYpxxf1uTa78NWR9
name: Esquive
@@ -59,7 +63,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!Igt8XPaL7NQrGYlq.CYpxxf1uTa78NWR9'
- _id: lzEdMrKXbOYrWG5S
name: Vigilance
@@ -88,7 +96,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!Igt8XPaL7NQrGYlq.lzEdMrKXbOYrWG5S'
- _id: NWmRryjNFkXcd1v9
name: Piétinement
@@ -116,7 +128,12 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors.items!Igt8XPaL7NQrGYlq.NWmRryjNFkXcd1v9'
effects: []
folder: null
@@ -183,16 +200,16 @@ system:
value: '+4'
label: +dom
derivee: true
vitesse:
type: string
value: 10/40
label: Vitesse
derivee: true
encombrement:
type: number
value: 20
label: Encombrement
derivee: false
vitesse:
type: string
value: 10/40
label: Vitesse
derivee: true
protection:
type: number
value: 4
@@ -295,7 +312,6 @@ prototypeToken:
detectionModes: []
appendNumber: false
prependAdjective: false
hexagonalShape: 0
occludable:
radius: 0
ring:
@@ -307,9 +323,19 @@ prototypeToken:
subject:
scale: 1
texture: null
turnMarker:
mode: 1
animation: null
src: null
disposition: false
movementAction: null
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors!Igt8XPaL7NQrGYlq'

View File

@@ -30,7 +30,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!ppjPZoSKp7j841bp.shsUV8UpU18c0RJK'
- _id: yDHZfK4RmwQW4YaW
name: Discrétion
@@ -59,7 +63,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!ppjPZoSKp7j841bp.yDHZfK4RmwQW4YaW'
- _id: CYpxxf1uTa78NWR9
name: Esquive
@@ -88,7 +96,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!ppjPZoSKp7j841bp.CYpxxf1uTa78NWR9'
- _id: 6DK46pyO0hzEuuUg
name: Morsure
@@ -117,7 +129,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!ppjPZoSKp7j841bp.6DK46pyO0hzEuuUg'
- _id: lzEdMrKXbOYrWG5S
name: Vigilance
@@ -146,7 +162,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!ppjPZoSKp7j841bp.lzEdMrKXbOYrWG5S'
effects: []
folder: null
@@ -213,16 +233,16 @@ system:
value: -2
label: +dom
derivee: true
vitesse:
type: string
value: 14/36
label: Vitesse
derivee: true
encombrement:
type: number
value: 0
label: Encombrement
derivee: false
vitesse:
type: string
value: 14/36
label: Vitesse
derivee: true
protection:
type: number
value: -3
@@ -327,7 +347,6 @@ prototypeToken:
detectionModes: []
appendNumber: false
prependAdjective: false
hexagonalShape: 0
occludable:
radius: 0
ring:
@@ -339,9 +358,19 @@ prototypeToken:
subject:
scale: 1
texture: null
turnMarker:
mode: 1
animation: null
src: null
disposition: false
movementAction: null
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors!ppjPZoSKp7j841bp'

View File

@@ -30,7 +30,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!Q0i8frS62Mn7SW5c.shsUV8UpU18c0RJK'
- _id: yDHZfK4RmwQW4YaW
name: Discrétion
@@ -59,7 +63,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!Q0i8frS62Mn7SW5c.yDHZfK4RmwQW4YaW'
- _id: CYpxxf1uTa78NWR9
name: Esquive
@@ -88,7 +96,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!Q0i8frS62Mn7SW5c.CYpxxf1uTa78NWR9'
- _id: 6DK46pyO0hzEuuUg
name: Morsure
@@ -117,7 +129,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!Q0i8frS62Mn7SW5c.6DK46pyO0hzEuuUg'
- _id: lzEdMrKXbOYrWG5S
name: Vigilance
@@ -146,7 +162,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!Q0i8frS62Mn7SW5c.lzEdMrKXbOYrWG5S'
effects: []
folder: null
@@ -213,16 +233,16 @@ system:
value: '+4'
label: +dom
derivee: true
vitesse:
type: string
value: 10/24
label: Vitesse
derivee: true
encombrement:
type: number
value: 0
label: Encombrement
derivee: false
vitesse:
type: string
value: 10/24
label: Vitesse
derivee: true
protection:
type: number
value: 2
@@ -317,7 +337,6 @@ prototypeToken:
detectionModes: []
appendNumber: false
prependAdjective: false
hexagonalShape: 0
occludable:
radius: 0
ring:
@@ -329,9 +348,19 @@ prototypeToken:
subject:
scale: 1
texture: null
turnMarker:
mode: 1
animation: null
src: null
disposition: false
movementAction: null
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors!Q0i8frS62Mn7SW5c'

View File

@@ -30,7 +30,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!ZLROmHLm6G9pElkk.shsUV8UpU18c0RJK'
- _id: CYpxxf1uTa78NWR9
name: Esquive
@@ -59,7 +63,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!ZLROmHLm6G9pElkk.CYpxxf1uTa78NWR9'
- _id: BjqRrGtHtTzuNpZB
name: Griffes et Crocs
@@ -88,7 +96,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!ZLROmHLm6G9pElkk.BjqRrGtHtTzuNpZB'
- _id: lzEdMrKXbOYrWG5S
name: Vigilance
@@ -117,7 +129,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!ZLROmHLm6G9pElkk.lzEdMrKXbOYrWG5S'
effects: []
folder: null
@@ -184,16 +200,16 @@ system:
value: '+9'
label: +dom
derivee: true
vitesse:
type: string
value: 16/60
label: Vitesse
derivee: true
encombrement:
type: number
value: 0
label: Encombrement
derivee: false
vitesse:
type: string
value: 16/60
label: Vitesse
derivee: true
protection:
type: number
value: 10
@@ -304,7 +320,6 @@ prototypeToken:
detectionModes: []
appendNumber: false
prependAdjective: false
hexagonalShape: 0
occludable:
radius: 0
ring:
@@ -316,9 +331,19 @@ prototypeToken:
subject:
scale: 1
texture: null
turnMarker:
mode: 1
animation: null
src: null
disposition: false
movementAction: null
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors!ZLROmHLm6G9pElkk'

View File

@@ -30,7 +30,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!zMvyRrp10dkfcS43.LWQHz5ymNBzh6ZEr'
- _id: shsUV8UpU18c0RJK
name: Course
@@ -59,7 +63,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!zMvyRrp10dkfcS43.shsUV8UpU18c0RJK'
- _id: CYpxxf1uTa78NWR9
name: Esquive
@@ -88,7 +96,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!zMvyRrp10dkfcS43.CYpxxf1uTa78NWR9'
- _id: lzEdMrKXbOYrWG5S
name: Vigilance
@@ -117,7 +129,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!zMvyRrp10dkfcS43.lzEdMrKXbOYrWG5S'
- _id: iwQo9KoK5tfIN7sw
name: Saut
@@ -145,7 +161,12 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors.items!zMvyRrp10dkfcS43.iwQo9KoK5tfIN7sw'
effects: []
folder: null
@@ -212,16 +233,16 @@ system:
value: '+4'
label: +dom
derivee: true
vitesse:
type: string
value: 14/54
label: Vitesse
derivee: true
encombrement:
type: number
value: 0
label: Encombrement
derivee: false
vitesse:
type: string
value: 14/54
label: Vitesse
derivee: true
protection:
type: number
value: 1
@@ -319,7 +340,6 @@ prototypeToken:
detectionModes: []
appendNumber: false
prependAdjective: false
hexagonalShape: 0
occludable:
radius: 0
ring:
@@ -331,9 +351,19 @@ prototypeToken:
subject:
scale: 1
texture: null
turnMarker:
mode: 1
animation: null
src: null
disposition: false
movementAction: null
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors!zMvyRrp10dkfcS43'

View File

@@ -30,7 +30,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!twCuK1GjVBTUFGXF.shsUV8UpU18c0RJK'
- _id: 4GmpkphbsmQjvVVK
name: Escalade
@@ -59,7 +63,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!twCuK1GjVBTUFGXF.4GmpkphbsmQjvVVK'
- _id: CYpxxf1uTa78NWR9
name: Esquive
@@ -88,7 +96,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!twCuK1GjVBTUFGXF.CYpxxf1uTa78NWR9'
- _id: BjqRrGtHtTzuNpZB
name: Griffes et Crocs
@@ -117,7 +129,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!twCuK1GjVBTUFGXF.BjqRrGtHtTzuNpZB'
- _id: lzEdMrKXbOYrWG5S
name: Vigilance
@@ -146,7 +162,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!twCuK1GjVBTUFGXF.lzEdMrKXbOYrWG5S'
- _id: plIWZXJT0XGKJ5ar
name: Saut
@@ -174,7 +194,12 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors.items!twCuK1GjVBTUFGXF.plIWZXJT0XGKJ5ar'
effects: []
folder: null
@@ -241,16 +266,16 @@ system:
value: '+0'
label: +dom
derivee: true
vitesse:
type: string
value: 12/24
label: Vitesse
derivee: true
encombrement:
type: number
value: 0
label: Encombrement
derivee: false
vitesse:
type: string
value: 12/24
label: Vitesse
derivee: true
protection:
type: number
value: 0
@@ -300,9 +325,8 @@ system:
d&eacute;chirure. Celle-l&agrave; se contente de chercher &agrave; fuir en
cas d&rsquo;agression, ou attaque toutes griffes dehors si elle se sent
accul&eacute;e. Pour la distinguer (visuellement) de la rieuse,
r&eacute;ussir @roll[VUE/Zoologie/-5]. Les caract&eacute;ristiques de
combat indiqu&eacute;es ne s&rsquo;appliquent qu&rsquo;&agrave; la
pointue.</p>
r&eacute;ussir @roll[VUE/Zoologie/-5]. Les caract&eacute;ristiques de combat
indiqu&eacute;es ne s&rsquo;appliquent qu&rsquo;&agrave; la pointue.</p>
race: ''
notesmj: ''
ownership:
@@ -371,7 +395,6 @@ prototypeToken:
detectionModes: []
appendNumber: false
prependAdjective: false
hexagonalShape: 0
occludable:
radius: 0
ring:
@@ -383,9 +406,19 @@ prototypeToken:
subject:
scale: 1
texture: null
turnMarker:
mode: 1
animation: null
src: null
disposition: false
movementAction: null
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors!twCuK1GjVBTUFGXF'

View File

@@ -31,7 +31,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!LqYHIJf9LVGxRT7S.shsUV8UpU18c0RJK'
- _id: CYpxxf1uTa78NWR9
name: Esquive
@@ -60,7 +64,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!LqYHIJf9LVGxRT7S.CYpxxf1uTa78NWR9'
- _id: 6DK46pyO0hzEuuUg
name: Morsure
@@ -89,7 +97,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!LqYHIJf9LVGxRT7S.6DK46pyO0hzEuuUg'
- _id: lzEdMrKXbOYrWG5S
name: Vigilance
@@ -118,7 +130,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!LqYHIJf9LVGxRT7S.lzEdMrKXbOYrWG5S'
- _id: 3MgAaUHeKGBcbyr5
name: Coup de pied
@@ -146,7 +162,12 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors.items!LqYHIJf9LVGxRT7S.3MgAaUHeKGBcbyr5'
effects: []
system:
@@ -211,16 +232,16 @@ system:
value: '+4'
label: +dom
derivee: true
vitesse:
type: string
value: 12/40
label: Vitesse
derivee: true
encombrement:
type: number
value: 18
label: Encombrement
derivee: false
vitesse:
type: string
value: 12/40
label: Vitesse
derivee: true
protection:
type: number
value: 1
@@ -324,7 +345,6 @@ prototypeToken:
detectionModes: []
appendNumber: false
prependAdjective: false
hexagonalShape: 0
occludable:
radius: 0
ring:
@@ -336,10 +356,20 @@ prototypeToken:
subject:
scale: 1
texture: null
turnMarker:
mode: 1
animation: null
src: null
disposition: false
movementAction: null
folder: null
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors!LqYHIJf9LVGxRT7S'

View File

@@ -30,7 +30,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!76I21ASdWYBqsg8I.shsUV8UpU18c0RJK'
- _id: CYpxxf1uTa78NWR9
name: Esquive
@@ -59,7 +63,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!76I21ASdWYBqsg8I.CYpxxf1uTa78NWR9'
- _id: ndNshntOYb1JFNqi
name: Ruade
@@ -88,7 +96,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!76I21ASdWYBqsg8I.ndNshntOYb1JFNqi'
- _id: lzEdMrKXbOYrWG5S
name: Vigilance
@@ -117,7 +129,11 @@ items:
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
_key: '!actors.items!76I21ASdWYBqsg8I.lzEdMrKXbOYrWG5S'
effects: []
folder: null
@@ -184,16 +200,16 @@ system:
value: '+5'
label: +dom
derivee: true
vitesse:
type: string
value: 14/58
label: Vitesse
derivee: true
encombrement:
type: number
value: 22
label: Encombrement
derivee: false
vitesse:
type: string
value: 14/58
label: Vitesse
derivee: true
protection:
type: number
value: 2
@@ -287,7 +303,6 @@ prototypeToken:
detectionModes: []
appendNumber: false
prependAdjective: false
hexagonalShape: 0
occludable:
radius: 0
ring:
@@ -299,9 +314,19 @@ prototypeToken:
subject:
scale: 1
texture: null
turnMarker:
mode: 1
animation: null
src: null
disposition: false
movementAction: null
_stats:
systemId: foundryvtt-reve-de-dragon
systemVersion: 12.0.22
coreVersion: '12.331'
coreVersion: '13.350'
lastModifiedBy: null
compendiumSource: null
duplicateSource: null
exportSource: null
flags: {}
_key: '!actors!76I21ASdWYBqsg8I'

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