Compare commits

...
88 Commits
Author SHA1 Message Date
fabres ded584ccc8 feat(inventaire): tri par quantité, dialogues de gestion, duplication cachée des livres lus
Release Creation / build (release) Successful in 1m45s
- Remplace le tri 'Manuel' par un tri 'Quantité' dans l'inventaire
- Supprime _onDrop / _onSortItem (obsolètes sans tri manuel)
- Nouveau dialogue 'Gérer ses deniers' (ApplicationV2)
- Nouveau dialogue 'Gérer ses potions' (ApplicationV2)
- Boutons herbes/ingrédients/potions/deniers déplacés dans l'onglet Équipement
- Dialogues herbes/ingrédients harmonisés (alterne-list, contrôles +/-)
- Ajout titre 'Livres lus' et en-têtes alignés
- Ajout estCopieLue au schéma livre (template.json)
- creerCopieLue() extrait dans base-actor.js
- Filtre estCopieLue dans prepareInventaire/buildContenuConteneur
2026-07-14 18:56:38 +02:00
fabres ac10de85cf Gestion des livres lus et des herbes 2026-07-14 08:28:44 +02:00
VincentVk b9fec47311 Correction du but des recettes alchimiques 2026-07-14 01:21:52 +02:00
VincentVk 7d5903aa84 Support des tâches à plusieurs
Release Creation / build (release) Successful in 1m50s
2026-07-11 16:12:15 +02:00
VincentVk 66a8eb0e8a Images de la barre de menu droite 2026-07-11 01:16:10 +02:00
VincentVk 6636ebb77c Améliorations des titres des fenêtres de jets 2026-07-10 23:37:42 +02:00
VincentVk 89207df01d Correction d'updates non affichés 2026-07-10 20:34:16 +02:00
VincentVk 000e16f8b7 Amélioration sur les voies de Draconic
- Ne pas proposer les voies de Draconic à -11 pour lire un signe
  draconic ou lancer un sort
- Trier les voies par ordre décroissant pour le sorts à voies multiples
- Les rencontres et les maîtrises dans les TMR peuvent être vaincues
  sans draconic si les voies sont négatives
2026-07-10 19:26:34 +02:00
VincentVk bbbc817e5f Pas de lecture avec Draconic à -11 2026-07-10 18:13:29 +02:00
VincentVk b89dd3845a Visibilité des jets /rdd 2026-07-10 18:07:08 +02:00
VincentVk 6c239b8ed9 Suppression de TMR "Inconnu" pour signes 2026-07-10 16:50:41 +02:00
VincentVk e42e12f56f Publish version 1.1.1
Release Creation / build (release) Successful in 1m1s
2026-06-29 23:11:01 +02:00
VincentVk 32f99e35ef Using nodejs 24 for release actions
Release Creation / build (release) Failing after 1m19s
2026-06-29 01:00:17 +02:00
VincentVk ae42bc4aa4 Using nodejs 24 for release actions 2026-06-29 00:56:07 +02:00
VincentVk 089c0c2243 Correction des couleurs des tooltips d'aide foundry
Release Creation / build (release) Failing after 1m1s
2026-06-28 23:49:56 +02:00
VincentVk e34449631c Optimisation fenêtre de jets
La fenêtre de jet pour les attaques à distance prenait
trop de hauteur sur petit écran.

La difficulté était mal visualisée par les joueurs (et confondue
avec les conditions)

Le d100 de la zone "tricher" était un peu trop gros

Les ajustements sont organisés plus logiquement: difficulté,
conditions, ajustements à cocher
2026-06-20 18:38:48 +02:00
VincentVk f8a20b90ff Génération aléatoire d'archétype 2026-06-20 18:38:48 +02:00
VincentVk 749eb5ee13 upgrade publish action 2026-06-20 18:38:47 +02:00
VincentVk 17cb8a2e06 13.0.45
Release Creation / build (release) Successful in 1m23s
2026-06-16 23:02:39 +02:00
VincentVk 933256da66 Nouvelle correction du manifest
Release Creation / build (release) Has been cancelled
Le manifest versionné, téléchargé dans le système, pointe maintenant
sur le manifest latest.

Le lien manifest foundry est celui du manifest de la version.
2026-06-16 22:59:36 +02:00
VincentVk a58b171fb4 13.0.44 - Le dépôt d'Illisys
Release Creation / build (release) Successful in 1m5s
- le manifest pointe maintenant toujours vers la dernière version
- changement des liens dans le system.json
2026-06-15 21:26:03 +02:00
VincentVk 2eac969261 Update system.json
even if not necessary, it was referencing previous repository
2026-06-14 22:41:04 +02:00
fabres e6612fe024 Make default release as latest 2026-06-14 21:57:55 +02:00
fabres 18b9e4c7a8 Updte gitignore 2026-06-14 21:55:48 +02:00
VincentVk fcaebe6334 Correction des jets impossibles
Release Creation / build (release) Successful in 1m58s
2026-06-12 00:26:54 +02:00
VincentVk c4033707be macro signe draconique
Release Creation / build (release) Successful in 1m48s
2026-06-03 00:56:52 +02:00
VincentVk 8b83369d5a On peut choisir la difficulté de résistance
La difficulté des jets de résistance est libre
2026-06-03 00:46:15 +02:00
VincentVk e9183df59c le Guerrier Sorde n'est pas joueur 2026-06-03 00:46:15 +02:00
VincentVk 45ccac3489 Mineur - rendu monnaies 2026-06-03 00:39:12 +02:00
VincentVk c41db974ff Corrections description aléatoire 2026-06-03 00:39:12 +02:00
VincentVk 875e121a09 Merge pull request '13.0.41 -mode de visibilité des jets' (#808) from feature/v13-corrections into v13
Release Creation / build (release) Successful in 1m0s
Reviewed-on: https, #808
2026-05-29 02:08:11 +02:00
VincentVk 12e0e6397c mode de visibilité des jets 2026-05-29 02:01:30 +02:00
VincentVk 93b74574ad pas de stress/sommeil pour personnage non lié
Release Creation / build (release) Successful in 1m32s
2026-05-29 01:53:35 +02:00
VincentVk 1765cb2ef9 Mode de visibilité des jets 2026-05-29 01:53:35 +02:00
VincentVk 0cbd7a6deb Merge pull request '13.0.39 - La défense d'Illisys' (#806) from feature/v13-corrections into v13
Release Creation / build (release) Successful in 1m1s
Reviewed-on: https, #806
2026-05-10 15:06:35 +02:00
VincentVk aec4364889 Type de jet: Jet de résistance 2026-05-09 23:14:28 +02:00
VincentVk f17996b1c8 Difficultés attaque/défense sur appel à la chance 2026-05-09 22:41:47 +02:00
VincentVk 14a4b34bbd Correction jets de compétence des invocations 2026-05-09 22:41:02 +02:00
VincentVk 1777eced30 Correction des catégories de parades 2026-05-09 21:42:09 +02:00
VincentVk 9bdda32d54 Merge pull request 'Set version changelog 13.0.38' (#805) from feature/v13-corrections into v13
Release Creation / build (release) Successful in 2m29s
Reviewed-on: https, #805
2026-05-05 23:55:45 +02:00
VincentVk 3fe53d7ff0 Set version changelog 13.0.38 2026-05-05 23:55:16 +02:00
VincentVk c839d4633d Merge pull request '## 13.0.37 - L'urgence d'Illisys' (#804) from feature/v13-corrections into v13
Reviewed-on: https, #804
2026-05-05 23:54:19 +02:00
VincentVk 24753bfc29 Appel chance RollDialogV2 2026-05-05 23:51:04 +02:00
VincentVk e7acb0c4f2 Fix v14 Dés dice-so-nice 2026-05-05 21:51:01 +02:00
VincentVk 7535e5f340 Fix v14: /roll dans le tchat 2026-05-05 21:48:24 +02:00
VincentVk d2326e5a25 Fix: liste des actions disponibles
- ajout du haut-rêve
- possibilité de ne lister que les armes équipées
2026-05-05 02:12:48 +02:00
VincentVk e2afc24601 Message en cas d'erreur de migration 2026-05-02 16:46:25 +02:00
VincentVk f220e3a394 Merge pull request 'Version 13.0.37' (#803) from feature/v13-corrections into v13
Release Creation / build (release) Successful in 1m28s
Reviewed-on: https, #803
2026-05-02 16:37:40 +02:00
VincentVk 1d9348b701 Version 13.0.37 2026-05-02 16:36:51 +02:00
VincentVk d96dff988e Merge pull request 'isNewerVersion' (#802) from feature/v13-corrections into v13
Reviewed-on: https, #802
2026-05-02 16:35:21 +02:00
VincentVk 9966a33524 Correction Migration avec Foundry14
Accès à méthode isNewerVersion à travers foundry.utils
2026-05-02 16:32:19 +02:00
VincentVk 7fb0ee1659 await ChatMessage.create
ChatMessage.create est async, il faut donc de préférence
l'appeler avec un await.

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

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

Affichage des contusions. Les blessures sont affichées en
dernier, par gravité décroissante
2026-04-26 22:37:49 +02:00
VincentVk 8b46ea3681 Ajout de tokens de créatures 2026-04-26 22:37:49 +02:00
VincentVk 3ce33eeea3 simplification pre-update checkCompetence 2026-04-26 22:37:48 +02:00
VincentVk 5c4292882f Correction des updates multiples
Utilisation d'un render sur timer pour forcer le réaffichage
2026-04-26 22:37:48 +02:00
VincentVk fb150753e0 Suppression image de fond "players"
Adaptation theme Foundry v13
2026-04-26 22:37:48 +02:00
VincentVk fa54865369 Amélioration des tirages
- option pour ne pas afficher la table source
- les tirages de rencontres sont entre joueur et MJ
2026-04-26 22:37:48 +02:00
VincentVk 200e35b7b7 Filtrage des actions des items des commerces 2026-04-26 22:37:48 +02:00
VincentVk 76fb385c69 Visibilité des tirages dans le compendium
Les tirages de queues, têtes, ... ne concernent plus tout le monde,
mais le joueur et le MJ
2026-04-26 22:37:48 +02:00
VincentVk ef30e76449 Fix: recul contre entité de cauchemar 2026-04-26 22:37:47 +02:00
VincentVk 10aba8bd58 Fix: sortie d'objet de conteneur 2026-04-26 22:37:47 +02:00
giteadmin 0aedff9d4b Merge pull request 'v13.0.34 - La saumuche d'Illysis' (#799) from feature/v13-corrections into v13
Release Creation / build (release) Successful in 2m2s
Reviewed-on: https, #799
2026-04-07 19:23:26 +02:00
VincentVk 6062d0428c Fix: difficulté d'annulation de magie 2026-04-03 22:16:50 +02:00
VincentVk eebca509bd Fix: affichage appel moral sur sorts 2026-04-03 22:16:50 +02:00
VincentVk 9934fe9191 Le pluriel de jeu est jeux 2026-04-03 22:16:50 +02:00
VincentVk e6c4f7990a Correction: qualité des improvisations de cuisine 2026-04-03 22:16:50 +02:00
VincentVk 956fecdd82 Demi-rêve masqué, masquer les rencontres
Pour éviter de trahir l'emplacement du demi-rêve...
2026-04-03 22:16:50 +02:00
giteadmin afcd200913 Merge pull request 'v13.0.33 - L'ébriété d'Illysis' (#798) from feature/v13-corrections into v13
Release Creation / build (release) Successful in 1m31s
Reviewed-on: https, #798
2026-03-26 23:11:26 +01:00
VincentVk f3e7cc38a7 Message de Vaisseau 2026-03-24 20:45:54 +01:00
VincentVk bcc1ec6a37 Pas de perte d'endurance quand éméché 2026-03-24 20:45:54 +01:00
VincentVk 4141eeaa4a Cleanup: gererExperience=>ajoutExperience 2026-03-24 20:45:54 +01:00
VincentVk d80efba092 Corrections relecture IA 2026-03-24 20:45:54 +01:00
304 changed files with 3956 additions and 2479 deletions
+5 -4
View File
@@ -32,13 +32,13 @@ jobs:
env:
version: ${{steps.get_version.outputs.version-without-v}}
url: https://gitea.scriptarium.org/${{gitea.repository}}
manifest: https://gitea.scriptarium.org/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json
manifest: "https://gitea.scriptarium.org/Scriptarium/foundryvtt-reve-de-dragon/releases/download/latest/system.json"
download: https://gitea.scriptarium.org/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/rddsystem.zip
- name: Set up Node.js
uses: actions/setup-node@v2
with:
node-version: "18" # Use the node version your project requires
node-version: "24" # Use the node version your project requires
- name: Install dependencies
run: npm install
@@ -64,12 +64,13 @@ jobs:
api_key: "${{secrets.RDD_PUBLISH_RELEASE}}"
- name: Publish to Foundry server
uses: djlechuck/foundryvtt-publish-package-action@v1
uses: djlechuck/foundryvtt-publish-package-action@v1.1.1
with:
token: ${{ secrets.RDD_PUBLISH_RELEASE_FOUNDRY }}
id: "foundryvtt-reve-de-dragon"
version: ${{github.event.release.tag_name}}
manifest: "https://gitea.scriptarium.org/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json"
manifest: https://gitea.scriptarium.org/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json
notes: "https://gitea.scriptarium.org/Scriptarium/foundryvtt-reve-de-dragon/raw/branch/v13/changelog.md"
compatibility-minimum: "13"
compatibility-verified: "13"
node-version: "24"
+1
View File
@@ -12,3 +12,4 @@ todo.md
/packs/*/CURRENT
/packs/*/LOG
/packs/*/LOCK
.github/
+87 -1
View File
@@ -1 +1,87 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><defs><filter id="shadow-1" height="300%" width="300%" x="-100%" y="-100%"><feFlood flood-color="rgba(201, 201, 201, 1)" result="flood"></feFlood><feComposite in="flood" in2="SourceGraphic" operator="atop" result="composite"></feComposite>0<feOffset dx="230" dy="300" result="offset"></feOffset><feComposite in="SourceGraphic" in2="offset" operator="over"></feComposite></filter></defs><g class="" transform="translate(-100,0)" style=""><path d="m375.483 251.243-109.98 51.138.213 183.381L477.01 266.346l-86.993-21.81zm-12.736 108.626-5.947 14.699-48.604-8.955 5.007-12.832a141.306 141.306 0 0 0 13.51-11.358 167.184 167.184 0 0 0 16.566-17.517 170.478 170.478 0 0 0 12.606-17.958 115.607 115.607 0 0 0 9.514-17.97l14.068 2.51q-9.37 22.334-30.361 44.43-13.296 13.64-20.645 18.636zM121.603 244.334l-84.71 21.763L246.474 486V302.38l-109.946-51.137zm19.147 50.852a28.72 28.72 0 0 1 24.273 6.802 53.052 53.052 0 0 1 11.226 14.188l-13.081 2.676a28.542 28.542 0 0 0-5.388-7.374q-5.185-4.876-11.262-3.853l-.487.095a6.458 6.458 0 0 0-5.162 4.448c-.856 2.378-.238 5.554 1.796 9.371q4.08 7.6 10.81 9.027a23.785 23.785 0 0 0 8.563-.203l1.867-.344 5.791 10.822q-6.398 1.427-8.23 3.282-3.21 3.14.429 9.93a17.042 17.042 0 0 0 6.089 6.696 10.406 10.406 0 0 0 7.385 1.534l.416-.083q4.757-.964 5.079-4.757c.261-2.57-.655-5.744-2.748-9.514l12.38-2.545a49.247 49.247 0 0 1 4.103 11.226 19.956 19.956 0 0 1-.642 9.383 11.702 11.702 0 0 1-3.96 5.411 19.575 19.575 0 0 1-8.027 3.235l-1.19.214a27.971 27.971 0 0 1-17.494-2.7 32.193 32.193 0 0 1-14.128-14.092q-3.627-6.79-2.604-12.19a8.396 8.396 0 0 1 2.521-4.947h-.071q-1.844.31-7.04-2.497a32.11 32.11 0 0 1-12.916-13.593q-5.245-9.764-3.282-18.398 1.962-8.634 13.676-11zM27.19 248.865l108.78-116.309a7.135 7.135 0 0 1 1.427 0h.154q3.14.345 2.842 3.71a19.36 19.36 0 0 1-3.294 8.1 39.376 39.376 0 0 1-9.728 10.405q-3.912 2.938-15.044 9.514-12.796 7.505-19.55 14.77a92.535 92.535 0 0 0-11.513 14.486l32.907 3.758 8.182-12.963-20.967-2.378a36.415 36.415 0 0 1 4.757-3.83q2.379-1.605 8.444-5.125l6.422-3.747a92.975 92.975 0 0 0 12.903-8.776 61.472 61.472 0 0 0 12.51-14.414q6.84-10.846 6.494-17.957c-.19-3.949-2.105-6.434-5.684-7.505l79.798-85.161-102.097 179.576-5.708 10.06zm367.238-71.974q-3.817-5.458-3.758-8.515c0-2.033 1.19-3.199 3.568-3.448h.57a11.892 11.892 0 0 1 6.91 2.247 29.85 29.85 0 0 1 7.837 8.051q3.687 5.28 3.71 8.397c0 2.093-1.188 3.258-3.496 3.567h-.594a11.75 11.75 0 0 1-6.957-2.378 29.79 29.79 0 0 1-7.79-7.885zm-109.41-141.52 83.948 89.634h-1.189c-.38 0-.975 0-1.463.107q-7.825.892-8.324 6.862-.5 5.97 5.03 13.747a53.778 53.778 0 0 0 6.375 7.374 37.901 37.901 0 0 0 10.144 6.897q-2.117 2.89-.702 7.98a37.283 37.283 0 0 0 5.613 11.096 55.122 55.122 0 0 0 15.223 14.806q8.098 5.268 16.066 4.935.81 0 1.618-.13 8.776-.988 9.228-7.873a16.114 16.114 0 0 0-.463-4.853l58.689 62.686-91.572-22.941-6.1-10.703zm98.22 104.927 2.45 2.617c.451.57.903 1.189 1.355 1.784 1.808 2.592 2.723 4.757 2.723 6.529 0 1.771-1.034 2.782-3.127 3.02h-.512a10.346 10.346 0 0 1-6.077-1.95 22.596 22.596 0 0 1-6.184-6.137c-1.974-2.83-2.937-5.102-2.878-6.814.06-1.713 1.118-2.7 3.187-2.937h.524a10.263 10.263 0 0 1 6.005 1.879 19.147 19.147 0 0 1 2.533 2.01zM255.987 26 137.456 231.026l118.532 55.05 118.604-55.05zm-1.19 208.463q-17.529 0-24.58-12.273-7.053-12.273-7.053-34.988 0-22.714 7.052-35.047 7.052-12.332 24.582-12.344 17.53 0 24.582 12.332 7.052 12.333 7.052 35.047 0 22.715-7.052 34.988-7.053 12.273-24.582 12.285zm10.538-71.807q2.497 7.968 2.497 24.546 0 15.817-2.497 24.201-2.498 8.384-10.537 8.325-8.04 0-10.632-8.325-2.593-8.324-2.593-24.2 0-16.579 2.593-24.547t10.632-7.968q8.015-.012 10.513 7.956z" fill="#fff" fill-opacity="1" filter="url(#shadow-1)" transform="translate(128, 128) scale(0.5, 0.5) rotate(-30, 256, 256) skewX(0) skewY(0)"></path></g></svg>
<?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 649.20972 359.75745"
version="1.1"
id="svg6"
sodipodi:docname="_d100.svg"
width="649.20972"
height="359.75745"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
<metadata
id="metadata12">
<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>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="2202"
inkscape:window-height="1379"
id="namedview8"
showgrid="true"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="1.4355469"
inkscape:cx="366.48667"
inkscape:cy="102.06012"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg6">
<inkscape:grid
type="xygrid"
id="grid837"
originx="110.48667"
originy="-153.93988" />
</sodipodi:namedview>
<g
class=""
id="g4"
style="fill:#ffffff"
transform="translate(-94.621782,-91.536548)">
<path
d="m 375.483,251.243 -109.98,51.138 0.213,183.381 211.294,-219.416 -86.993,-21.81 z m -12.736,108.626 -5.947,14.699 -48.604,-8.955 5.007,-12.832 a 141.306,141.306 0 0 0 13.51,-11.358 167.184,167.184 0 0 0 16.566,-17.517 170.478,170.478 0 0 0 12.606,-17.958 115.607,115.607 0 0 0 9.514,-17.97 l 14.068,2.51 q -9.37,22.334 -30.361,44.43 -13.296,13.64 -20.645,18.636 z M 121.603,244.334 36.893,266.097 246.474,486 V 302.38 L 136.528,251.243 Z m 19.147,50.852 a 28.72,28.72 0 0 1 24.273,6.802 53.052,53.052 0 0 1 11.226,14.188 l -13.081,2.676 a 28.542,28.542 0 0 0 -5.388,-7.374 q -5.185,-4.876 -11.262,-3.853 l -0.487,0.095 a 6.458,6.458 0 0 0 -5.162,4.448 c -0.856,2.378 -0.238,5.554 1.796,9.371 q 4.08,7.6 10.81,9.027 a 23.785,23.785 0 0 0 8.563,-0.203 l 1.867,-0.344 5.791,10.822 q -6.398,1.427 -8.23,3.282 -3.21,3.14 0.429,9.93 a 17.042,17.042 0 0 0 6.089,6.696 10.406,10.406 0 0 0 7.385,1.534 l 0.416,-0.083 q 4.757,-0.964 5.079,-4.757 c 0.261,-2.57 -0.655,-5.744 -2.748,-9.514 l 12.38,-2.545 a 49.247,49.247 0 0 1 4.103,11.226 19.956,19.956 0 0 1 -0.642,9.383 11.702,11.702 0 0 1 -3.96,5.411 19.575,19.575 0 0 1 -8.027,3.235 l -1.19,0.214 a 27.971,27.971 0 0 1 -17.494,-2.7 32.193,32.193 0 0 1 -14.128,-14.092 q -3.627,-6.79 -2.604,-12.19 a 8.396,8.396 0 0 1 2.521,-4.947 h -0.071 q -1.844,0.31 -7.04,-2.497 a 32.11,32.11 0 0 1 -12.916,-13.593 q -5.245,-9.764 -3.282,-18.398 1.962,-8.634 13.676,-11 z M 27.19,248.865 135.97,132.556 a 7.135,7.135 0 0 1 1.427,0 h 0.154 q 3.14,0.345 2.842,3.71 a 19.36,19.36 0 0 1 -3.294,8.1 39.376,39.376 0 0 1 -9.728,10.405 q -3.912,2.938 -15.044,9.514 -12.796,7.505 -19.55,14.77 a 92.535,92.535 0 0 0 -11.513,14.486 l 32.907,3.758 8.182,-12.963 -20.967,-2.378 a 36.415,36.415 0 0 1 4.757,-3.83 q 2.379,-1.605 8.444,-5.125 l 6.422,-3.747 a 92.975,92.975 0 0 0 12.903,-8.776 61.472,61.472 0 0 0 12.51,-14.414 q 6.84,-10.846 6.494,-17.957 c -0.19,-3.949 -2.105,-6.434 -5.684,-7.505 l 79.798,-85.161 -102.097,179.576 -5.708,10.06 z m 367.238,-71.974 q -3.817,-5.458 -3.758,-8.515 c 0,-2.033 1.19,-3.199 3.568,-3.448 h 0.57 a 11.892,11.892 0 0 1 6.91,2.247 29.85,29.85 0 0 1 7.837,8.051 q 3.687,5.28 3.71,8.397 c 0,2.093 -1.188,3.258 -3.496,3.567 h -0.594 a 11.75,11.75 0 0 1 -6.957,-2.378 29.79,29.79 0 0 1 -7.79,-7.885 z m -109.41,-141.52 83.948,89.634 h -1.189 c -0.38,0 -0.975,0 -1.463,0.107 q -7.825,0.892 -8.324,6.862 -0.5,5.97 5.03,13.747 a 53.778,53.778 0 0 0 6.375,7.374 37.901,37.901 0 0 0 10.144,6.897 q -2.117,2.89 -0.702,7.98 a 37.283,37.283 0 0 0 5.613,11.096 55.122,55.122 0 0 0 15.223,14.806 q 8.098,5.268 16.066,4.935 0.81,0 1.618,-0.13 8.776,-0.988 9.228,-7.873 a 16.114,16.114 0 0 0 -0.463,-4.853 l 58.689,62.686 -91.572,-22.941 -6.1,-10.703 z m 98.22,104.927 2.45,2.617 c 0.451,0.57 0.903,1.189 1.355,1.784 1.808,2.592 2.723,4.757 2.723,6.529 0,1.771 -1.034,2.782 -3.127,3.02 h -0.512 a 10.346,10.346 0 0 1 -6.077,-1.95 22.596,22.596 0 0 1 -6.184,-6.137 c -1.974,-2.83 -2.937,-5.102 -2.878,-6.814 0.06,-1.713 1.118,-2.7 3.187,-2.937 h 0.524 a 10.263,10.263 0 0 1 6.005,1.879 19.147,19.147 0 0 1 2.533,2.01 z M 255.987,26 137.456,231.026 l 118.532,55.05 118.604,-55.05 z m -1.19,208.463 q -17.529,0 -24.58,-12.273 -7.053,-12.273 -7.053,-34.988 0,-22.714 7.052,-35.047 7.052,-12.332 24.582,-12.344 17.53,0 24.582,12.332 7.052,12.333 7.052,35.047 0,22.715 -7.052,34.988 -7.053,12.273 -24.582,12.285 z m 10.538,-71.807 q 2.497,7.968 2.497,24.546 0,15.817 -2.497,24.201 -2.498,8.384 -10.537,8.325 -8.04,0 -10.632,-8.325 -2.593,-8.324 -2.593,-24.2 0,-16.579 2.593,-24.547 2.593,-7.968 10.632,-7.968 8.015,-0.012 10.513,7.956 z"
fill="#ffffff"
fill-opacity="1"
transform="matrix(0.69282032,-0.4,0.4,0.69282032,-23.762003,181.038)"
id="path2"
style="fill:#ffffff" />
</g>
<g
class=""
id="g4-4"
style="fill:#ffffff"
transform="rotate(12.267903,709.7839,1245.6727)">
<path
d="m 375.483,251.243 -109.98,51.138 0.213,183.381 211.294,-219.416 -86.993,-21.81 z m -12.736,108.626 -5.947,14.699 -48.604,-8.955 5.007,-12.832 a 141.306,141.306 0 0 0 13.51,-11.358 167.184,167.184 0 0 0 16.566,-17.517 170.478,170.478 0 0 0 12.606,-17.958 115.607,115.607 0 0 0 9.514,-17.97 l 14.068,2.51 q -9.37,22.334 -30.361,44.43 -13.296,13.64 -20.645,18.636 z M 121.603,244.334 36.893,266.097 246.474,486 V 302.38 L 136.528,251.243 Z m 19.147,50.852 a 28.72,28.72 0 0 1 24.273,6.802 53.052,53.052 0 0 1 11.226,14.188 l -13.081,2.676 a 28.542,28.542 0 0 0 -5.388,-7.374 q -5.185,-4.876 -11.262,-3.853 l -0.487,0.095 a 6.458,6.458 0 0 0 -5.162,4.448 c -0.856,2.378 -0.238,5.554 1.796,9.371 q 4.08,7.6 10.81,9.027 a 23.785,23.785 0 0 0 8.563,-0.203 l 1.867,-0.344 5.791,10.822 q -6.398,1.427 -8.23,3.282 -3.21,3.14 0.429,9.93 a 17.042,17.042 0 0 0 6.089,6.696 10.406,10.406 0 0 0 7.385,1.534 l 0.416,-0.083 q 4.757,-0.964 5.079,-4.757 c 0.261,-2.57 -0.655,-5.744 -2.748,-9.514 l 12.38,-2.545 a 49.247,49.247 0 0 1 4.103,11.226 19.956,19.956 0 0 1 -0.642,9.383 11.702,11.702 0 0 1 -3.96,5.411 19.575,19.575 0 0 1 -8.027,3.235 l -1.19,0.214 a 27.971,27.971 0 0 1 -17.494,-2.7 32.193,32.193 0 0 1 -14.128,-14.092 q -3.627,-6.79 -2.604,-12.19 a 8.396,8.396 0 0 1 2.521,-4.947 h -0.071 q -1.844,0.31 -7.04,-2.497 a 32.11,32.11 0 0 1 -12.916,-13.593 q -5.245,-9.764 -3.282,-18.398 1.962,-8.634 13.676,-11 z M 27.19,248.865 135.97,132.556 a 7.135,7.135 0 0 1 1.427,0 h 0.154 q 3.14,0.345 2.842,3.71 a 19.36,19.36 0 0 1 -3.294,8.1 39.376,39.376 0 0 1 -9.728,10.405 q -3.912,2.938 -15.044,9.514 -12.796,7.505 -19.55,14.77 a 92.535,92.535 0 0 0 -11.513,14.486 l 32.907,3.758 8.182,-12.963 -20.967,-2.378 a 36.415,36.415 0 0 1 4.757,-3.83 q 2.379,-1.605 8.444,-5.125 l 6.422,-3.747 a 92.975,92.975 0 0 0 12.903,-8.776 61.472,61.472 0 0 0 12.51,-14.414 q 6.84,-10.846 6.494,-17.957 c -0.19,-3.949 -2.105,-6.434 -5.684,-7.505 l 79.798,-85.161 -102.097,179.576 -5.708,10.06 z m 367.238,-71.974 q -3.817,-5.458 -3.758,-8.515 c 0,-2.033 1.19,-3.199 3.568,-3.448 h 0.57 a 11.892,11.892 0 0 1 6.91,2.247 29.85,29.85 0 0 1 7.837,8.051 q 3.687,5.28 3.71,8.397 c 0,2.093 -1.188,3.258 -3.496,3.567 h -0.594 a 11.75,11.75 0 0 1 -6.957,-2.378 29.79,29.79 0 0 1 -7.79,-7.885 z m -109.41,-141.52 83.948,89.634 h -1.189 c -0.38,0 -0.975,0 -1.463,0.107 q -7.825,0.892 -8.324,6.862 -0.5,5.97 5.03,13.747 a 53.778,53.778 0 0 0 6.375,7.374 37.901,37.901 0 0 0 10.144,6.897 q -2.117,2.89 -0.702,7.98 a 37.283,37.283 0 0 0 5.613,11.096 55.122,55.122 0 0 0 15.223,14.806 q 8.098,5.268 16.066,4.935 0.81,0 1.618,-0.13 8.776,-0.988 9.228,-7.873 a 16.114,16.114 0 0 0 -0.463,-4.853 l 58.689,62.686 -91.572,-22.941 -6.1,-10.703 z m 98.22,104.927 2.45,2.617 c 0.451,0.57 0.903,1.189 1.355,1.784 1.808,2.592 2.723,4.757 2.723,6.529 0,1.771 -1.034,2.782 -3.127,3.02 h -0.512 a 10.346,10.346 0 0 1 -6.077,-1.95 22.596,22.596 0 0 1 -6.184,-6.137 c -1.974,-2.83 -2.937,-5.102 -2.878,-6.814 0.06,-1.713 1.118,-2.7 3.187,-2.937 h 0.524 a 10.263,10.263 0 0 1 6.005,1.879 19.147,19.147 0 0 1 2.533,2.01 z M 255.987,26 137.456,231.026 l 118.532,55.05 118.604,-55.05 z m -1.19,208.463 q -17.529,0 -24.58,-12.273 -7.053,-12.273 -7.053,-34.988 0,-22.714 7.052,-35.047 7.052,-12.332 24.582,-12.344 17.53,0 24.582,12.332 7.052,12.333 7.052,35.047 0,22.715 -7.052,34.988 -7.053,12.273 -24.582,12.285 z m 10.538,-71.807 q 2.497,7.968 2.497,24.546 0,15.817 -2.497,24.201 -2.498,8.384 -10.537,8.325 -8.04,0 -10.632,-8.325 -2.593,-8.324 -2.593,-24.2 0,-16.579 2.593,-24.547 2.593,-7.968 10.632,-7.968 8.015,-0.012 10.513,7.956 z"
fill="#ffffff"
fill-opacity="1"
transform="matrix(0.69282032,-0.4,0.4,0.69282032,-23.762003,181.038)"
id="path2-6"
style="fill:#ffffff" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 6.7 KiB

-449
View File
@@ -1,449 +0,0 @@
<?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">
<g>
<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" 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>

Before

Width:  |  Height:  |  Size: 28 KiB

+80
View File
@@ -0,0 +1,80 @@
<?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 512 512"
style="height: 256px; width: 256px;"
version="1.1"
id="svg6"
sodipodi:docname="icon_sidebar_tables.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
<metadata
id="metadata12">
<rdf:RDF>
<cc:Work
rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
</cc:Work>
</rdf:RDF>
</metadata>
<defs
id="defs10" />
<sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1956"
inkscape:window-height="1125"
id="namedview8"
showgrid="false"
inkscape:zoom="0.71777344"
inkscape:cx="403.50636"
inkscape:cy="-55.697677"
inkscape:window-x="0"
inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg6" />
<g
id="g838"
transform="matrix(0.52656879,-0.75618342,0.76711498,0.53418097,-33.85852,326.4134)"
style="fill:#ffffff;stroke:none">
<g
class=""
id="g4-5"
style="fill:#ffffff;stroke:none"
transform="matrix(0.76010883,0,0,0.77788021,-69.057255,5.6807692)">
<path
d="m 375.483,251.243 -109.98,51.138 0.213,183.381 211.294,-219.416 -86.993,-21.81 z m -12.736,108.626 -5.947,14.699 -48.604,-8.955 5.007,-12.832 a 141.306,141.306 0 0 0 13.51,-11.358 167.184,167.184 0 0 0 16.566,-17.517 170.478,170.478 0 0 0 12.606,-17.958 115.607,115.607 0 0 0 9.514,-17.97 l 14.068,2.51 q -9.37,22.334 -30.361,44.43 -13.296,13.64 -20.645,18.636 z M 121.603,244.334 36.893,266.097 246.474,486 V 302.38 L 136.528,251.243 Z m 19.147,50.852 a 28.72,28.72 0 0 1 24.273,6.802 53.052,53.052 0 0 1 11.226,14.188 l -13.081,2.676 a 28.542,28.542 0 0 0 -5.388,-7.374 q -5.185,-4.876 -11.262,-3.853 l -0.487,0.095 a 6.458,6.458 0 0 0 -5.162,4.448 c -0.856,2.378 -0.238,5.554 1.796,9.371 q 4.08,7.6 10.81,9.027 a 23.785,23.785 0 0 0 8.563,-0.203 l 1.867,-0.344 5.791,10.822 q -6.398,1.427 -8.23,3.282 -3.21,3.14 0.429,9.93 a 17.042,17.042 0 0 0 6.089,6.696 10.406,10.406 0 0 0 7.385,1.534 l 0.416,-0.083 q 4.757,-0.964 5.079,-4.757 c 0.261,-2.57 -0.655,-5.744 -2.748,-9.514 l 12.38,-2.545 a 49.247,49.247 0 0 1 4.103,11.226 19.956,19.956 0 0 1 -0.642,9.383 11.702,11.702 0 0 1 -3.96,5.411 19.575,19.575 0 0 1 -8.027,3.235 l -1.19,0.214 a 27.971,27.971 0 0 1 -17.494,-2.7 32.193,32.193 0 0 1 -14.128,-14.092 q -3.627,-6.79 -2.604,-12.19 a 8.396,8.396 0 0 1 2.521,-4.947 h -0.071 q -1.844,0.31 -7.04,-2.497 a 32.11,32.11 0 0 1 -12.916,-13.593 q -5.245,-9.764 -3.282,-18.398 1.962,-8.634 13.676,-11 z M 27.19,248.865 135.97,132.556 a 7.135,7.135 0 0 1 1.427,0 h 0.154 q 3.14,0.345 2.842,3.71 a 19.36,19.36 0 0 1 -3.294,8.1 39.376,39.376 0 0 1 -9.728,10.405 q -3.912,2.938 -15.044,9.514 -12.796,7.505 -19.55,14.77 a 92.535,92.535 0 0 0 -11.513,14.486 l 32.907,3.758 8.182,-12.963 -20.967,-2.378 a 36.415,36.415 0 0 1 4.757,-3.83 q 2.379,-1.605 8.444,-5.125 l 6.422,-3.747 a 92.975,92.975 0 0 0 12.903,-8.776 61.472,61.472 0 0 0 12.51,-14.414 q 6.84,-10.846 6.494,-17.957 c -0.19,-3.949 -2.105,-6.434 -5.684,-7.505 l 79.798,-85.161 -102.097,179.576 -5.708,10.06 z m 367.238,-71.974 q -3.817,-5.458 -3.758,-8.515 c 0,-2.033 1.19,-3.199 3.568,-3.448 h 0.57 a 11.892,11.892 0 0 1 6.91,2.247 29.85,29.85 0 0 1 7.837,8.051 q 3.687,5.28 3.71,8.397 c 0,2.093 -1.188,3.258 -3.496,3.567 h -0.594 a 11.75,11.75 0 0 1 -6.957,-2.378 29.79,29.79 0 0 1 -7.79,-7.885 z m -109.41,-141.52 83.948,89.634 h -1.189 c -0.38,0 -0.975,0 -1.463,0.107 q -7.825,0.892 -8.324,6.862 -0.5,5.97 5.03,13.747 a 53.778,53.778 0 0 0 6.375,7.374 37.901,37.901 0 0 0 10.144,6.897 q -2.117,2.89 -0.702,7.98 a 37.283,37.283 0 0 0 5.613,11.096 55.122,55.122 0 0 0 15.223,14.806 q 8.098,5.268 16.066,4.935 0.81,0 1.618,-0.13 8.776,-0.988 9.228,-7.873 a 16.114,16.114 0 0 0 -0.463,-4.853 l 58.689,62.686 -91.572,-22.941 -6.1,-10.703 z m 98.22,104.927 2.45,2.617 c 0.451,0.57 0.903,1.189 1.355,1.784 1.808,2.592 2.723,4.757 2.723,6.529 0,1.771 -1.034,2.782 -3.127,3.02 h -0.512 a 10.346,10.346 0 0 1 -6.077,-1.95 22.596,22.596 0 0 1 -6.184,-6.137 c -1.974,-2.83 -2.937,-5.102 -2.878,-6.814 0.06,-1.713 1.118,-2.7 3.187,-2.937 h 0.524 a 10.263,10.263 0 0 1 6.005,1.879 19.147,19.147 0 0 1 2.533,2.01 z M 255.987,26 137.456,231.026 l 118.532,55.05 118.604,-55.05 z m -1.19,208.463 q -17.529,0 -24.58,-12.273 -7.053,-12.273 -7.053,-34.988 0,-22.714 7.052,-35.047 7.052,-12.332 24.582,-12.344 17.53,0 24.582,12.332 7.052,12.333 7.052,35.047 0,22.715 -7.052,34.988 -7.053,12.273 -24.582,12.285 z m 10.538,-71.807 q 2.497,7.968 2.497,24.546 0,15.817 -2.497,24.201 -2.498,8.384 -10.537,8.325 -8.04,0 -10.632,-8.325 -2.593,-8.324 -2.593,-24.2 0,-16.579 2.593,-24.547 2.593,-7.968 10.632,-7.968 8.015,-0.012 10.513,7.956 z"
fill="#ffffff"
fill-opacity="1"
transform="matrix(0.69282032,-0.4,0.4,0.69282032,-23.762003,181.038)"
id="path2-65"
style="fill:#ffffff;stroke:none" />
</g>
<g
class=""
id="g4-4"
style="fill:#ffffff;stroke:none"
transform="matrix(0.74275157,0.16528633,-0.16151022,0.76011713,216.37438,-18.305353)">
<path
d="m 375.483,251.243 -109.98,51.138 0.213,183.381 211.294,-219.416 -86.993,-21.81 z m -12.736,108.626 -5.947,14.699 -48.604,-8.955 5.007,-12.832 a 141.306,141.306 0 0 0 13.51,-11.358 167.184,167.184 0 0 0 16.566,-17.517 170.478,170.478 0 0 0 12.606,-17.958 115.607,115.607 0 0 0 9.514,-17.97 l 14.068,2.51 q -9.37,22.334 -30.361,44.43 -13.296,13.64 -20.645,18.636 z M 121.603,244.334 36.893,266.097 246.474,486 V 302.38 L 136.528,251.243 Z m 19.147,50.852 a 28.72,28.72 0 0 1 24.273,6.802 53.052,53.052 0 0 1 11.226,14.188 l -13.081,2.676 a 28.542,28.542 0 0 0 -5.388,-7.374 q -5.185,-4.876 -11.262,-3.853 l -0.487,0.095 a 6.458,6.458 0 0 0 -5.162,4.448 c -0.856,2.378 -0.238,5.554 1.796,9.371 q 4.08,7.6 10.81,9.027 a 23.785,23.785 0 0 0 8.563,-0.203 l 1.867,-0.344 5.791,10.822 q -6.398,1.427 -8.23,3.282 -3.21,3.14 0.429,9.93 a 17.042,17.042 0 0 0 6.089,6.696 10.406,10.406 0 0 0 7.385,1.534 l 0.416,-0.083 q 4.757,-0.964 5.079,-4.757 c 0.261,-2.57 -0.655,-5.744 -2.748,-9.514 l 12.38,-2.545 a 49.247,49.247 0 0 1 4.103,11.226 19.956,19.956 0 0 1 -0.642,9.383 11.702,11.702 0 0 1 -3.96,5.411 19.575,19.575 0 0 1 -8.027,3.235 l -1.19,0.214 a 27.971,27.971 0 0 1 -17.494,-2.7 32.193,32.193 0 0 1 -14.128,-14.092 q -3.627,-6.79 -2.604,-12.19 a 8.396,8.396 0 0 1 2.521,-4.947 h -0.071 q -1.844,0.31 -7.04,-2.497 a 32.11,32.11 0 0 1 -12.916,-13.593 q -5.245,-9.764 -3.282,-18.398 1.962,-8.634 13.676,-11 z M 27.19,248.865 135.97,132.556 a 7.135,7.135 0 0 1 1.427,0 h 0.154 q 3.14,0.345 2.842,3.71 a 19.36,19.36 0 0 1 -3.294,8.1 39.376,39.376 0 0 1 -9.728,10.405 q -3.912,2.938 -15.044,9.514 -12.796,7.505 -19.55,14.77 a 92.535,92.535 0 0 0 -11.513,14.486 l 32.907,3.758 8.182,-12.963 -20.967,-2.378 a 36.415,36.415 0 0 1 4.757,-3.83 q 2.379,-1.605 8.444,-5.125 l 6.422,-3.747 a 92.975,92.975 0 0 0 12.903,-8.776 61.472,61.472 0 0 0 12.51,-14.414 q 6.84,-10.846 6.494,-17.957 c -0.19,-3.949 -2.105,-6.434 -5.684,-7.505 l 79.798,-85.161 -102.097,179.576 -5.708,10.06 z m 367.238,-71.974 q -3.817,-5.458 -3.758,-8.515 c 0,-2.033 1.19,-3.199 3.568,-3.448 h 0.57 a 11.892,11.892 0 0 1 6.91,2.247 29.85,29.85 0 0 1 7.837,8.051 q 3.687,5.28 3.71,8.397 c 0,2.093 -1.188,3.258 -3.496,3.567 h -0.594 a 11.75,11.75 0 0 1 -6.957,-2.378 29.79,29.79 0 0 1 -7.79,-7.885 z m -109.41,-141.52 83.948,89.634 h -1.189 c -0.38,0 -0.975,0 -1.463,0.107 q -7.825,0.892 -8.324,6.862 -0.5,5.97 5.03,13.747 a 53.778,53.778 0 0 0 6.375,7.374 37.901,37.901 0 0 0 10.144,6.897 q -2.117,2.89 -0.702,7.98 a 37.283,37.283 0 0 0 5.613,11.096 55.122,55.122 0 0 0 15.223,14.806 q 8.098,5.268 16.066,4.935 0.81,0 1.618,-0.13 8.776,-0.988 9.228,-7.873 a 16.114,16.114 0 0 0 -0.463,-4.853 l 58.689,62.686 -91.572,-22.941 -6.1,-10.703 z m 98.22,104.927 2.45,2.617 c 0.451,0.57 0.903,1.189 1.355,1.784 1.808,2.592 2.723,4.757 2.723,6.529 0,1.771 -1.034,2.782 -3.127,3.02 h -0.512 a 10.346,10.346 0 0 1 -6.077,-1.95 22.596,22.596 0 0 1 -6.184,-6.137 c -1.974,-2.83 -2.937,-5.102 -2.878,-6.814 0.06,-1.713 1.118,-2.7 3.187,-2.937 h 0.524 a 10.263,10.263 0 0 1 6.005,1.879 19.147,19.147 0 0 1 2.533,2.01 z M 255.987,26 137.456,231.026 l 118.532,55.05 118.604,-55.05 z m -1.19,208.463 q -17.529,0 -24.58,-12.273 -7.053,-12.273 -7.053,-34.988 0,-22.714 7.052,-35.047 7.052,-12.332 24.582,-12.344 17.53,0 24.582,12.332 7.052,12.333 7.052,35.047 0,22.715 -7.052,34.988 -7.053,12.273 -24.582,12.285 z m 10.538,-71.807 q 2.497,7.968 2.497,24.546 0,15.817 -2.497,24.201 -2.498,8.384 -10.537,8.325 -8.04,0 -10.632,-8.325 -2.593,-8.324 -2.593,-24.2 0,-16.579 2.593,-24.547 2.593,-7.968 10.632,-7.968 8.015,-0.012 10.513,7.956 z"
fill="#ffffff"
fill-opacity="1"
transform="matrix(0.69282032,-0.4,0.4,0.69282032,-23.762003,181.038)"
id="path2-6"
style="fill:#ffffff;stroke:none" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 9.3 KiB

+123
View File
@@ -1,5 +1,128 @@
# 13.0
## 13.0.49 - La pharmacopée d'Illisys
- Le but des recettes alchimiques est affiché et éditable
## 13.0.48 - Les vagabondages d'Illisys
- Gestion des tâches à plusieurs
- Les tâches du monde peuvent être configurées pour être effectuées à plusieurs
- Une tâche à plusieurs ajoutée à un personnage permet au personnage de contribuer à la tâche commune
- suppression du type de TMR "Inconnu" des feuilles de création de signes draconiques (ce type sert uniquement pour le cas où une case saisie à la main est incorrecte)
- les jets de dés /rdd utilisent le mode de visibilité sélectionné
- Voies de Draconic
- Ne pas proposer les voies de Draconic à -11 pour lire un signe draconic ou lancer un sort
- Trier les voies par ordre décroissant pour le sorts à voies multiples
- Les rencontres et les maîtrises dans les TMR peuvent être vaincues sans
draconic si les voies sont négatives
- correction d'updates non affichés
- Améliorations des titres des fenêtres de jets
## 13.0.47 - Les goûts et les couleurs d'Illisys
- Correction des couleurs des tooltips d'aide foundry
## 13.0.46 - L'archétype d'Illisys
- ajout d'une génération d'archétype aléatoire
- respecte les niveaux d'archétype déjà alloués
- l'archétype alloué est supérieur au niveau actuel (si c'est possible)
- les compétences supérieures à 0 ont plus de chances d'avoir les niveaux d'archétype élevés
- si tous les niveaux d'archétype supérieurs à une compétences sont déjà alloué,
l'archétype est au niveau actuel de la compétence
- Amélioration de l'affichage de la fenêtre de jets:
- La difficultée est déplacée dans la colonne des ajustements
- les ajustements sont mieux alignés
- les ajustements sont mieux ordonnés
- Les indications d'ajustements de tir prennent moins de place
- l'icône d100 est redessinée pour être mieux centrée
## 13.0.45 - L'endépôté d'Illisys
- nouvelle correction du manifest
## 13.0.44 - Le dépôt d'Illisys
- le manifest pointe maintenant toujours vers la dernière version
- changement des liens dans le system.json
## 13.0.43 - L'urgence d'Illisys
- correction urgente des jets
## 13.0.42 - La rebellion d'Illisys
- on peut choisir la difficulté des jets de résistances
- la macro signe draconique fonctionne de nouveau (ajout et suppression)
- le Guerrier Sorde n'est pas joueur et ne cuisine pas (pas de message si compétence Jeu / Cuisine manquent)
- Corrections V14
- Les descriptions aléatoires fonctionnent de nouveau
## 13.0.41 - Le miroir d'Illisys
- les mode de visibilité des jets sont bien pris en compte
## 13.0.40 - Le miroir d'Illisys
- pas de stress ou de sommeil pour les personnage non liés
## 13.0.39 - La défense d'Illisys
- mise à jour de version foundry-cli
- correction des catégories de parades des compendiums
- des ne pouvaient pas parer (exemple: le bouclier du guerrier sorde)
- les difficultés des jets d'attaque/défense après appel à la chance sont conservées
- L'absence des compétences cuisine/jeu ne bloque plus l'accès à la fenêtre de jets (cas des invocations)
## 13.0.38 - L'urgence d'Illisys
- Corrections v14
- on peut utiliser les commandes foundry dans le tchat (par exemple, /roll 1d6)
- les dés customisés Dice-So-Nice (heure, rencontres, dé draconique) fonctionnent
- Le Haut-rêve est de nouveau proposé dans les options d'initiative
- Nouvelle règle optionnelle: choisir si seules les armes équipées sont proposées en combat
- L'appel à la chance utilise la nouvelle fenêtre de jet de dés
## 13.0.37 - Le bonheur des zyglutes d'Illisys
- Corrections v14
- correction du problème liè à Foundry 14 qui peut empêcher d'utiliser les fenêtres de jets à cause de migrations mal effectuées
- Les bon moments sont affichés en tooltip sur le moral
- Les modifications de coeurs fonctionnent de nouveau
- Le refoulement est remis à zéro après avoir refoulé et reçu un souffle
## 13.0.36 - Les rêveries d'Illisys
- Corrections v14
- les attaques à distance n'empèchent plus la fenêtre d'attaque de s'ouvrir
- les commandes (/help, ...) fonctionnent en v14
- Les feuilles d'acteurs ne s'ouvrent plus lors d'un changement (par exemple en cas d'encaissement)
- Les jeux sont correctement affichés
- Ajout d'une gravité de blessure sur les encaissement d'entités
- Amélioration de champs numériques: ajout de min et max quand c'est utile
- correction pour cuisiner depuis l'équipement
- les boutons dans les listes d'équipement sont mieux affichés sans retour à la ligne
## 13.0.35 - Les travaux d'Illisys
- Correction du recul contre une entité de cauchemar (qui utilise le rêve comme force)
- Correction erreur lors de la suppression d'un objet d'un conteneur
- Meilleure gestion des messages publics/GM, en particulier pour les tirage dans les compendiums
- Filtrage des boutons pour les acteurs non personnages (pour éviter de faire manger l'auberge...)
## 13.0.34 - La saumuche d'Illysis
- la qualité des "improvisations du moment" se base sur le niveau du cuisinier
- l'appel au moral n'est pas affiché à l'ouverture d'une fenêtre de jets de sorts (ou de tâche intellectuelle)
- la difficulté variable de l'annulation de magie est bien prise en compte
- correction erreur lors de la suppression d'un objet d'un conteneur
## 13.0.33 - L'ébriété d'Illysis
- le stade éméché ne cause plus de perte d'endurance
## 13.0.32 - Le surpoids d'Illysis
- Le malus d'encombrement sur jet d'Agilité avec Natation ou Acrobatie peuvent être changés, et sont correctement arrondis
+162 -37
View File
@@ -514,6 +514,13 @@ body {
align-items: anchor-center;
margin: 0 0.2rem;
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-section label,
.system-foundryvtt-reve-de-dragon .roll-dialog roll-section div label {
text-align: left;
min-width: 55%;
display: flex;
flex-direction: row;
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-resume {
display: flex;
flex-direction: row;
@@ -670,10 +677,14 @@ body {
padding: 0;
filter: invert(0.8);
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="tricher"] img {
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="tricher"] label {
display: flex;
flex-direction: row;
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="tricher"] label img {
/* image de d100 */
max-width: 2.5rem;
max-height: 2.5rem;
max-width: 2rem;
max-height: 2rem;
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-buttons {
display: flex;
@@ -1120,49 +1131,56 @@ body {
text-align: left;
}
.system-foundryvtt-reve-de-dragon .equipement-nom {
flex-grow: 3;
flex-grow: 4;
flex-shrink: 2;
margin: 0;
justify-content: center;
text-align: left;
display: ruby;
}
.system-foundryvtt-reve-de-dragon .equipement-valeur {
margin: 0;
flex-grow: 1.5;
flex-grow: 1;
flex-shrink: 1;
text-align: center;
}
.system-foundryvtt-reve-de-dragon .equipement-detail {
margin: 0;
flex-grow: 1;
align-items: center;
justify-content: center;
text-align: center;
}
.system-foundryvtt-reve-de-dragon span.equipement-detail-buttons {
margin: 0;
flex-grow: 1.5;
flex-shrink: 1;
align-items: center;
justify-content: center;
text-align: center;
display: flex;
flex-direction: row;
min-width: max-content;
}
.system-foundryvtt-reve-de-dragon .equipement-button {
margin: 0;
flex-grow: 0.5;
align-items: center;
justify-content: center;
text-align: center;
.system-foundryvtt-reve-de-dragon .conteneur-sature {
color: #c00 !important;
font-weight: bold;
}
.system-foundryvtt-reve-de-dragon :is(.item-actions-controls, .equipement-actions) {
margin: 0;
flex-grow: 1.2;
align-items: end;
justify-content: flex-end;
text-align: right;
.system-foundryvtt-reve-de-dragon .conteneur-capacity-bar {
width: 5rem;
height: 0.4rem;
background: rgba(0, 0, 0, 0.1);
border-radius: 0.2rem;
overflow: hidden;
margin: 0 0.3rem;
}
.system-foundryvtt-reve-de-dragon .liste-equipement :is(.equipement-actions, .item-actions-controls) {
flex-grow: 2;
.system-foundryvtt-reve-de-dragon .conteneur-capacity-fill {
height: 100%;
background: #4a90d9;
border-radius: 0.2rem;
transition: width 0.3s;
}
.system-foundryvtt-reve-de-dragon .conteneur-parent-badge {
font-size: 0.7rem;
color: #666;
margin-left: 0.3rem;
}
.system-foundryvtt-reve-de-dragon .conteneur-parent-badge::before {
content: "(";
}
.system-foundryvtt-reve-de-dragon .conteneur-parent-badge::after {
content: ")";
}
.system-foundryvtt-reve-de-dragon .blessure-control {
flex-grow: 1;
@@ -1229,6 +1247,96 @@ body {
vertical-align: baseline;
padding: 0.1rem;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table {
width: 100%;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table th,
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table td {
padding: 0.2rem 0.3rem !important;
vertical-align: middle !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table th {
color: var(--color-text-light-heading, #f0f0f0) !important;
font-weight: bold !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table th:first-child,
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table td:first-child {
width: 36px !important;
text-align: center !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table th:nth-child(2),
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table td:nth-child(2) {
width: auto !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table th:nth-child(3),
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table td:nth-child(3) {
width: 3rem !important;
text-align: center !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table th:nth-child(4),
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table td:nth-child(4) {
width: 6rem !important;
text-align: center !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table th:nth-child(5),
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table td:nth-child(5) {
width: 5rem !important;
text-align: center !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table th:nth-child(7),
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table td:nth-child(7) {
width: 2.5rem !important;
text-align: center !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table select {
max-width: 12rem !important;
min-width: 8rem !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-herbes table img {
width: 30px !important;
height: 30px !important;
object-fit: cover !important;
border: none !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-ingredients table {
width: 100%;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-ingredients table td {
padding: 0.2rem 0.3rem !important;
vertical-align: middle !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-ingredients table td:first-child {
width: 36px !important;
text-align: center !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-ingredients table td:nth-child(2) {
width: auto !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-ingredients table td:nth-child(3) {
width: 3rem !important;
text-align: center !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-ingredients table td:nth-child(4) {
width: 6rem !important;
text-align: center !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-ingredients table td:nth-child(5) {
width: auto !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-ingredients table td:nth-child(6) {
width: 2.5rem !important;
text-align: center !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-ingredients table select {
max-width: 12rem !important;
min-width: 8rem !important;
}
.system-foundryvtt-reve-de-dragon .dialog-gerer-ingredients table img {
width: 30px !important;
height: 30px !important;
object-fit: cover !important;
border: none !important;
}
.system-foundryvtt-reve-de-dragon .dice-img {
border-width: 0;
max-width: 1.5rem;
@@ -1526,9 +1634,20 @@ body {
.system-foundryvtt-reve-de-dragon .competence-list .item-controls.hidden-controls {
display: none !important;
}
.system-foundryvtt-reve-de-dragon .competence-header .item-actions-controls {
flex-shrink: 2;
flex-grow: 2;
}
.system-foundryvtt-reve-de-dragon .item-actions-controls,
.system-foundryvtt-reve-de-dragon .item-controls {
vertical-align: super;
margin: 0;
flex-grow: 1;
flex-shrink: 1;
align-items: end;
text-align: right;
min-width: max-content;
flex-basis: fit-content;
vertical-align: baseline;
}
.system-foundryvtt-reve-de-dragon .item-actions-controls img,
.system-foundryvtt-reve-de-dragon .item-controls img {
@@ -2398,6 +2517,8 @@ body {
[data-tab="items"],
[data-tab="journal"],
[data-tab="cards"],
[data-tab="tables"],
[data-tab="placeables"],
[data-tab="macros"],
[data-tab="tables"],
[data-tab="playlists"],
@@ -2426,6 +2547,9 @@ body {
.system-foundryvtt-reve-de-dragon #sidebar-tabs menu button[data-tab="scenes"] {
background-image: url("../assets/ui/icon_sidebar_scene.svg");
}
.system-foundryvtt-reve-de-dragon #sidebar-tabs menu button[data-tab="placeables"] {
background-image: url("../assets/ui/icon_sidebar_placeables.svg");
}
.system-foundryvtt-reve-de-dragon #sidebar-tabs menu button[data-tab="actors"] {
background-image: url("../assets/ui/icon_sidebar_actor.svg");
}
@@ -2442,7 +2566,7 @@ body {
background-image: url("../assets/ui/icon_sidebar_macros.svg");
}
.system-foundryvtt-reve-de-dragon #sidebar-tabs menu button[data-tab="tables"] {
background-image: url("../assets/ui/d100.svg");
background-image: url("../assets/ui/icon_sidebar_tables.svg");
}
.system-foundryvtt-reve-de-dragon #sidebar-tabs menu button[data-tab="playlists"] {
background-image: url("../assets/ui/icon_sidebar_music.svg");
@@ -2499,12 +2623,6 @@ body {
background: #1e1914;
border: 1px solid #482e1c;
}
.system-foundryvtt-reve-de-dragon #players {
border-image: url(../assets/ui/footer-button.webp) 10 repeat;
border-image-width: 4px;
border-image-outset: 0px;
background: #1e1914;
}
.system-foundryvtt-reve-de-dragon #navigation #scene-list .scene.nav-item.active {
background: #482e1c;
}
@@ -2841,12 +2959,19 @@ body {
padding: 0.3rem;
font-family: "CaslonAntique";
}
.system-foundryvtt-reve-de-dragon aside#tooltip h4 {
color: var(--rdd-color-text-primary);
}
.system-foundryvtt-reve-de-dragon aside#tooltip span.reference {
color: var(--color-tooltip);
border: 1px solid var(--color-tooltip-faint);
}
.system-foundryvtt-reve-de-dragon aside#tooltip .toolclip p.faint {
color: var(--color-tooltip-faint);
color: var(--color-tooltip);
}
.system-foundryvtt-reve-de-dragon aside#tooltip .toolclip span.reference {
color: var(--color-tooltip);
background-color: var(--color-controls-hover);
}
.system-foundryvtt-reve-de-dragon .chat-card-info {
font-size: 1.1rem;
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 198 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 184 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 155 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 177 KiB

+4 -3
View File
@@ -1,5 +1,6 @@
<h3>Joyeuses fêtes</h3>
<h3>L'oeuf de Dragon</h3>
<p>
VincentVK, LeRatierBretonnien et toute l'équipe de Scriptrarium vous
souhaitent de joyeuses et oniriques fêtes !
On raconte que si le premier Vaisseau, on trouve un oeuf couvé par
un lapin, il faut bien s'occuper dudit lapin, car quatre mois plus tard
pourrait bien éclore un dragon!
</p>
+160 -45
View File
@@ -393,49 +393,56 @@
text-align: left;
}
.equipement-nom {
flex-grow: 3;
flex-grow: 4;
flex-shrink: 2;
margin: 0;
justify-content: center;
text-align: left;
display: ruby;
}
.equipement-valeur {
margin: 0;
flex-grow: 1.5;
flex-grow: 1;
flex-shrink: 1;
text-align: center;
}
.equipement-detail {
margin: 0;
flex-grow: 1;
align-items: center;
justify-content: center;
text-align: center;
}
span.equipement-detail-buttons {
margin: 0;
flex-grow: 1.5;
flex-shrink: 1;
align-items: center;
justify-content: center;
text-align: center;
display: flex;
flex-direction: row;
min-width: max-content;
}
.equipement-button {
margin: 0;
flex-grow: 0.5;
align-items: center;
justify-content: center;
text-align: center;
.conteneur-sature {
color: #c00 !important;
font-weight: bold;
}
:is(.item-actions-controls, .equipement-actions) {
margin: 0;
flex-grow: 1.2;
align-items: end;
justify-content: flex-end;
text-align: right;
.conteneur-capacity-bar {
width: 5rem;
height: 0.4rem;
background: rgba(0, 0, 0, 0.1);
border-radius: 0.2rem;
overflow: hidden;
margin: 0 0.3rem;
}
.liste-equipement :is(.equipement-actions, .item-actions-controls) {
flex-grow: 2;
.conteneur-capacity-fill {
height: 100%;
background: #4a90d9;
border-radius: 0.2rem;
transition: width 0.3s;
}
.conteneur-parent-badge {
font-size: 0.7rem;
color: #666;
margin-left: 0.3rem;
&::before {
content: "(";
}
&::after {
content: ")";
}
}
.blessure-control {
@@ -505,6 +512,98 @@
padding: 0.1rem;
}
.dialog-gerer-herbes table {
width: 100%;
}
.dialog-gerer-herbes table th,
.dialog-gerer-herbes table td {
padding: 0.2rem 0.3rem !important;
vertical-align: middle !important;
}
.dialog-gerer-herbes table th {
color: var(--color-text-light-heading, #f0f0f0) !important;
font-weight: bold !important;
}
.dialog-gerer-herbes table th:first-child,
.dialog-gerer-herbes table td:first-child {
width: 36px !important;
text-align: center !important;
}
.dialog-gerer-herbes table th:nth-child(2),
.dialog-gerer-herbes table td:nth-child(2) {
width: auto !important;
}
.dialog-gerer-herbes table th:nth-child(3),
.dialog-gerer-herbes table td:nth-child(3) {
width: 3rem !important;
text-align: center !important;
}
.dialog-gerer-herbes table th:nth-child(4),
.dialog-gerer-herbes table td:nth-child(4) {
width: 6rem !important;
text-align: center !important;
}
.dialog-gerer-herbes table th:nth-child(5),
.dialog-gerer-herbes table td:nth-child(5) {
width: 5rem !important;
text-align: center !important;
}
.dialog-gerer-herbes table th:nth-child(7),
.dialog-gerer-herbes table td:nth-child(7) {
width: 2.5rem !important;
text-align: center !important;
}
.dialog-gerer-herbes table select {
max-width: 12rem !important;
min-width: 8rem !important;
}
.dialog-gerer-herbes table img {
width: 30px !important;
height: 30px !important;
object-fit: cover !important;
border: none !important;
}
.dialog-gerer-ingredients table {
width: 100%;
}
.dialog-gerer-ingredients table td {
padding: 0.2rem 0.3rem !important;
vertical-align: middle !important;
}
.dialog-gerer-ingredients table td:first-child {
width: 36px !important;
text-align: center !important;
}
.dialog-gerer-ingredients table td:nth-child(2) {
width: auto !important;
}
.dialog-gerer-ingredients table td:nth-child(3) {
width: 3rem !important;
text-align: center !important;
}
.dialog-gerer-ingredients table td:nth-child(4) {
width: 6rem !important;
text-align: center !important;
}
.dialog-gerer-ingredients table td:nth-child(5) {
width: auto !important;
}
.dialog-gerer-ingredients table td:nth-child(6) {
width: 2.5rem !important;
text-align: center !important;
}
.dialog-gerer-ingredients table select {
max-width: 12rem !important;
min-width: 8rem !important;
}
.dialog-gerer-ingredients table img {
width: 30px !important;
height: 30px !important;
object-fit: cover !important;
border: none !important;
}
.dice-img {
border-width: 0;
max-width: 1.5rem;
@@ -848,12 +947,20 @@
.competence-list .item-controls.hidden-controls {
display: none !important;
}
.competence-header .item-actions-controls{
flex-shrink: 2;
flex-grow: 2;
}
.item-actions-controls,
.item-controls {
vertical-align: super;
// a {
// }
margin: 0;
flex-grow: 1;
flex-shrink: 1;
align-items: end;
text-align: right;
min-width: max-content;
flex-basis: fit-content;
vertical-align: baseline;
img {
vertical-align: text-bottom;
display: inline;
@@ -1798,6 +1905,8 @@
[data-tab="items"],
[data-tab="journal"],
[data-tab="cards"],
[data-tab="tables"],
[data-tab="placeables"],
[data-tab="macros"],
[data-tab="tables"],
[data-tab="playlists"],
@@ -1827,6 +1936,9 @@
button[data-tab="scenes"] {
background-image: url("../assets/ui/icon_sidebar_scene.svg");
}
button[data-tab="placeables"] {
background-image: url("../assets/ui/icon_sidebar_placeables.svg");
}
button[data-tab="actors"] {
background-image: url("../assets/ui/icon_sidebar_actor.svg");
}
@@ -1843,7 +1955,7 @@
background-image: url("../assets/ui/icon_sidebar_macros.svg");
}
button[data-tab="tables"] {
background-image: url("../assets/ui/d100.svg");
background-image: url("../assets/ui/icon_sidebar_tables.svg");
}
button[data-tab="playlists"] {
background-image: url("../assets/ui/icon_sidebar_music.svg");
@@ -1912,13 +2024,6 @@
border: 1px solid rgba(72, 46, 28, 1);
}
#players {
border-image: url(../assets/ui/footer-button.webp) 10 repeat;
border-image-width: 4px;
border-image-outset: 0px;
background: rgba(30, 25, 20, 1);
}
#navigation #scene-list .scene.nav-item.active {
background: rgba(72, 46, 28, 1);
}
@@ -2288,15 +2393,25 @@
border-radius: 0.2rem;
padding: 0.3rem;
font-family: "CaslonAntique";
}
h4{
color: var(--rdd-color-text-primary);
}
aside#tooltip span.reference {
color: var(--color-tooltip);
border: 1px solid var(--color-tooltip-faint);
}
aside#tooltip .toolclip p.faint {
color: var(--color-tooltip-faint);
span.reference {
color: var(--color-tooltip);
border: 1px solid var(--color-tooltip-faint);
}
.toolclip{
p.faint {
color: var(--color-tooltip);
}
span.reference{
color: var(--color-tooltip);
background-color: var(--color-controls-hover);
}
}
}
.chat-card-info {
+20 -5
View File
@@ -32,6 +32,7 @@
display: flex;
flex-direction: column;
}
roll-conditions roll-section[name="rollmode"],
roll-type {
button[data-checked="true"] {
@@ -64,6 +65,13 @@
flex-direction: row;
align-items: anchor-center;
margin: 0 0.2rem;
label {
text-align:left;
min-width: 55%;
display: flex;
flex-direction: row;
}
}
roll-resume {
@@ -241,11 +249,18 @@
padding: 0;
filter: invert(0.8);
}
roll-conditions roll-section[name="tricher"] img {
/* image de d100 */
max-width: 2.5rem;
max-height: 2.5rem;
}
roll-conditions roll-section[name="tricher"] {
label {
display: flex;
flex-direction: row;
img {
/* image de d100 */
max-width: 2rem;
max-height: 2rem;
}
}
}
roll-buttons {
display: flex;
+42 -5
View File
@@ -31,7 +31,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
static get defaultOptions() {
return foundry.utils.mergeObject(RdDBaseActorReveSheet.defaultOptions, {
template: "systems/foundryvtt-reve-de-dragon/templates/actor-sheet.hbs",
width: 550,
width: 640,
showCompNiveauBase: false,
vueArchetype: false,
}, { inplace: false })
@@ -51,7 +51,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
foundry.utils.mergeObject(formData.calc, {
surenc: this.actor.computeMalusSurEncombrement(),
surprise: RdDBonus.find(this.actor.getSurprise(false)).label,
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
blessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
caracTotalXp: RdDCarac.computeTotalXp(this.actor.system.carac, this.actor.system.beaute),
surEncombrementMessage: this.actor.isSurenc() ? "Sur-Encombrement!" : "",
@@ -70,6 +70,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
fatigue: RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max)
})
this.amendTacheCommunes(formData)
formData.competences.forEach(item => {
item.system.isHidden = this.options.recherche
@@ -100,20 +101,38 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
cacheTMR: this.actor.isTMRCache()
}
formData.livresLus = formData.livres.filter(l => l.system.estCopieLue)
formData.livres = formData.livres.filter(l => !l.system.estCopieLue)
formData.race = actor.itemTypes[ITEM_TYPES.race].find(it => true)
formData.subacteurs = {
vehicules: this.actor.listeVehicules(),
montures: this.actor.listeMontures(),
suivants: this.actor.listeSuivants()
}
if (this.actor.getBestDraconic().system.niveau > -11 && !this.actor.isHautRevant()) {
if (this.actor.getDraconics().find(it => it.system.niveau > -11) && !this.actor.isHautRevant()) {
ui.notifications.error(`${this.actor.name} a des compétences draconiques, mais pas le don de Haut-Rêve!
<br>Ajoutez-lui la tête "Don de Haut-Rêve" pour lui permettre d'utiliser ses compétences et d'accéder aux terres médianes du rêve`);
}
}
else {
console.error("Ouverture actor-sheet avec un acteur non personnage")
}
return formData;
}
amendTacheCommunes(formData) {
formData.taches
.forEach(tache => {
if (tache.isTacheCommune()) {
const tacheCommune = tache.getTacheOuCommune()
tache.system = foundry.utils.duplicate(tacheCommune.system)
tache.system.tacheCommuneId = tache.system.tacheCommuneId
}
return tache
})
}
/* -------------------------------------------- */
/** @override */
activateListeners(html) {
@@ -196,6 +215,23 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
this.html.find('.action-recettecuisine').click(async event => await this.actor.rollRecetteCuisine(RdDSheetUtility.getItemId(event)))
this.html.find('.description-aleatoire').click(async event => new AppPersonnageAleatoire(this.actor).render(true))
this.html.find('.gerer-herbes').click(async event => {
const { DialogGererHerbes } = await import("./dialog-gerer-herbes.js")
DialogGererHerbes.create(this.actor)
})
this.html.find('.gerer-ingredients').click(async event => {
const { DialogGererIngredients } = await import("./dialog-gerer-ingredients.js")
DialogGererIngredients.create(this.actor)
})
this.html.find('.gerer-deniers').click(async event => {
const { DialogGererDeniers } = await import("./dialog-gerer-deniers.js")
DialogGererDeniers.create(this.actor)
})
this.html.find('.gerer-potions').click(async event => {
const { DialogGererPotions } = await import("./dialog-gerer-potions.js")
DialogGererPotions.create(this.actor)
})
if (game.user.isGM) {
// experience log
this.html.find('.experiencelog-delete').click(async event => {
@@ -216,7 +252,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
// Points de reve actuel
this.html.find('.roll-reve-actuel').click(async event => await this.actor.rollReveActuel({ resistance: false }))
this.html.find('.button-reve-resistance').click(async event => await this.actor.rollReveActuel({ diff: -8, resistance: true }))
this.html.find('.button-reve-resistance').click(async event => await this.actor.rollReveResistance())
this.html.find('.action-empoignade').click(async event => await RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor)))
this.html.find('.roll-arme').click(async event => {
@@ -275,11 +311,12 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
await this.actor.updateCompetenceArchetype(compName, parseInt(event.target.value));
});
this.html.find('.nouvelle-incarnation').click(async event => await this.actor.nouvelleIncarnation())
this.html.find('.repartition-archetype-aleatoire').click(async event => await this.actor.repartitionArchetypeAleatoire())
}
// On pts de reve change
this.html.find('.pointsreve-value').change(async event => await this.actor.update({ "system.reve.reve.value": event.currentTarget.value }))
this.html.find('.seuil-reve-value').change(async event => await this.actor.setPointsDeSeuil(event.currentTarget.value))
this.html.find('.seuil-reve-value').change(async event => await this.actor.update({ "system.reve.seuil.value": event.currentTarget.value }))
this.html.find('.stress-test').click(async event => await this.actor.transformerStress())
this.html.find('.moral-malheureux').click(async event => await this.actor.jetDeMoral(MORAL.MALHEUREUX))
+375 -415
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -14,7 +14,7 @@ export class RdDBaseActorReveSheet extends RdDBaseActorSheet {
/** @override */
static get defaultOptions() {
return foundry.utils.mergeObject(RdDBaseActorSheet.defaultOptions, {
width: 550
width: 640
});
}
+64 -43
View File
@@ -22,13 +22,12 @@ 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, CATEGORIES_COMPETENCES_CREATURES } from "../item/base-items.js";
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES_CREATURES, SANS_DRACONIC } 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 } from "../roll/roll-constants.mjs";
import { DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP, ROLL_TYPE_REVE_RESISTANCE } from "../roll/roll-constants.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js";
import { 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";
@@ -103,17 +102,18 @@ export class RdDBaseActorReve extends RdDBaseActor {
}
getDraconics() { return [] }
getDraconicOuPossession() {
getDraconicOuNaturel(options = {possession: false}) {
return [
...this.getDraconics(),
...this.itemTypes[ITEM_TYPES.competencecreature].filter(it => it.isCompetencePossession()),
this.getConjurationNaturelle()
options.possession ? this.getConjurationNaturelle() : SANS_DRACONIC
].sort(Misc.descending(it => it.system.niveau));
}
getConjurations() {
return this.getDraconicOuPossession()
.map(it => this.toActionConjuration(it))
getBestDraconic(options = {possession: false}) {
return this.getDraconicOuNaturel(options)
.find(it => true)
}
getConjurationNaturelle() {
@@ -145,7 +145,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
}
}
listActions({ isAttaque = false, isEquipe = false }) {
listActions() {
return this.itemTypes[ITEM_TYPES.competencecreature]
.filter(it => it.isAttaque())
.map(it => it.attaqueCreature())
@@ -154,11 +154,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
async computeArmure(dmg) { return this.getProtectionNaturelle() }
async remiseANeuf() { }
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
async ajoutExperience(rollData, hideChatMessage = 'show') { }
computeResumeBlessure() { }
computeResumeBlessure() { return [] }
countBlessures(filter = it => !it.isContusion()) { return 0 }
async santeIncDec(name, inc, options = {}) { }
async santeIncDec(name, inc, isCritique) { }
async finDeRound(options = { terminer: false }) {
await this.finDeRoundSuppressionEffetsTermines(options)
@@ -169,10 +169,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
}
async finDeRoundSuppressionEffetsTermines(options) {
for (let effect of this.getEffects()) {
const effects = this.getEffects();
for (let effect of effects) {
if (effect.duration.type !== 'none' && (effect.duration.remaining <= 0 || options.terminer)) {
await effect.delete();
ChatMessage.create({ content: `${this.getAlias()} n'est plus ${Misc.lowerFirst(game.i18n.localize(effect.system.label))} !` });
await effect.delete()
await ChatMessage.create({ content: `${this.getAlias()} n'est plus ${Misc.lowerFirst(game.i18n.localize(effect.system.label))} !` })
}
}
}
@@ -255,15 +256,15 @@ export class RdDBaseActorReve extends RdDBaseActor {
if (competence) {
function getFieldPath(fieldName) {
switch (fieldName) {
case "niveau": return 'system.niveau';
case "dommages": return 'system.dommages';
case "carac_value": return 'system.carac_value';
case "niveau": return 'system.niveau'
case "dommages": return 'system.dommages'
case "carac_value": return 'system.carac_value'
}
return undefined
}
const path = getFieldPath(fieldName);
const path = getFieldPath(fieldName)
if (path) {
await competence.update({ [path]: value });
await competence.update({ [path]: value })
}
}
}
@@ -295,7 +296,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
/* -------------------------------------------- */
createCallbackExperience() {
return { action: r => this.appliquerAjoutExperience(r) }
return { action: r => this.ajoutExperience(r) }
}
/* -------------------------------------------- */
@@ -304,7 +305,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
return { action: r => this.appliquerAppelMoral(r) }
}
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
async ajoutExperience(rollData, hideChatMessage = 'show') { }
async appliquerAppelMoral(rollData) { }
async _onCloseRollDialog(html) { }
@@ -316,7 +317,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
const competence = this.getCompetence(compName);
const rollData = {
ids: { actorId: this.id },
type: { allowed: DEFAULT_ROLL_TYPES, current: PART_COMP },
type: { allowed: DEFAULT_ROLL_TYPES, current: ROLL_TYPE_COMP },
selected: {
carac: { key: caracName },
comp: { key: competence.name },
@@ -347,7 +348,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
});
}
/**
* Méthode pour faire un jet prédéterminer sans ouvrir la fenêtre de dialogue
* Méthode pour faire un jet prédéterminé sans ouvrir la fenêtre de dialogue
*
* @param {*} caracName code ou label de la caractéristique. On peut utiliser 'intel' pour Intellect.
* @param {*} compName nom de compétence ou nom abrégé.
* @param {*} diff difficulté (0 si undefined)
@@ -367,17 +369,16 @@ export class RdDBaseActorReve extends RdDBaseActor {
selectedCarac: carac,
competence: competence,
diffLibre: diff ?? 0,
current: { rollmode: { key: game.settings.get("core", "rollMode") } },
show: { title: options?.title ?? '' }
}
RollDataAjustements.calcul(rollData, this);
await RdDResolutionTable.rollData(rollData);
this.gererExperience(rollData);
await RdDResolutionTable.displayRollData(rollData, this)
this.ajoutExperience(rollData);
await RdDRollResult.displayRollData(rollData, this)
return rollData.rolled;
}
gererExperience(rollData) { }
/* -------------------------------------------- */
async roll() {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
@@ -385,7 +386,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
ids: { actorId: this.id },
type: {
allowed: DEFAULT_ROLL_TYPES,
current: PART_COMP,
current: ROLL_TYPE_COMP,
},
selected: {
diff: { type: DIFF.DEFAUT }
@@ -413,13 +414,33 @@ export class RdDBaseActorReve extends RdDBaseActor {
})
}
/* -------------------------------------------- */
async rollReveResistance(diff = -8) {
return await RollDialog.create(
{
ids: { actorId: this.id },
type: {
allowed: [ROLL_TYPE_REVE_RESISTANCE],
current: ROLL_TYPE_REVE_RESISTANCE,
resistance: true
},
selected: {
carac: { key: CARACS.REVE_ACTUEL, forced: true },
comp: { key: undefined, forced: true },
diff: { type: DIFF.DEFAUT, value: diff }
}
},
{
onRollDone: (dialog, roll) => RollDialog.onRollDoneClose(dialog, roll)
})
}
async rollReveActuel({ diff = 0, resistance = false }) {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
type: {
allowed: [PART_COMP],
current: PART_COMP,
allowed: [ROLL_TYPE_REVE_RESISTANCE],
current: ROLL_TYPE_REVE_RESISTANCE,
resistance: resistance
},
selected: {
@@ -441,8 +462,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
const rollData = {
ids: { actorId: this.id },
type: {
allowed: options.resistance ? [PART_COMP] : DEFAULT_ROLL_TYPES,
current: PART_COMP,
allowed: options.resistance ? [ROLL_TYPE_COMP] : DEFAULT_ROLL_TYPES,
current: options.resistance ? ROLL_TYPE_COMP : ROLL_TYPE_COMP,
resistance: options.resistance
},
selected: {
@@ -617,7 +638,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
RdDPossessionV2.rollAttaquePossession(this)
}
verifierForceMin(item) { }
async verifierForceMin(item) { }
/* -------------------------------------------- */
async encaisser() { await RdDEncaisser.encaisser(this) }
@@ -667,20 +688,20 @@ export class RdDBaseActorReve extends RdDBaseActor {
show: show ?? {}
}, { overwrite: false });
await ChatUtility.createChatWithRollMode({
roll: encaissement.roll,
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.hbs', encaissement)
},
this
)
await ChatMessage.create(ChatUtility.adaptVisibility(
{
roll: encaissement.roll,
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.hbs', encaissement)
},
{ actor: this }))
if (!encaissement.hasPlayerOwner && encaissement.endurance != 0) {
encaissement = foundry.utils.duplicate(encaissement)
encaissement.isGM = true
ChatMessage.create({
await ChatMessage.create({
whisper: ChatUtility.getGMs(),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-encaissement.hbs', encaissement)
});
})
}
}
@@ -727,7 +748,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
}
await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-accorder-cauchemar.hbs')
await this.appliquerAjoutExperience(rollData, true)
await this.ajoutExperience(rollData, true)
return rolled.isSuccess;
}
+1 -1
View File
@@ -36,7 +36,7 @@ export class RdDBaseActorSangSheet extends RdDBaseActorReveSheet {
async jetEndurance() {
const endurance = this.actor.getEnduranceActuelle()
const result = await this.actor.jetEndurance(endurance);
ChatMessage.create({
await ChatMessage.create({
content: `Jet d'Endurance : ${result.jetEndurance} / ${endurance}
<br>${this.actor.name} a ${result.sonne ? 'échoué' : 'réussi'} son Jet d'Endurance ${result.sonne ? 'et devient Sonné' : ''}`,
whisper: ChatUtility.getOwners(this.actor)
+54 -67
View File
@@ -17,6 +17,14 @@ import { CARACS } from "../rdd-carac.js";
*/
export class RdDBaseActorSang extends RdDBaseActorReve {
async _preUpdate(changed, options, user) {
const updatedEndurance = changed?.system?.sante?.endurance
if (updatedEndurance && options.diff) {
await this.setEffect(STATUSES.StatusUnconscious, updatedEndurance.value == 0)
}
return super._preUpdate(changed, options, user)
}
prepareActorData() {
this.system.sante.vie.max = Math.ceil((this.getTaille() + this.getConstitution()) / 2)
this.system.sante.vie.value = Math.min(this.system.sante.vie.value, this.system.sante.vie.max)
@@ -71,43 +79,32 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return Math.min(0, Math.floor(this.getEncombrementMax() - this.encTotal));
}
countBlessures(filter) { return this.itemTypes[ITEM_TYPES.blessure].filter(filter).length }
isDead() { return this.system.sante.vie.value < -this.getSConst() }
nbBlessuresLegeres() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isLegere()).length }
nbBlessuresGraves() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isGrave()).length }
nbBlessuresCritiques() { return this.itemTypes[ITEM_TYPES.blessure].filter(it => it.isCritique()).length }
/* -------------------------------------------- */
computeResumeBlessure() {
const nbLegeres = this.nbBlessuresLegeres()
const nbGraves = this.nbBlessuresGraves()
const nbCritiques = this.nbBlessuresCritiques()
function descBlessure(count, name) {
return count > 0 ? [`${count} ${name}${count > 1 ? "s" : ""}`] : []
}
if (nbLegeres + nbGraves + nbCritiques == 0) {
return "Aucune blessure";
}
let resume = "Blessures:";
if (nbLegeres > 0) {
resume += " " + nbLegeres + " légère" + (nbLegeres > 1 ? "s" : "");
}
if (nbGraves > 0) {
if (nbLegeres > 0)
resume += ",";
resume += " " + nbGraves + " grave" + (nbGraves > 1 ? "s" : "");
}
if (nbCritiques > 0) {
if (nbGraves > 0 || nbLegeres > 0)
resume += ",";
resume += " une CRITIQUE !";
}
return resume;
const nbContusions = this.countBlessures(it => it.isContusion())
const nbLegeres = this.countBlessures(it => it.isLegere())
const nbGraves = this.countBlessures(it => it.isGrave())
const nbCritiques = this.countBlessures(it => it.isCritique())
return [
... (nbCritiques > 0 ? ['une CRITIQUE !'] : []),
...descBlessure(nbGraves, 'grave'),
...descBlessure(nbLegeres, 'légère'),
...descBlessure(nbContusions, 'contusion'),
]
}
blessuresASoigner() { return [] }
async computeArmure(attackerRoll) { return this.getProtectionNaturelle() }
async remiseANeuf() { }
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
async ajoutExperience(rollData, hideChatMessage = 'show') { }
/* -------------------------------------------- */
@@ -125,10 +122,10 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
blessure.system.vie = blessure.system.vie
const rollPerteEndurance = new Roll(blessure.system.endurance)
await rollPerteEndurance.evaluate()
blessure.system.endurance =rollPerteEndurance.total
blessure.system.endurance = rollPerteEndurance.total
}
const isCritique = blessure.system.gravite >= 6;
if (isCritique){
if (isCritique) {
blessure.system.endurance = this.getEnduranceActuelle()
}
// Will update the result table
@@ -137,8 +134,8 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
encaissement.mort = "à seconde blessure critique"
}
const perteVie = await this.santeIncDec("vie", -encaissement.vie, { render: false })
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, { isCritique, render: false })
const perteVie = await this.santeIncDec("vie", -encaissement.vie)
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance, isCritique)
await this.createEmbeddedDocuments('Item', [blessure])
foundry.utils.mergeObject(encaissement, {
@@ -152,7 +149,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
}
/* -------------------------------------------- */
async santeIncDec(name, inc, options = {}) {
async santeIncDec(name, inc, isCritique = false) {
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
return
}
@@ -164,16 +161,16 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
const result = { sonne: false }
let perteEndurance = 0
let minValue = name == "vie" ? -this.getSConst() - 1 : 0;
result.newValue = Math.max(minValue, Math.min(compteur.value + inc, compteur.max));
let fatigue = 0;
if (name == "endurance" && result.newValue == 0 && inc < 0 && !options.isCritique) { // perte endurance et endurance devient 0 (sauf critique) -> -1 vie
sante.vie.value--;
result.perteVie = true;
}
foundry.utils.mergeObject(options, { render: true }, { overwrite: false })
if (name == "endurance") {
if (result.newValue == 0 && inc < 0 && !isCritique) {
// perte endurance et endurance devient 0 (sauf critique) -> -1 vie
sante.vie.value--
result.perteVie = true
}
result.newValue = Math.max(0, result.newValue);
if (inc > 0) { // le max d'endurance s'applique seulement à la récupération
result.newValue = Math.min(result.newValue, this._computeEnduranceMax())
@@ -189,17 +186,17 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
if (ReglesOptionnelles.isUsing("appliquer-fatigue") && sante.fatigue && fatigue > 0) {
sante.fatigue.value = Math.max(sante.fatigue.value + fatigue, this.getFatigueMin());
}
await this.update({ "system.sante": sante }, options)
await this.update({ "system.sante": sante })
if (perteEndurance > 1) {
// Peut-être sonné si 2 points d'endurance perdus d'un coup
foundry.utils.mergeObject(result, await this.jetEndurance(result.newValue, options));
foundry.utils.mergeObject(result, await this.jetEndurance(result.newValue));
} else if (name == "endurance" && inc > 0) {
await this.setSonne(false, options)
await this.setSonne(false)
}
if (this.isDead()) {
await this.setEffect(STATUSES.StatusComma, true, options)
await this.setEffect(STATUSES.StatusComma, true)
}
return result
}
@@ -281,14 +278,6 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return Math.max(0, Math.min(maxEndVie, maxEndGraves, maxEndCritiques));
}
async onUpdateActor(update, options, actorId) {
const updatedEndurance = update?.system?.sante?.endurance
if (updatedEndurance && options.diff) {
await this.setEffect(STATUSES.StatusUnconscious, updatedEndurance.value == 0)
}
await super.onUpdateActor(update, options, actorId)
}
async onCreateItem(item, options, id) {
await this.changeItemEffects(item)
await super.onCreateItem(item, options, id)
@@ -307,12 +296,12 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
async changeItemEffects(item) {
switch (item.type) {
case ITEM_TYPES.blessure:
await this.changeStateBleeding();
await this.changeStateBleeding()
break;
case ITEM_TYPES.maladie:
case ITEM_TYPES.poison:
await this.changeStateMalade();
break;
await this.changeStateMalade()
break
}
}
@@ -349,10 +338,10 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
}
}
async supprimerBlessures(filterToDelete, options = { render: true}) {
async supprimerBlessures(filterToDelete) {
const toDelete = this.filterItems(filterToDelete, ITEM_TYPES.blessure)
.map(it => it.id)
await this.deleteEmbeddedDocuments('Item', toDelete, options)
await this.deleteEmbeddedDocuments('Item', toDelete)
}
countBlessures(filter = it => !it.isContusion()) {
@@ -362,19 +351,17 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
/* -------------------------------------------- */
async jetDeVie() {
if (this.isDead()) {
ChatMessage.create({
return await ChatMessage.create({
content: `Jet de Vie: ${this.getAlias()} est déjà mort, ce n'est pas la peine d'en rajouter !!!!!`,
whisper: ChatUtility.getOwners(this)
})
return
}
const jetDeVie = await RdDDice.roll("1d20");
const sConst = this.getSConst();
const vie = this.system.sante.vie.value;
const isCritique = this.nbBlessuresCritiques() > 0;
const isGrave = this.nbBlessuresGraves();
const isEchecTotal = jetDeVie.total == 20;
const isCritique = this.countBlessures(it => it.isCritique()) > 0
const isGrave = this.countBlessures(it => it.isGrave())
const isEchecTotal = jetDeVie.total == 20
const isSuccess = jetDeVie.total == 1 || jetDeVie.total <= vie;
const perte = isSuccess ? 0 : 1 + (isEchecTotal ? vie + sConst : 0)
const prochainJet = (jetDeVie.total == 1 && vie > 0 ? 20 : 1) * (isCritique ? 1 : isGrave > 0 ? sConst : 0)
@@ -392,18 +379,18 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
else if (prochainJet > 0) {
msgText += `<br>Prochain jet de vie dans ${prochainJet} ${isCritique ? 'round' : 'minute'}${prochainJet > 1 ? 's' : ''} ${isCritique ? '(état critique)' : '(état grave)'}`
}
ChatMessage.create({
return await ChatMessage.create({
content: msgText,
whisper: ChatUtility.getOwners(this)
});
})
}
/* -------------------------------------------- */
async jetEndurance(resteEndurance = undefined, options) {
async jetEndurance(resteEndurance = undefined) {
const jetEndurance = (await RdDDice.roll("1d20")).total;
const sonne = jetEndurance == 20 || jetEndurance > (resteEndurance ?? this.system.sante.endurance.value)
if (sonne) {
await this.setSonne(true, options)
await this.setSonne(true)
}
return { jetEndurance, sonne }
}
@@ -417,13 +404,13 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
}
}
async setSonne(sonne = true, options = {}) {
async setSonne(sonne = true) {
if (!game.combat && sonne) {
// TODO: vérifier si comportement toujours valable
ui.notifications.info(`${this.getAlias()} est hors combat, il ne reste donc pas sonné`);
return
}
await this.setEffect(STATUSES.StatusStunned, sonne, options)
await this.setEffect(STATUSES.StatusStunned, sonne)
}
isSonne() {
+67 -2
View File
@@ -23,7 +23,9 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
classes: ["rdd", "sheet", "actor"],
tabs: [{ navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "carac" }],
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: undefined }],
vueDetaillee: false
scrollY: [".sheet-body"],
vueDetaillee: false,
triEquipement: 'name'
}, { inplace: false })
}
@@ -45,7 +47,7 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
effects: this.actor.effects
}
RdDUtility.filterItemsPerTypeForSheet(formData, this.actor.itemTypes);
RdDUtility.filterItemsPerTypeForSheet(formData, this.actor.itemTypes, this.options.triEquipement);
formData.calc = {
fortune: Monnaie.toSolsDeniers(this.actor.getFortune()),
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
@@ -104,6 +106,16 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
this.html.find('.recherche').prop("disabled", false)
this.html.find('.item-list .item').dblclick(async event => {
const item = this.getItem(event)
if (item) item.sheet.render(true)
})
this.html.find('.tri-equipement').change(event => {
this.options.triEquipement = event.currentTarget.value;
this.render(true);
})
// Everything below here is only needed if the sheet is editable
if (!this.options.editable) return;
@@ -111,6 +123,46 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
this.html.find('.item-delete').click(async event => await RdDUtility.confirmActorItemDelete(this.getItem(event), this.actor));
this.html.find('.item-quantite-plus').click(async event => await this.actor.itemQuantiteIncDec(this.getItemId(event), 1));
this.html.find('.item-quantite-moins').click(async event => await this.actor.itemQuantiteIncDec(this.getItemId(event), -1));
this.html.find('.item-quantite').change(async event => {
const input = event.currentTarget;
const item = this.actor.items.get(input.dataset.itemId);
if (item) {
const newQty = Math.max(0, parseInt(input.value) || 0);
await item.update({ 'system.quantite': newQty });
if (newQty === 0) this.render(true);
}
})
this.html.find('.item-quantite').on('contextmenu', async event => {
event.preventDefault()
const item = this.getItem(event)
if (!item?.isInventaire()) return
new Dialog({
title: `Quantité — ${item.name}`,
content: `<p>Réduire la quantité de :</p>
<select class="qty-amount" style="width:100%">
<option value="1">1</option>
<option value="5">5</option>
<option value="10">10</option>
<option value="all">Tout jeter</option>
</select>`,
buttons: {
reduce: {
icon: '<i class="fas fa-minus"></i>',
label: 'Retirer',
callback: html => {
const amount = html.find('.qty-amount').val()
if (amount === 'all') {
item.delete()
this.render(true)
} else {
item.update({ 'system.quantite': Math.max(0, item.system.quantite - parseInt(amount)) })
}
}
}
}
}).render(true)
})
this.html.find('.creer-un-objet').click(async event => await this.selectObjetTypeToCreate())
this.html.find('.nettoyer-conteneurs').click(async event => await this.actor.nettoyerConteneurs())
@@ -180,15 +232,28 @@ export class RdDBaseActorSheet extends foundry.appv1.sheets.ActorSheet {
/* -------------------------------------------- */
async _onDropItem(event, dragData) {
const destItemId = this.html.find(event.target)?.closest('.item').attr('data-item-id')
const previousItemIds = new Set(this.actor.items.keys())
const dropParams = await RdDSheetUtility.prepareItemDropParameters(destItemId, this.actor, dragData, this.objetVersConteneur)
if (dropParams) {
const callSuper = await this.actor.processDropItem(dropParams)
if (callSuper) {
await super._onDropItem(event, dragData)
}
// For external drops onto a container row, place the new item inside
if (destItemId && dropParams.sourceActorId !== this.actor.id) {
const container = this.actor.items.get(destItemId)
if (container?.isConteneur()) {
const dropped = [...this.actor.items].find(i => !previousItemIds.has(i.id))
if (dropped && !this.actor.findConteneur(dropped)) {
await this.actor.ajouterDansConteneur(dropped, container, () => {})
}
}
}
}
}
/* -------------------------------------------- */
async selectObjetTypeToCreate() {
let types = this.getTypesInventaire().sort(Misc.ascending(type => Misc.typeName('Item', type)));
+78 -48
View File
@@ -49,11 +49,9 @@ export class RdDBaseActor extends Actor {
static init() {
Handlebars.registerHelper('actor-isFeminin', actor => actor.isFeminin())
Hooks.on("preUpdateItem", (item, change, options, id) => Misc.documentIfResponsible(item.parent)?.onPreUpdateItem(item, change, options, id))
Hooks.on("createItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onCreateItem(item, options, id))
Hooks.on("updateItem", (item, updates, options, id) => Misc.documentIfResponsible(item.parent)?.onUpdateItem(item, updates, options, id))
Hooks.on("deleteItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onDeleteItem(item, options, id))
Hooks.on("updateActor", (actor, change, options, actorId) => Misc.documentIfResponsible(actor)?.onUpdateActor(change, options, actorId))
}
static onSocketMessage(sockmsg) {
@@ -93,25 +91,11 @@ export class RdDBaseActor extends Actor {
}
static getRealActor(actorId, tokenId) {
if (tokenId) {
let token = canvas.tokens.get(tokenId)
if (token) {
return token.actor
}
}
return game.actors.get(actorId)
const actor = tokenId ? canvas.tokens.get(tokenId)?.actor : undefined
return actor ?? game.actors.get(actorId)
}
getAlias() {
if (this.token?.name != null && this.token != this.prototypeToken) {
return this.token.name
}
return this.name
}
isPersonnageJoueur() { return false }
static extractActorMin = (actor) => { return { id: actor?.id, type: actor?.type, name: actor?.name, img: actor?.img }; };
static extractActorMin(actor) { return { id: actor?.id, type: actor?.type, name: actor?.name, img: actor?.img } }
/**
* Cette methode surcharge Actor.create() pour ajouter si besoin des Items par défaut:
@@ -156,6 +140,13 @@ export class RdDBaseActor extends Actor {
super(docData, context);
}
getAlias() {
if (this.token?.name != null && this.token != this.prototypeToken) {
return this.token.name
}
return this.name
}
getCarac() {
return foundry.utils.duplicate(this.system.carac)
}
@@ -221,6 +212,41 @@ export class RdDBaseActor extends Actor {
}
}
async _preUpdate(changed, options, user) {
const updatedCarac = changed?.system?.carac
if (updatedCarac && (updatedCarac.force || updatedCarac.reve || updatedCarac.taille)) {
await this.setEffect(STATUSES.StatusSurEnc, this.isSurenc())
}
await this.delayedRenderSheet('_preUpdate', changed, options)
return super._preUpdate(changed, options, user)
}
_onUpdate(changed, options, userId) {
super._onUpdate(changed, options, userId)
if (userId == game.user.id){
this.delayedRenderSheet('_onUpdate', changed, options)
}
}
async delayedRenderSheet(caller, data, options) {
this.refreshDelayCounter = (this.refreshDelayCounter ?? 0)+1
if (this.refreshDelayCounter == 1) {
this.renderAfterDelay(this.refreshDelayCounter)
}
}
renderAfterDelay(currentCounter) {
setTimeout(async () => {
if (currentCounter == this.refreshDelayCounter) {
this.sheet?.render()
this.refreshDelayCounter = 0
}
else {
this.renderAfterDelay(this.refreshDelayCounter)
}
}, 50)
}
/* -------------------------------------------- */
prepareData() {
super.prepareData()
@@ -233,11 +259,13 @@ export class RdDBaseActor extends Actor {
prepareActorData() { }
async computeEtatGeneral() { }
/* -------------------------------------------- */
findPlayer() {
return game.users.players.find(player => player.active && player.character?.id == this.id);
}
isPersonnageJoueur() { return false }
isCreatureOuEntite() { return this.isCreature() || this.isEntite() }
isCreature() { return false }
isEntite() { return false }
@@ -285,7 +313,7 @@ export class RdDBaseActor extends Actor {
return this.getEffects().filter(it => it.statuses.has(effectId))
}
async setEffect(effectId, status, options = {render: true}) {
async setEffect(effectId, status, options = { render: true }) {
if (this.isEffectAllowed(effectId)) {
const effects = this.getEffectsByStatus(effectId)
if (!status && effects.length > 0) {
@@ -301,7 +329,7 @@ export class RdDBaseActor extends Actor {
this.removeEffects(it => it.id == id)
}
async removeEffects(filter = e => true, options = {render: true}) {
async removeEffects(filter = e => true, options = { render: true }) {
if (game.user.isGM) {
const ids = this.getEffects(filter)
.filter(it => this.canRemoveEffects(it))
@@ -326,16 +354,8 @@ export class RdDBaseActor extends Actor {
async updateCarac(caracName, to) {
}
async onUpdateActor(change, options, actorId) {
const updatedCarac = change?.system?.carac
if (updatedCarac && (updatedCarac.force || updatedCarac.reve || updatedCarac.taille)) {
console.log(' onUpdateActor', change, options, actorId)
await this.setEffect(STATUSES.StatusSurEnc, this.isSurenc())
}
}
/* -------------------------------------------- */
async onPreUpdateItem(item, change, options, id) { }
async onCreateItem(item, options, id) {
}
@@ -352,13 +372,13 @@ export class RdDBaseActor extends Actor {
}
async _removeItemFromConteneur(item) {
const updates = this.findConteneur(item)
.map(conteneur => {
const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id)
return { _id: conteneur.id, 'system.contenu': nouveauContenu }
})
if (updates.length > 0) {
await this.updateEmbeddedDocuments('Item', updates)
const conteneur = this.findConteneur(item);
if (conteneur) {
const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id)
const updates = { _id: conteneur.id, 'system.contenu': nouveauContenu }
if (updates.length > 0) {
await this.updateEmbeddedDocuments('Item', updates)
}
}
}
@@ -429,7 +449,7 @@ export class RdDBaseActor extends Actor {
msg = "Vous n'avez pas assez d'argent pour payer cette somme !";
}
ChatMessage.create({
await ChatMessage.create({
whisper: ChatUtility.getOwners(this),
content: msg
})
@@ -473,7 +493,7 @@ export class RdDBaseActor extends Actor {
await Monnaie.optimiserFortune(this, sols + this.getFortune());
RdDAudio.PlayContextAudio("argent"); // Petit son
ChatMessage.create({
await ChatMessage.create({
whisper: ChatUtility.getOwners(this),
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
})
@@ -527,7 +547,7 @@ export class RdDBaseActor extends Actor {
}
const chatAchatItem = foundry.utils.duplicate(achat.vente);
chatAchatItem.quantiteTotal = quantite;
ChatMessage.create({
await ChatMessage.create({
user: achat.userId,
speaker: { alias: (acheteur ?? vendeur).getAlias() },
whisper: ChatUtility.getOwners(this),
@@ -691,8 +711,8 @@ export class RdDBaseActor extends Actor {
}
}
}
await this.computeEncTotal()
}
await this.computeEncTotal()
return result;
}
@@ -872,18 +892,32 @@ export class RdDBaseActor extends Actor {
system: { description: this.system.description }
}
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-actor.hbs', chatData)
.then(html => ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
.then(async html => await ChatMessage.create(RdDUtility.chatDataSetup(html, modeOverride)));
}
actionImpossible(action) {
ui.notifications.info(`${this.getAlias()} ne peut pas faire cette action: ${action}`)
}
async doRollCaracCompetence(caracName, compName, diff, options = { title: "" }) {
}
ajoutExperience(rollData) { }
isAlcoolise() { return false }
async jetEthylisme() { this.actionImpossible("jet d'éthylisme") }
async rollAppelChance() { this.actionImpossible("appel à la chance") }
async jetDeMoral() { this.actionImpossible("jet de moral") }
async creerCopieLue(item) {
if (item.type !== ITEM_TYPES.livre) return
const existante = this.items.find(i => i.type === 'livre' && i.system.estCopieLue && i.name === item.name)
if (existante) return
const copie = item.toObject()
copie.system.estCopieLue = true
copie.system.lu = true
copie.system.quantite = 0
delete copie._id
await this.createEmbeddedDocuments('Item', [copie], { renderSheet: false })
}
async resetItemUse() { }
async incDecItemUse(itemId, shouldIncrease = true) { }
getItemUse(itemId) { return 0; }
@@ -892,11 +926,7 @@ export class RdDBaseActor extends Actor {
isActorCombat() { return false }
getCaracInit(competence) { return 0 }
listAttaques() {
return this.listActions({ isAttaque: true, isEquipe: false })
}
listActions({ isAttaque = false, isEquipe = false }) { return [] }
listActions() { return [] }
listActionsPossessions() {
return this.itemTypes[ITEM_TYPES.possession]
+3 -3
View File
@@ -15,13 +15,13 @@ export class RdDCreature extends RdDBaseActorSang {
}
async remiseANeuf() {
await this.removeEffects(e => true, { render: false })
await this.supprimerBlessures(it => true, { render: false })
await this.removeEffects(e => true)
await this.supprimerBlessures(it => true)
await this.update({
'system.sante.endurance.value': this.system.sante.endurance.max,
'system.sante.vie.value': this.system.sante.vie.max,
'system.sante.fatigue.value': 0
}, { render: true });
});
}
async finDeRoundBlessures() {
+2 -1
View File
@@ -18,6 +18,7 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
formData.niveau = this.actor.getNiveau()
delete formData.system.carac.niveau
formData.resonances = this.actor.system.sante.resonnance.actors.map(actorId => game.actors.get(actorId))
.filter(actor => actor != undefined)
.map(actor => { return { id: actor.id, name: actor.name, img: actor.img } })
return formData
}
@@ -75,6 +76,6 @@ export class RdDActorEntiteSheet extends RdDBaseActorReveSheet {
async resonanceDelete(actorId) {
console.log('Delete : ', actorId);
let newResonances = this.actor.system.sante.resonnance.actors.filter(id => id != actorId);
await this.actor.update({ 'system.sante.resonnance.actors': newResonances }, { renderSheet: false });
await this.actor.update({ 'system.sante.resonnance.actors': newResonances }, { render: false });
}
}
+2 -3
View File
@@ -43,9 +43,7 @@ export class RdDEntite extends RdDBaseActorReve {
async remiseANeuf() {
if (!this.isEntiteNonIncarnee()) {
await this.update({
'system.sante.endurance.value': this.system.sante.endurance.max
});
await this.update({ 'system.sante.endurance.value': this.system.sante.endurance.max })
}
await this.removeEffects(e => true)
}
@@ -85,6 +83,7 @@ export class RdDEntite extends RdDBaseActorReve {
if (this.isEntiteNonIncarnee()) {
return
}
encaissement.isEntiteIncarnee = true
const perteEndurance = await this.santeIncDec("endurance", -encaissement.endurance);
foundry.utils.mergeObject(encaissement, { resteEndurance: perteEndurance.newValue, endurance: perteEndurance.perte })
}
@@ -46,9 +46,9 @@ export class RdDActorExportSheet extends RdDActorSheet {
formData.export = this.getMappingValues(formData.context, this.actor)
formData.competences = this.getCompetences(CATEGORIES_COMPETENCES_BASE)
formData.draconic = this.getCompetences(CATEGORIES_DRACONIC)
const legeres = this.actor.nbBlessuresLegeres()
const graves = this.actor.nbBlessuresGraves()
const critiques = this.actor.nbBlessuresCritiques()
const legeres = this.actor.countBlessures(it => it.isLegere())
const graves = this.actor.countBlessures(it => it.isGrave())
const critiques = this.actor.countBlessures(it => it.isCritique())
formData.etat = {
surenc: this.actor.computeMalusSurEncombrement(),
fatigue: {
+115 -106
View File
@@ -5,25 +5,80 @@ import { RdDDice } from "../../rdd-dice.js";
import { RdDNameGen } from "../../rdd-namegen.js";
import { RdDTimestamp } from "../../time/rdd-timestamp.js";
const PATHS = [
'name',
'system.sexe',
'system.age',
'system.taille',
'system.poids',
'system.main',
'system.heure',
'system.cheveux',
'system.yeux'
]
const RANDOM_VALUES = {
'system.sexe': { 'masculin': 1, 'féminin': 1 },
'system.main': { 'droitier': 51, 'gaucher': 15, 'ambidextre': 6 },
'system.cheveux': { 'noirs': 2, 'bruns': 5, 'châtains': 3, 'châtain clair': 5, 'blonds': 4, 'blond platine': 1, 'roux carotte': 1, 'roux cuivré': 3, 'chauve': 1 },
'system.yeux': { 'noirs': 2, 'noisette': 3, 'brun-vert': 4, 'verts': 3, 'bleu clair': 3, 'bleu gris': 2, 'gris': 1, 'mauves': 1, 'indigos': 1 },
async function randomFrom(values) {
const max = Object.values(values).reduce(Misc.sum(), 0)
const total = await RdDDice.rollTotal(`1d${max}`)
let sum = 0
for (let entry of Object.entries(values)) {
sum = sum + entry[1]
if (sum >= total) {
return entry[0]
}
}
return Object.keys(values)[0]
}
async function randomTailleCm(taille) {
const infoTaille = RdDCarac.getCaracDerivee(taille)
const infoTailleSup = RdDCarac.getCaracDerivee(taille + 1)
const variation = (infoTailleSup.taille - infoTaille.taille) + Math.floor((infoTaille.poidsMax - infoTaille.poidsMin) / 2)
const base = infoTaille.taille
const total = await RdDDice.rollTotal(`1d${variation} -1d ${variation} + ${base}`)
const cm = total % 100
const dm = cm < 10 ? '0' : ''
const m = (total - cm) / 100
return `${m}m${dm}${cm}`
}
async function randomPoidsKg(taille) {
const infoTaille = RdDCarac.getCaracDerivee(taille)
const range = infoTaille.poidsMax - infoTaille.poidsMin + 1
const total = await RdDDice.rollTotal(`1d${range} + ${infoTaille.poidsMin}`)
return total + ' kg'
}
async function randomHeure() {
return RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "selfroll", showDice: SHOW_DICE })).key
}
const CONTROL_UNKNOWN = { name: 'unknown', path: '', getter: (act) => { undefined }, random: async act => undefined }
const TABLE_SEXES = { 'masculin': 1, 'féminin': 1 };
const TABLE_MAINS = { 'droitier': 51, 'gaucher': 15, 'ambidextre': 6 };
const TABLE_COULEURS_CHEVEUX = {
'noirs': 2,
'bruns': 5,
'châtains': 3,
'châtain clair': 5,
'blonds': 4,
'blond platine': 1,
'roux carotte': 1,
'roux cuivré': 3,
'chauve': 1
};
const TABLE_COULEURS_YEUX = {
'noirs': 2,
'noisette': 3,
'brun-vert': 4,
'verts': 3,
'bleu clair': 3,
'bleu gris': 2,
'gris': 1,
'mauves': 1,
'indigos': 1
};
const CONTROLS = [
{ name: 'name', path: 'name', getter: (act) => act.name, random: async act => await RdDNameGen.generate() },
{ name: 'sexe', path: 'system.sexe', getter: act => act.system.sexe, random: async act => await randomFrom(TABLE_SEXES) },
{ name: 'age', path: 'system.age', getter: act => act.system.age, random: async act => await RdDDice.rollTotal('(2d4kl)*10 + 1d7xo + 2d20kl') },
{ name: 'taille', path: 'system.taille', getter: act => act.system.taille, random: async act => await randomTailleCm(act.system.carac.taille.value) },
{ name: 'poids', path: 'system.poids', getter: act => act.system.poids, random: async act => await randomPoidsKg(act.system.carac.taille.value) },
{ name: 'main', path: 'system.main', getter: act => act.system.main, random: async act => await randomFrom(TABLE_MAINS) },
{ name: 'heure', path: 'system.heure', getter: act => act.system.heure, random: async act => await randomHeure() },
{ name: 'cheveux', path: 'system.cheveux', getter: act => act.system.cheveux, random: async act => await randomFrom(TABLE_COULEURS_CHEVEUX) },
{ name: 'yeux', path: 'system.yeux', getter: act => act.system.yeux, random: async act => await randomFrom(TABLE_COULEURS_YEUX) },
]
export class AppPersonnageAleatoire extends FormApplication {
static preloadHandlebars() {
foundry.applications.handlebars.loadTemplates([
@@ -47,18 +102,12 @@ export class AppPersonnageAleatoire extends FormApplication {
constructor(actor) {
super({})
this.actor = actor
this.current = foundry.utils.duplicate(actor)
this.checked = {
'name': false,
'system.sexe': (this.actor.system.sexe ?? '') == '',
'system.age': this.actor.system.age == 0,
'system.taille': (this.actor.system.taille ?? '') == '',
'system.poids': (this.actor.system.poids ?? '') == '',
'system.main': (this.actor.system.main ?? '') == '',
'system.heure': (this.actor.system.heure ?? '') == '',
'system.cheveux': (this.actor.system.cheveux ?? '') == '',
'system.yeux': (this.actor.system.yeux ?? '') == '',
}
this.current = AppPersonnageAleatoire.getActorValues()
this.checked = Object.fromEntries(CONTROLS.map(it => [it.name, [0, '', undefined].includes(it.getter(this.current))]))
}
static getActorValues() {
return Object.fromEntries(CONTROLS.map(it => [it.name, it.getter(this.actor)]));
}
async getData(options) {
@@ -73,124 +122,84 @@ export class AppPersonnageAleatoire extends FormApplication {
activateListeners(html) {
super.activateListeners(html)
this.html = html
this.html.find("button.button-cancel").click(async event => await this.close())
this.html.find("button.button-apply").click(async event => await this.onApply())
this.html.find("input.current-value").change(async event => await this.onChange(event))
this.html.find("div.random-field[data-path='system.heure'] select.current-value").change(async event => await this.onChange(event))
this.html.find('a[data-action="sexe-masculin"]').click(async event => await this.onSexe('masculin'))
this.html.find('a[data-action="sexe-feminin"]').click(async event => await this.onSexe('féminin'))
this.html.find("a.random").click(async event => await this.onRandom(event))
this.html.find("a.reset").click(async event => await this.onReset(event))
this.html.find("a.randomize-selected").click(async event => await this.onRandomizeSelected())
this.html.find("input.check-for-random").click(async event => await this.onCheckForRandom(event))
this.html.find("div.random-field[data-field-name='heure'] select.current-value").change(async event => await this.onChange(event))
this.html.find('a[data-action="sexe-masculin"]').click(async event => await this.onSexe('masculin'))
this.html.find('a[data-action="sexe-feminin"]').click(async event => await this.onSexe('féminin'))
this.html.find("button.button-cancel").click(async event => await this.close())
this.html.find("button.button-apply").click(async event => await this.onApply())
}
async _updateObject(event, formData) { }
async onApply() {
const updates = Object.fromEntries(
PATHS.filter(path => game.user.isGM || path != 'name')
.map(path => [path, this.current[path]])
CONTROLS.filter(control => game.user.isGM || control.name != 'name')
.map(control => [control.path, control.getter(this.current)])
)
await this.actor.update(updates)
await this.close()
}
getPath(selector) {
getName(selector) {
const fields = this.html.find(selector).parents("div.random-field:first")
return fields[0].attributes['data-path'].value
return fields[0].attributes['data-field-name'].value
}
getControl(name) {
return CONTROLS.find(it => it.name == name) ?? CONTROL_UNKNOWN
}
async onSexe(sexe) {
this.current['system.sexe'] = sexe
this.current['sexe'] = sexe
this.render()
}
async onChange(event) {
const path = this.getPath(event.currentTarget)
this.current[path] = event.currentTarget.value
const name = this.getName(event.currentTarget)
const control = this.getControl(name)
this.current[control.name] = event.currentTarget.value
this.render()
}
async onRandom(event) {
const path = this.getPath(event.currentTarget)
await this.setRandom(path);
const name = this.getName(event.currentTarget)
const control = this.getControl(name)
await this.randomControl(control)
this.render()
}
async onReset(event) {
const path = this.getPath(event.currentTarget)
this.current[path] = this.actor[path]
const name = this.getName(event.currentTarget)
const control = this.getControl(name)
this.current[control.name] = control.getter(this.actor)
await this.render()
}
async onCheckForRandom(event) {
const path = this.getPath(event.currentTarget)
this.checked[path] = event.currentTarget.checked
const name = this.getName(event.currentTarget)
this.checked[name] = event.currentTarget.checked
this.render()
}
async onRandomizeSelected() {
const paths = this.html.find("input.check-for-random:checked")
const controls = this.html.find("input.check-for-random:checked")
.parents("div.random-field")
.toArray()
.map(it => it.attributes['data-path'].value)
await Promise.all(paths.map(path => this.setRandom(path)))
.map(it => this.getControl(it.attributes['data-field-name'].value))
await Promise.all(controls.map(it => this.randomControl(it)))
this.render()
}
async setRandom(path) {
this.current[path] = await this.random(path);
async randomControl(control) {
this.current[control.name] = await control.random(this.current)
}
async random(path) {
switch (path) {
case 'name':
return await RdDNameGen.generate()
case 'system.sexe':
case 'system.main':
case 'system.cheveux':
case 'system.yeux':
return await this.randomFromMap(RANDOM_VALUES[path])
case 'system.poids':
return await this.randomPoids()
case 'system.taille':
return await this.randomTaille()
case 'system.age':
return await RdDDice.rollTotal('(2d4kl)*10 + 1d7xo + 2d20kl')
case 'system.heure':
return RdDTimestamp.defHeure(await RdDDice.rollHeure({ rollMode: "selfroll", showDice: SHOW_DICE })).key
}
return 'unknown'
}
async randomFromMap(valuesMap) {
const max = Object.values(valuesMap).reduce(Misc.sum(), 0)
const total = await RdDDice.rollTotal(`1d${max}`)
let sum = 0
for (let entry of Object.entries(valuesMap)) {
sum = sum + entry[1]
if (sum >= total) {
return entry[0]
}
}
return Object.keys(valuesMap)[0]
}
async randomPoids() {
const caracTaille = RdDCarac.getCaracDerivee(this.current.system.carac.taille.value)
const range = caracTaille.poidsMax - caracTaille.poidsMin + 1
const total = await RdDDice.rollTotal(`1d${range} + ${caracTaille.poidsMin}`)
return total + ' kg'
}
async randomTaille() {
const caracTaille = RdDCarac.getCaracDerivee(this.current.system.carac.taille.value)
const base = this.current.system.carac.taille.value * 2 + 60 + caracTaille.poidsMin
const variation = Math.floor((caracTaille.poidsMax - caracTaille.poidsMin + base / 5) / 2)
const total = await RdDDice.rollTotal(`2d${variation} + ${base}`)
const cm = total % 100
const dm = cm < 10 ? '0' : ''
const m = (total - cm) / 100
return `${m}m${dm}${cm}`
}
}
+2 -4
View File
@@ -16,7 +16,7 @@ export class RdDTextEditor {
$(html).on("click", '.roll-text', async event => await RdDTextEditor.rollText(event))
}
static async enrichHTML(text, object, options = {showlink:true}) {
static async enrichHTML(text, object, options = { showlink: true }) {
const context = {
text,
object,
@@ -70,9 +70,7 @@ export class RdDTextEditor {
options: { showLink: false }
},
param)
ChatMessage.create({
content: text
})
await ChatMessage.create({ content: text })
}
}
}
+19 -17
View File
@@ -92,48 +92,50 @@ export class ChatUtility {
}
/* -------------------------------------------- */
static async createChatWithRollMode(messageData, actor = undefined, rollMode = game.settings.get("core", "rollMode")) {
switch (rollMode) {
static adaptVisibility( messageData, options = { actor: undefined, rollMode: undefined }) {
foundry.utils.mergeObject(options, { rollMode: game.settings.get("core", "rollMode") }, { overwrite: false });
switch (options.rollMode) {
case "blindroll": // GM only
if (!game.user.isGM) {
ChatUtility.blindMessageToGM(messageData)
messageData.whisper = [game.user];
messageData.content = "Message envoyé en aveugle au Gardien"
messageData.whisper = [game.user]
messageData.content = "Message envoyé en aveugle au Gardien";
}
else {
messageData.whisper = ChatUtility.getGMs()
}
break
break;
case "gmroll":
messageData.whisper = actor ? ChatUtility.getOwners(actor) : ChatUtility.getUserAndGMs()
break
messageData.whisper = options.actor ? ChatUtility.getOwners(options.actor) : ChatUtility.getUserAndGMs()
break;
case "selfroll":
messageData.whisper = [game.user]
break
}
messageData.alias = messageData.alias ?? actor?.name ?? game.user.name
return await ChatMessage.create(messageData)
messageData.alias = messageData.alias ?? options.actor?.name ?? game.user.name
return messageData
}
static tellToUser(message) {
ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id] });
static async tellToUser(message) {
await ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id] });
}
static tellToGM(message) {
ChatMessage.create({
static async tellToGM(message) {
await ChatMessage.create({
user: game.user.id,
content: message,
whisper: ChatUtility.getGMs()
});
})
}
static tellToUserAndGM(message) {
ChatMessage.create({
static async tellToUserAndGM(message) {
await ChatMessage.create({
user: game.user.id,
content: message,
whisper: ChatUtility.getUserAndGMs()
})
}
static getOwners(document) {
return document ? game.users.filter(it => document.getUserLevel(it) == CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) : [game.user]
}
@@ -216,7 +218,7 @@ export class ChatUtility {
static async onRenderChatMessage(chatMessage, html, data) {
const rddTimestamp = chatMessage.getFlag(SYSTEM_RDD, 'rdd-timestamp')
const heureRdD = $(html).find('header.message-header .heure-rdd')
if (rddTimestamp && heureRdD.length==0) {
if (rddTimestamp && heureRdD.length == 0) {
const messageTimestamp = $(html).find('header.message-header .message-timestamp');
const timestamp = new RdDTimestamp(rddTimestamp);
const timestampData = timestamp.toCalendrier();
+24 -20
View File
@@ -71,28 +71,32 @@ export class RdDCoeur {
}
static async applyCoeurChateauDormant(actor, message) {
const newSuivants = foundry.utils.duplicate(actor.system.subacteurs.suivants)
let count = 0
newSuivants.forEach(async link => {
const suivant = game.actors.get(link.id)
const prochainCoeur = link.prochainCoeur ?? 0;
const coeurCourant = link.coeur ?? 0;
const diff = prochainCoeur - coeurCourant
if (diff < 0) {
await actor.moralIncDec(-4);
link.coeur = Math.max(0, coeurCourant - 1)
link.prochainCoeur = link.coeur
message.content += `<br>Votre c&oelig;ur brisé pour ${suivant.name} vous fait perdre 4 points de moral, il vous reste ${link.coeur} points de C&oelig;ur.`
count++
}
else if (diff > 0) {
link.coeur = Math.min(prochainCoeur, 4)
message.content += `<br>Votre c&oelig;ur bat fort, vous avez maintenant ${link.coeur} points de C&oelig;ur pour ${suivant.name}.`
link.prochainCoeur = link.coeur
count++
}
let ajustMoral = 0
const newSuivants = actor.system.subacteurs.suivants.filter(link => game.actors.get(link.id) != undefined)
.map(link => {
const suivant = game.actors.get(link.id)
const prochainCoeur = link.prochainCoeur ?? 0
const coeurCourant = link.coeur ?? 0
const diff = prochainCoeur - coeurCourant
if (diff < 0) {
ajustMoral -= 4
link.coeur = Math.max(0, coeurCourant - 1)
link.prochainCoeur = link.coeur
message.content += `<br>Votre c&oelig;ur brisé pour ${suivant.name} vous fait perdre 4 points de moral, il vous reste ${link.coeur} points de C&oelig;ur.`
count++
}
if (diff > 0) {
link.coeur = Math.min(prochainCoeur, 4)
message.content += `<br>Votre c&oelig;ur bat fort, vous avez maintenant ${link.coeur} points de C&oelig;ur pour ${suivant.name}.`
link.prochainCoeur = link.coeur
count++
}
return foundry.utils.duplicate(link)
})
if (ajustMoral != 0) {
await actor.moralIncDec(ajustMoral, 'Coeur')
}
)
if (count > 0) {
await actor.update({ 'system.subacteurs.suivants': newSuivants });
}
+1 -1
View File
@@ -48,7 +48,7 @@ export class Distance {
static isVisible(token, defenderToken) {
// TODO: regarder les StatusEffect aveuglé?
if (Distance.$isToken(token) && Distance.$isToken(defenderToken)) {
return canvas.effects.visibility.testVisibility(defenderToken.getCenterPoint(), { object: token })
return canvas.visibility.testVisibility(defenderToken.getCenterPoint(), { object: token })
}
return true
}
+18 -18
View File
@@ -7,7 +7,7 @@ import { TMRUtility } from "./tmr-utility.js";
export class DialogCreateSigneDraconique extends Dialog {
static async createSigneForActors() {
const signe = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
const signe = await RdDItemSigneDraconique.randomSigneDraconique({ ephemere: true });
let dialogData = {
signe: signe,
tmrs: TMRUtility.buildSelectionTypesTMR(signe.system.typesTMR),
@@ -36,25 +36,25 @@ export class DialogCreateSigneDraconique extends Dialog {
super(conf, options);
this.dialogData = dialogData;
}
async _onCreerSigneActeurs() {
await this.html.find("[name='signe.system.ephemere']").change();
await this.html.find(".signe-xp-sort").change();
this.validerSigne();
this.dialogData.actors.filter(it => it.selected)
.map(it => game.actors.get(it.id))
.forEach(actor => this._createSigneForActor(actor, this.dialogData.signe));
await this.html.find("[name='signe.system.ephemere']").change()
await this.html.find(".signe-xp-sort").change()
this.validerSigne()
await Promise.all(this.dialogData.actors.filter(it => it.selected)
.map(it => game.actors.get(it.id))
.map(async actor => await this._createSigneForActor(actor, this.dialogData.signe)))
}
async _createSigneForActor(actor, signe) {
actor.createEmbeddedDocuments("Item", [signe]);
ChatMessage.create({
await actor.createEmbeddedDocuments("Item", [signe]);
await ChatMessage.create({
whisper: ChatUtility.getOwners(actor),
content: await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.hbs", {
signe: signe,
alias: actor.getAlias()
})
});
})
}
validerSigne() {
@@ -67,7 +67,7 @@ export class DialogCreateSigneDraconique extends Dialog {
this.dialogData.signe.system.duree = this.html.find("[name='signe.system.duree']").val();
this.dialogData.signe.system.typesTMR = TMRUtility.buildListTypesTMRSelection(this.dialogData.tmrs);
}
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
@@ -81,7 +81,7 @@ export class DialogCreateSigneDraconique extends Dialog {
}
async setSigneAleatoire() {
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique({ ephemere: true });
this.html.find("[name='signe.name']").val(newSigne.name);
this.html.find("[name='signe.system.valeur.norm']").val(newSigne.system.valeur.norm);
@@ -90,9 +90,9 @@ export class DialogCreateSigneDraconique extends Dialog {
this.html.find("[name='signe.system.difficulte']").val(newSigne.system.difficulte);
this.html.find("[name='signe.system.duree']").val(newSigne.system.duree);
this.html.find("[name='signe.system.ephemere']").prop("checked", newSigne.system.ephemere);
this.dialogData.tmrs = TMRUtility.buildSelectionTypesTMR(newSigne.system.typesTMR);
this.dialogData.tmrs.forEach(t => {
this.html.find(`[data-tmr-name='${t.name}']`).prop( "checked", t.selected);
this.dialogData.tmrs = TMRUtility.buildSelectionTypesTMR(newSigne.system.typesTMR)
this.dialogData.tmrs.forEach(it => {
this.html.find(`[data-tmr-name='${it.name}']`).prop("checked", it.selected);
})
this.setEphemere(newSigne.system.ephemere);
}
@@ -113,7 +113,7 @@ export class DialogCreateSigneDraconique extends Dialog {
onSelectTmr(event) {
const tmrName = this.html.find(event.currentTarget)?.data("tmr-name");
const onTmr = this.dialogData.tmrs.find(it => it.name == tmrName);
if (onTmr){
if (onTmr) {
onTmr.selected = event.currentTarget.checked;
}
}
+112
View File
@@ -0,0 +1,112 @@
import { ITEM_TYPES } from "./constants.js"
import { RdDSheetUtility } from "./rdd-sheet-utility.js"
import { Monnaie } from "./item-monnaie.js"
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
export class DialogGererDeniers extends HandlebarsApplicationMixin(ApplicationV2) {
static DEFAULT_OPTIONS = {
tag: "form",
classes: ["dialog-gerer-deniers"],
form: {
submitOnChange: false,
closeOnSubmit: false
},
position: {
width: 700,
height: "auto"
},
window: {
title: "Gérer ses deniers",
icon: "fa-solid fa-coins"
}
}
static PARTS = {
form: { template: "systems/foundryvtt-reve-de-dragon/templates/actor/dialog-gerer-deniers.hbs" }
}
static async create(actor) {
const dialog = new DialogGererDeniers({ actor })
dialog.render(true)
}
constructor(options) {
super(options)
this.actor = options.actor
}
async _prepareContext() {
const monnaies = this.actor.itemTypes[ITEM_TYPES.monnaie] || []
const conteneurs = this.actor.itemTypes[ITEM_TYPES.conteneur] || []
const fortune = Monnaie.toSolsDeniers(this.actor.getFortune())
const monnaieData = monnaies.map(piece => ({
id: piece.id,
name: piece.name,
img: piece.img,
quantite: piece.system.quantite,
cout: piece.system.cout,
conteneurId: this.actor.findConteneur(piece)?.id || ""
}))
const conteneurOptions = [
{ id: "", name: "— Aucun —" },
...conteneurs.map(c => ({ id: c.id, name: c.name }))
]
return { monnaies: monnaieData, conteneurs: conteneurOptions, fortune }
}
async _onRender(context, options) {
this.element.querySelectorAll(".denier-moins").forEach(el => {
el.addEventListener("click", async event => {
const id = RdDSheetUtility.getItemId(event)
const piece = this.actor.items.get(id)
if (!piece) return
const q = Number(piece.system.quantite)
if (q <= 0) return
await piece.update({ "system.quantite": Math.max(0, q - 1) })
this.render(true)
})
})
this.element.querySelectorAll(".denier-plus").forEach(el => {
el.addEventListener("click", async event => {
const id = RdDSheetUtility.getItemId(event)
const piece = this.actor.items.get(id)
if (!piece) return
await piece.update({ "system.quantite": Number(piece.system.quantite) + 1 })
this.render(true)
})
})
this.element.querySelectorAll(".denier-edit").forEach(el => {
el.addEventListener("click", async event => {
const id = RdDSheetUtility.getItemId(event)
const piece = this.actor.items.get(id)
if (piece) piece.sheet.render(true)
})
})
this.element.querySelectorAll(".denier-conteneur").forEach(el => {
el.addEventListener("change", async event => {
const id = RdDSheetUtility.getItemId(event)
const newConteneurId = String(event.currentTarget.value)
const piece = this.actor.items.get(id)
if (!piece) return
const currentConteneur = this.actor.findConteneur(piece)
const newConteneur = newConteneurId ? this.actor.items.get(newConteneurId) : null
if (currentConteneur) {
await this.actor.enleverDeConteneur(piece, currentConteneur, () => {})
}
if (newConteneur) {
await this.actor.ajouterDansConteneur(piece, newConteneur, () => {})
}
})
})
}
}
+122
View File
@@ -0,0 +1,122 @@
import { ITEM_TYPES } from "./constants.js"
import { RdDSheetUtility } from "./rdd-sheet-utility.js"
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
export class DialogGererHerbes extends HandlebarsApplicationMixin(ApplicationV2) {
static DEFAULT_OPTIONS = {
tag: "form",
classes: ["dialog-gerer-herbes"],
form: {
submitOnChange: false,
closeOnSubmit: false
},
position: {
width: 650,
height: "auto"
},
window: {
title: "Gérer ses herbes",
icon: "fa-solid fa-leaf"
}
}
static PARTS = {
form: { template: "systems/foundryvtt-reve-de-dragon/templates/actor/dialog-gerer-herbes.hbs" }
}
static async create(actor) {
const dialog = new DialogGererHerbes({ actor })
dialog.render(true)
}
constructor(options) {
super(options)
this.actor = options.actor
}
async _prepareContext() {
const herbes = this.actor.itemTypes[ITEM_TYPES.herbe] || []
const conteneurs = this.actor.itemTypes[ITEM_TYPES.conteneur] || []
const herbeData = herbes.map(herbe => ({
id: herbe.id,
name: herbe.name,
img: herbe.img,
quantite: herbe.system.quantite,
categorie: herbe.system.categorie,
niveau: herbe.system.niveau,
isHerbeAPotion: herbe.isHerbeAPotion(),
conteneurId: this.actor.findConteneur(herbe)?.id || ""
}))
const conteneurOptions = [
{ id: "", name: "— Aucun —" },
...conteneurs.map(c => ({ id: c.id, name: c.name }))
]
return { herbes: herbeData, conteneurs: conteneurOptions }
}
async _onRender(context, options) {
this.element.querySelectorAll(".herbe-moins").forEach(el => {
el.addEventListener("click", async event => {
const id = RdDSheetUtility.getItemId(event)
const herbe = this.actor.items.get(id)
if (!herbe) return
const q = Number(herbe.system.quantite)
if (q <= 0) return
await herbe.update({ "system.quantite": Math.max(0, q - 1) })
this.render(true)
})
})
this.element.querySelectorAll(".herbe-plus").forEach(el => {
el.addEventListener("click", async event => {
const id = RdDSheetUtility.getItemId(event)
const herbe = this.actor.items.get(id)
if (!herbe) return
await herbe.update({ "system.quantite": Number(herbe.system.quantite) + 1 })
this.render(true)
})
})
this.element.querySelectorAll(".herbe-edit").forEach(el => {
el.addEventListener("click", async event => {
const herbeId = RdDSheetUtility.getItemId(event)
const herbe = this.actor.items.get(herbeId)
if (herbe) herbe.sheet.render(true)
})
})
this.element.querySelectorAll(".herbe-decoction").forEach(el => {
el.addEventListener("click", async event => {
const herbeId = RdDSheetUtility.getItemId(event)
const herbe = this.actor.items.get(herbeId)
if (herbe) this.actor.fabriquerDecoctionHerbe(herbe)
})
})
this.element.querySelectorAll(".herbe-conteneur").forEach(el => {
el.addEventListener("change", async event => {
const herbeId = RdDSheetUtility.getItemId(event)
const newConteneurId = String(event.currentTarget.value)
const herbe = this.actor.items.get(herbeId)
if (!herbe) return
const currentConteneur = this.actor.findConteneur(herbe)
const newConteneur = newConteneurId ? this.actor.items.get(newConteneurId) : null
if (currentConteneur) {
await this.actor.enleverDeConteneur(herbe, currentConteneur, () => {})
}
if (newConteneur) {
await this.actor.ajouterDansConteneur(herbe, newConteneur, () => {})
}
})
})
}
}
+110
View File
@@ -0,0 +1,110 @@
import { ITEM_TYPES } from "./constants.js"
import { RdDSheetUtility } from "./rdd-sheet-utility.js"
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
export class DialogGererIngredients extends HandlebarsApplicationMixin(ApplicationV2) {
static DEFAULT_OPTIONS = {
tag: "form",
classes: ["dialog-gerer-ingredients"],
form: {
submitOnChange: false,
closeOnSubmit: false
},
position: {
width: 650,
height: "auto"
},
window: {
title: "Gérer ses ingrédients",
icon: "fa-solid fa-flask"
}
}
static PARTS = {
form: { template: "systems/foundryvtt-reve-de-dragon/templates/actor/dialog-gerer-ingredients.hbs" }
}
static async create(actor) {
const dialog = new DialogGererIngredients({ actor })
dialog.render(true)
}
constructor(options) {
super(options)
this.actor = options.actor
}
async _prepareContext() {
const ingredients = this.actor.itemTypes[ITEM_TYPES.ingredient] || []
const conteneurs = this.actor.itemTypes[ITEM_TYPES.conteneur] || []
const ingredientData = ingredients.map(ing => ({
id: ing.id,
name: ing.name,
img: ing.img,
quantite: ing.system.quantite,
categorie: ing.system.categorie,
conteneurId: this.actor.findConteneur(ing)?.id || ""
}))
const conteneurOptions = [
{ id: "", name: "— Aucun —" },
...conteneurs.map(c => ({ id: c.id, name: c.name }))
]
return { ingredients: ingredientData, conteneurs: conteneurOptions }
}
async _onRender(context, options) {
this.element.querySelectorAll(".ingredient-moins").forEach(el => {
el.addEventListener("click", async event => {
const id = RdDSheetUtility.getItemId(event)
const ing = this.actor.items.get(id)
if (!ing) return
const q = Number(ing.system.quantite)
if (q <= 0) return
await ing.update({ "system.quantite": Math.max(0, q - 1) })
this.render(true)
})
})
this.element.querySelectorAll(".ingredient-plus").forEach(el => {
el.addEventListener("click", async event => {
const id = RdDSheetUtility.getItemId(event)
const ing = this.actor.items.get(id)
if (!ing) return
await ing.update({ "system.quantite": Number(ing.system.quantite) + 1 })
this.render(true)
})
})
this.element.querySelectorAll(".ingredient-edit").forEach(el => {
el.addEventListener("click", async event => {
const ingId = RdDSheetUtility.getItemId(event)
const ing = this.actor.items.get(ingId)
if (ing) ing.sheet.render(true)
})
})
this.element.querySelectorAll(".ingredient-conteneur").forEach(el => {
el.addEventListener("change", async event => {
const ingId = RdDSheetUtility.getItemId(event)
const newConteneurId = String(event.currentTarget.value)
const ing = this.actor.items.get(ingId)
if (!ing) return
const currentConteneur = this.actor.findConteneur(ing)
const newConteneur = newConteneurId ? this.actor.items.get(newConteneurId) : null
if (currentConteneur) {
await this.actor.enleverDeConteneur(ing, currentConteneur, () => {})
}
if (newConteneur) {
await this.actor.ajouterDansConteneur(ing, newConteneur, () => {})
}
})
})
}
}
+121
View File
@@ -0,0 +1,121 @@
import { ITEM_TYPES } from "./constants.js"
import { RdDSheetUtility } from "./rdd-sheet-utility.js"
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
export class DialogGererPotions extends HandlebarsApplicationMixin(ApplicationV2) {
static DEFAULT_OPTIONS = {
tag: "form",
classes: ["dialog-gerer-potions"],
form: {
submitOnChange: false,
closeOnSubmit: false
},
position: {
width: 700,
height: "auto"
},
window: {
title: "Gérer ses potions",
icon: "fa-solid fa-flask"
}
}
static PARTS = {
form: { template: "systems/foundryvtt-reve-de-dragon/templates/actor/dialog-gerer-potions.hbs" }
}
static async create(actor) {
const dialog = new DialogGererPotions({ actor })
dialog.render(true)
}
constructor(options) {
super(options)
this.actor = options.actor
}
async _prepareContext() {
const potions = this.actor.itemTypes[ITEM_TYPES.potion] || []
const conteneurs = this.actor.itemTypes[ITEM_TYPES.conteneur] || []
const potionData = potions.map(p => ({
id: p.id,
name: p.name,
img: p.img,
quantite: p.system.quantite,
categorie: p.system.categorie,
conteneurId: this.actor.findConteneur(p)?.id || ""
}))
const conteneurOptions = [
{ id: "", name: "— Aucun —" },
...conteneurs.map(c => ({ id: c.id, name: c.name }))
]
return { potions: potionData, conteneurs: conteneurOptions }
}
async _onRender(context, options) {
this.element.querySelectorAll(".potion-moins").forEach(el => {
el.addEventListener("click", async event => {
const id = RdDSheetUtility.getItemId(event)
const potion = this.actor.items.get(id)
if (!potion) return
const q = Number(potion.system.quantite)
if (q <= 0) return
await potion.update({ "system.quantite": Math.max(0, q - 1) })
this.render(true)
})
})
this.element.querySelectorAll(".potion-plus").forEach(el => {
el.addEventListener("click", async event => {
const id = RdDSheetUtility.getItemId(event)
const potion = this.actor.items.get(id)
if (!potion) return
await potion.update({ "system.quantite": Number(potion.system.quantite) + 1 })
this.render(true)
})
})
this.element.querySelectorAll(".potion-consommer").forEach(el => {
el.addEventListener("click", async event => {
const id = RdDSheetUtility.getItemId(event)
const potion = this.actor.items.get(id)
if (potion) {
await this.actor.consommerPotion(potion)
this.render(true)
}
})
})
this.element.querySelectorAll(".potion-edit").forEach(el => {
el.addEventListener("click", async event => {
const id = RdDSheetUtility.getItemId(event)
const potion = this.actor.items.get(id)
if (potion) potion.sheet.render(true)
})
})
this.element.querySelectorAll(".potion-conteneur").forEach(el => {
el.addEventListener("change", async event => {
const id = RdDSheetUtility.getItemId(event)
const newConteneurId = String(event.currentTarget.value)
const potion = this.actor.items.get(id)
if (!potion) return
const currentConteneur = this.actor.findConteneur(potion)
const newConteneur = newConteneurId ? this.actor.items.get(newConteneurId) : null
if (currentConteneur) {
await this.actor.enleverDeConteneur(potion, currentConteneur, () => {})
}
if (newConteneur) {
await this.actor.ajouterDansConteneur(potion, newConteneur, () => {})
}
})
})
}
}
+19
View File
@@ -0,0 +1,19 @@
export class RdDActiveEffect extends ActiveEffect {
async _preCreate(data, options, user) {
await this.parent?.delayedRenderSheet('_preCreateEffect', data, options)
return super._preCreate(data, options, user)
}
async _preUpdate(changed, options, user) {
await this.parent?.delayedRenderSheet('_preUpdateEffect', changed, options)
return super._preUpdate(changed, options, user)
}
async _preDelete(options, user) {
await this.parent?.delayedRenderSheet('_preDeleteEffect', { id: this.id }, options)
return super._preDelete(options, user)
}
}
+31 -1
View File
@@ -1,4 +1,4 @@
import { ChatUtility } from "./chat-utility.js";
import { Grammar } from "./grammar.js";
import { RdDInitiative } from "./initiative.mjs";
import { RdDItem } from "./item.js";
@@ -71,6 +71,36 @@ export class RdDItemCompetence extends RdDItem {
}
return undefined
}
async _preUpdate(changed, options, user) {
await this.checkCompetenceXP(changed.system?.xp)
return super._preUpdate(changed, options, user)
}
async checkCompetenceXP(newXP, display = true) {
if (this.actor?.isPersonnage() && newXP && newXP != this.system.xp && newXP > 0) {
const newNiv = this.system.niveau + 1
let needed = RdDItemCompetence.getCompetenceNextXp(newNiv)
if (newXP >= needed) {
const xpData = {
alias: this.actor.getAlias(),
competence: this.name,
niveau: newNiv,
xp: newXP,
archetype: this.system.niveau_archetype,
archetypeWarning: newNiv > this.system.niveau_archetype
}
if (display) {
await ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.hbs`, xpData)
})
}
return xpData
}
}
}
/* -------------------------------------------- */
static getLabelCategorie(category) {
return CATEGORIES_COMPETENCES[category].label;
+1 -1
View File
@@ -105,7 +105,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
descriptionmj: await RdDTextEditor.enrichHTML(this.item.system.descriptionmj, this.item),
isComestible: this.item.getUtilisationCuisine(),
options: RdDSheetUtility.mergeDocumentRights({}, this.item, this.isEditable),
competences: [new RdDItemCompetence(SANS_COMPETENCE), ...competences],
competences: [SANS_COMPETENCE, ...competences],
categories: RdDItem.getCategories(this.item.type),
isAppreciable: Apprecier.isAppreciable(this.item)
}
+17 -12
View File
@@ -70,20 +70,25 @@ export class RdDItemSort extends RdDItem {
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 getDraconicsSort(competencesDraconic, sort) {
// se baser sur la voie du sort?
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
case "lecture d'aura":
case "detection d'aura":
return competencesDraconic
case "annulation de magie":
return competencesDraconic.filter(it => !RdDItemCompetence.isThanatos(it))
function getVoies() {
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
case "lecture d'aura":
case "detection d'aura":
return competencesDraconic
case "annulation de magie":
return competencesDraconic.filter(it => !RdDItemCompetence.isThanatos(it))
default:
return sort.system.draconic.split('/').map(voie => RdDItemCompetence.getVoieDraconic(competencesDraconic, voie))
}
}
const voies = sort.system.draconic.split('/')
return voies.map(voie => RdDItemCompetence.getVoieDraconic(competencesDraconic, voie))
return getVoies()
.filter(it => it.system.niveau > -11)
.sort(Misc.descending(it => it.system.niveau))
}
static getBestDraconicSort(competencesDraconic, sort) {
return RdDItemSort.getDraconicsSort(competencesDraconic, sort).sort(Misc.descending(it => it.system.niveau)).find(it => true)
return RdDItemSort.getDraconicsSort(competencesDraconic, sort).find(it => true)
}
static getOrdreCode(code) {
@@ -153,10 +158,10 @@ export class RdDItemSort extends RdDItem {
}
/* -------------------------------------------- */
static incrementBonusCase(actor, sort, coord) {
static async incrementBonusCase(actor, sort, coord) {
let bonuscase = RdDItemSort.calculBonuscase(sort, coord)
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]);
await actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'system.bonuscase': bonuscase }]);
}
+31 -4
View File
@@ -79,12 +79,17 @@ export const defaultItemImg = {
sort: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
sortreserve: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp",
tache: "systems/foundryvtt-reve-de-dragon/assets/actions/tache.svg",
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
tete: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp",
monnaie: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
munition: "systems/foundryvtt-reve-de-dragon/icons/objets/fleche.webp"
}
const ITEM_TYPES_PLURIEL = {
[ITEM_TYPES.jeu]: 'jeux'
}
/* -------------------------------------------- */
export class RdDItem extends Item {
@@ -112,6 +117,13 @@ export class RdDItem extends Item {
return true;
}
static itemTypePluriel(type) {
if (ITEM_TYPES[type]) {
return ITEM_TYPES_PLURIEL[type] ?? (type + 's')
}
console.error(`Item type ${type} is undefined`)
return type
}
static async getCorrespondingItem(itemRef) {
if (itemRef.pack) {
return await SystemCompendiums.loadDocument(itemRef)
@@ -163,6 +175,21 @@ export class RdDItem extends Item {
super(docData, context);
}
async _preCreate(data, options, user) {
await this.parent?.delayedRenderSheet('_preCreateItem', data, options)
return super._preCreate(data, options, user)
}
async _preUpdate(changed, options, user) {
await this.parent?.delayedRenderSheet('_preUpdateItem', changed, options)
return super._preUpdate(changed, options, user)
}
async _preDelete(options, user) {
await this.parent?.delayedRenderSheet('_preDeleteItem', { id: this.id }, options)
return super._preDelete(options, user)
}
getUniteQuantite() {
switch (this.type) {
case ITEM_TYPES.monnaie: return "(Pièces)"
@@ -601,14 +628,14 @@ export class RdDItem extends Item {
system: { description: this.system.description },
properties: this.getProprietes(),
}
renderTemplate(this.getChatItemTemplate(), chatData).then(html => {
renderTemplate(this.getChatItemTemplate(), chatData).then(async html => {
let chatOptions = RdDUtility.chatDataSetup(html, modeOverride);
ChatMessage.create(chatOptions)
});
await ChatMessage.create(chatOptions)
})
}
getChatItemTemplate() {
return 'systems/foundryvtt-reve-de-dragon/templates/post-item.hbs';
return 'systems/foundryvtt-reve-de-dragon/templates/post-item.hbs'
}
static propertyIfDefined(name, val, condition = true) {
+3 -2
View File
@@ -6,7 +6,7 @@ import { RdDInitiative } from "../initiative.mjs";
import { MappingCreatureArme } from "./mapping-creature-arme.mjs";
import { Misc } from "../misc.js";
const nomCategorieParade = {
const categorie_parade = {
"sans-armes": "Sans arme",
"armes-naturelles": "Armes naturelles",
"hast": "Armes d'hast",
@@ -18,6 +18,7 @@ const nomCategorieParade = {
"epees-lourdes": "Epées lourdes",
"haches": "Haches",
"lances": "Lances",
"masses": "Masses",
}
export const ATTAQUE_TYPE = {
UNE_MAIN: '(1 main)',
@@ -122,7 +123,7 @@ export class RdDItemArme extends RdDItem {
/* -------------------------------------------- */
static getNomCategorieParade(arme) {
const categorie = arme?.system ? RdDItemArme.getCategorieParade(arme) : arme;
return nomCategorieParade[categorie];
return categorie_parade[categorie];
}
/* -------------------------------------------- */
+1 -1
View File
@@ -21,7 +21,7 @@ export class RdDItemArmure extends RdDItem {
if (deterioration >= 10) {
deterioration -= 10;
protection = this.calculProtectionDeterioree();
ChatMessage.create({ content: `Votre armure ${this.name} s'est détériorée, elle protège maintenant de ${protection}` });
await ChatMessage.create({ content: `Votre armure ${this.name} s'est détériorée, elle protège maintenant de ${protection}` });
}
await this.update({
'system.deterioration': deterioration,
+1 -1
View File
@@ -23,7 +23,7 @@ export const CATEGORIES_COMPETENCES_CREATURES = {
possession: { key: 'possession', base: 0, label: "Possession" },
}
export const POSSESSION_SANS_DRACONIC = {
export const SANS_DRACONIC = {
name: 'Sans draconic',
type: ITEM_TYPES.competence,
img: RDD_CONFIG.icons.possession,
+5 -7
View File
@@ -54,7 +54,7 @@ export class RdDItemBlessure extends RdDItem {
}
await this.createBlessure(actor, gravite)
ChatMessage.create({
await ChatMessage.create({
//TODO: hbs
content: `Blessure ${definition.label} appliquée à ${actor.name}<br>Perte d'endurance : ${lostEndurance} (${definition.endurance})<br>Perte de Vie : ${definition.vie}`,
whisper: ChatUtility.getOwners(actor)
@@ -106,11 +106,9 @@ export class RdDItemBlessure extends RdDItem {
async updateTacheSoinBlessure(tache) {
if (tache) {
await tache.update({
system: {
itemId: this.id,
difficulte: Math.min(this.system.difficulte, tache.system.difficulte),
points_de_tache_courant: Math.max(0, this.system.premierssoins.tache)
}
'system.itemId': this.id,
'system.difficulte': Math.min(this.system.difficulte, tache.system.difficulte),
'system.points_de_tache_courant': Math.max(0, this.system.premierssoins.tache)
});
}
}
@@ -162,7 +160,7 @@ export class RdDItemBlessure extends RdDItem {
message.content += ` -- une blessure ${label} reste stable`;
}
}
await this.update(update);
await this.update(update)
}
}
+26 -2
View File
@@ -28,6 +28,7 @@ const _MONTRER = {
}
const _SPLIT = {
code: 'item-split', label: 'Séparer le goupe', icon: 'fa-solid fa-unlink',
actorFilter: actor => actor.isOwner,
filter: it => Misc.toInt(it.system.quantite) > 1 && it.parent?.type != ACTOR_TYPES.commerce,
action: (item, actor) => RdDSheetUtility.splitItem(item, actor)
}
@@ -45,6 +46,7 @@ const _DELETE = {
}
const _EQUIPER = {
code: 'item-equip', label: 'Equiper', icon: it => it.system.equipe ? 'fa-solid fa-hand-rock' : 'fa-regular fa-hand-paper',
actorFilter: actor => actor.isPersonnage(),
filter: it => !it.estContenu && it.isEquipable(),
action: (item, actor) => actor.equiperObjet(item)
}
@@ -52,26 +54,31 @@ const _EQUIPER = {
const _CUISINER = {
code: 'item-cuisiner', label: 'Cuisiner',
img: 'systems/foundryvtt-reve-de-dragon/assets/actions/cuisine.svg',
actorFilter: actor => actor.isPersonnage(),
filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0,
action: (item, actor) => actor.preparerNourriture(item)
}
const _MANGER_CRU = {
code: 'item-manger-cru', label: 'Manger cru', icon: 'fa-solid fa-drumstick-bite',
actorFilter: actor => actor.isPersonnage(),
filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0,
action: (item, actor) => actor.mangerNourriture(item)
}
const _MANGER = {
code: 'item-manger', label: 'Manger', icon: 'fa-solid fa-utensils',
actorFilter: actor => actor.isPersonnage(),
filter: it => !(it.system.boisson),
action: (item, actor) => actor.mangerNourriture(item)
}
const _BOIRE = {
code: 'item-boire', label: 'Boire', icon: 'fa-solid fa-glass-water',
actorFilter: actor => actor.isPersonnage(),
filter: it => it.system.boisson,
action: (item, actor) => actor.mangerNourriture(item)
}
const _DECOCTION = {
code: 'item-decoction', label: 'Décoction', icon: 'fa-solid fa-flask-vial',
actorFilter: actor => actor.isPersonnage(),
action: (item, actor) => actor.fabriquerDecoctionHerbe(item)
}
@@ -82,30 +89,46 @@ const _OUVRIR = {
}
const _LIRE = {
code: 'item-lire', label: 'Lire', icon: 'fa-solid fa-book-open',
actorFilter: actor => actor.isPersonnage(),
action: (item, actor) => actor.actionLire(item)
}
const _MARQUER_LU = {
code: 'item-marquer-lu', label: 'Marquer comme lu',
icon: it => it.system.lu ? 'fa-solid fa-book-open' : 'fa-regular fa-book',
actorFilter: actor => actor.isPersonnage(),
action: async (item, actor) => { await actor.creerCopieLue(item) }
}
const _REFOULER = {
code: 'item-refouler', label: 'Refouler', icon: 'fa-solid fa-burst',
actorFilter: actor => actor.isPersonnage(),
filter: it => it.system.refoulement > 0,
action: (item, actor) => actor.actionRefoulement(item)
}
const _SORT_RESERVE = {
code: 'item-sortreserve-add', label: 'Ajouter en réserve', icon: 'fa-solid fa-sparkles',
actorFilter: actor => actor.isPersonnage(),
filter: it => game.user.isGM && !it.system.isrituel,
action: (item, actor) => actor.addSortReserve(item)
}
const _VIDER = {
code: 'item-vider', label: 'Vider le conteneur', icon: 'fa-solid fa-box-open',
filter: it => it.isConteneur() && (it.system.contenu?.length > 0),
actorFilter: actor => actor.isOwner,
action: (item, actor) => item.update({ 'system.contenu': [] })
}
export const COMMON_ACTIONS = [_EQUIPER]
export const DEFAULT_ACTIONS = [_ACHETER, _SPLIT, _SPACEHOLDER, _VENDRE, _MONTRER, _EDIT, _DELETE]
export const ITEM_ACTIONS = {
faune: [_CUISINER, _MANGER_CRU],
ingredient: [_CUISINER, _MANGER_CRU],
conteneur: [_OUVRIR],
conteneur: [_VIDER, _OUVRIR],
herbe: [_DECOCTION, _CUISINER, _MANGER_CRU],
livre: [_LIRE],
livre: [_LIRE, _MARQUER_LU],
nourritureboisson: [_MANGER, _BOIRE],
ombre: [_REFOULER],
plante: [_CUISINER, _MANGER_CRU],
@@ -118,6 +141,7 @@ export class ItemAction {
static applies(action, item, options) {
return action && item
&& item.isActionAllowed(action.code)
&& (!action.actorFilter || (item.actor && action.actorFilter(item.actor)))
&& (!action.filter || action.filter(item))
&& (action.allowLimited || options.editable)
&& (!action.optionsFilter || action.optionsFilter(options))
+1 -1
View File
@@ -22,7 +22,7 @@ export class RdDItemMaladie extends RdDItem {
const souffrance = mal.system.identifie
? `de ${mal.name}`
: `d'un mal inconnu`
ChatMessage.create({
await ChatMessage.create({
whisper: ChatUtility.getOwners(mal.actor),
content: `${mal.actor.name} souffre ${souffrance} (${Misc.typeName('Item', mal.type)}): vérifiez que les effets ne se sont pas aggravés !`
})
+6 -4
View File
@@ -3,6 +3,8 @@ import { RdDItem } from "../item.js";
import { Misc } from "../misc.js";
import { LIST_CARAC_PERSONNAGE, RdDCarac } from "../rdd-carac.js";
const _warn = msg => ui.notifications?.warn(msg)
export class RdDItemRace extends RdDItem {
static get ITEM_TYPE() { return ITEM_TYPES.race }
@@ -15,14 +17,14 @@ export class RdDItemRace extends RdDItem {
const race = RdDItemRace.getRace(actor)
if (code == LIST_CARAC_PERSONNAGE.force.code) {
if (!race.isForceValid(actor, value)) {
ui.notifications.warn(race.system.carac.force.limitmessage)
_warn(race.system.carac.force.limitmessage)
return false
}
}
if (code == LIST_CARAC_PERSONNAGE.taille.code) {
const carac = RdDCarac.carac(code)
if (race.isMax(actor, code, value - 1)) {
ui.notifications.warn(`${value} est supérieure au maximum de ${carac.label}`)
_warn(`${value} est supérieure au maximum de ${carac.label}`)
return false
}
}
@@ -73,13 +75,13 @@ export class RdDItemRace extends RdDItem {
getValidTaille(taille) {
const min = Math.max(this.system.carac.taille.min, 0)
if (min > taille) {
ui.notifications.warn("La Taille est inférieur au minimum racial")
_warn("La Taille est inférieur au minimum racial")
return min
}
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")
_warn("La Taille est supérieure au maximum racial")
return max
}
return taille
+15 -15
View File
@@ -77,41 +77,41 @@ export class RdDInventaireItemSheet extends RdDItemSheetV1 {
}
async onAddMilieu(event) {
const milieu = this.html.find('input.input-selection-milieu').val();
const milieu = this.html.find('input.input-selection-milieu').val()
if (!milieu) {
ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${this.item.name}`);
ui.notifications.warn(`Choisissez le milieu dans lequel se trouve le/la ${this.item.name}`)
return
}
const list = this.item.getEnvironnements();
const exists = list.find(it => it.milieu == milieu);
const list = this.item.getEnvironnements()
const exists = list.find(it => it.milieu == milieu)
if (exists) {
ui.notifications.warn(`${this.item.name} a déjà une rareté ${exists.rarete} en ${milieu} (fréquence: ${exists.frequence})`);
return
}
const rarete = RdDRaretes.rareteFrequente();
const added = { milieu, rarete: rarete.code, frequence: rarete.frequence };
const rarete = RdDRaretes.rareteFrequente()
const added = { milieu, rarete: rarete.code, frequence: rarete.frequence }
const newList = [added, ...list].sort(Misc.ascending(it => it.milieu))
await this.item.update({ 'system.environnement': newList })
}
async onDeleteMilieu(event) {
const milieu = this.$getEventMilieu(event);
const milieu = this.$getEventMilieu(event)
if (milieu != undefined) {
const newList = this.item.getEnvironnements().filter(it => it.milieu != milieu)
.sort(Misc.ascending(it => it.milieu));
await this.item.update({ 'system.environnement': newList });
.sort(Misc.ascending(it => it.milieu))
await this.item.update({ 'system.environnement': newList })
}
}
async onChange(event, doMutation) {
const list = this.item.system.environnement;
const milieu = this.$getEventMilieu(event);
const updated = list.find(it => it.milieu == milieu);
const list = this.item.system.environnement
const milieu = this.$getEventMilieu(event)
const updated = list.find(it => it.milieu == milieu)
if (updated) {
doMutation(updated);
doMutation(updated)
const newList = [...list.filter(it => it.milieu != milieu), updated]
.sort(Misc.ascending(it => it.milieu));
await this.item.update({ 'system.environnement': newList });
.sort(Misc.ascending(it => it.milieu))
await this.item.update({ 'system.environnement': newList })
}
}
+2 -2
View File
@@ -20,7 +20,7 @@ export class RdDFauneItemSheet extends RdDInventaireItemSheet {
'system.actor.pack': linkedActor.pack,
'system.actor.id': linkedActor._id,
'system.actor.name': linkedActor.name
});
})
}
else {
ui.notifications.warn(`${linkedActor.name} ne provient pas d'un compendium.
@@ -32,7 +32,7 @@ export class RdDFauneItemSheet extends RdDInventaireItemSheet {
'system.actor.pack': '',
'system.actor.id': '',
'system.actor.name': ''
});
})
}
}
+3 -3
View File
@@ -24,9 +24,9 @@ export class RdDSigneDraconiqueItemSheet extends RdDItemSheetV1 {
/* -------------------------------------------- */
async getData() {
const formData = await super.getData();
this.tmrs = TMRUtility.buildSelectionTypesTMR(this.item.system.typesTMR);
formData.tmrs = this.tmrs;
return formData;
this.tmrs = TMRUtility.buildSelectionTypesTMR(this.item.system.typesTMR)
formData.tmrs = this.tmrs
return formData
}
/* -------------------------------------------- */
+33
View File
@@ -0,0 +1,33 @@
import { ITEM_TYPES } from "../constants.js";
// import { RdDItemTache } from "tache.js";
import { RdDItemSheetV1 } from "../item-sheet.js";
export class RdDTacheItemSheet extends RdDItemSheetV1 {
static get ITEM_TYPE() { return ITEM_TYPES.tache };
async getData() {
const formData = await super.getData()
if (this.item.system.tacheCommuneId) {
formData.tacheCommune = game.items.get(this.item.system.tacheCommuneId);
formData.system = formData.tacheCommune.system
formData.disabled = this.item.actor != undefined
}
return formData
}
activateListeners(html) {
super.activateListeners(html);
this.html.find('input[name="is-tache-partagee"]').click((event) => this.checktacheCommune(event.currentTarget.checked))
}
async checktacheCommune(checked) {
if (!this.item.parent) {
const tacheCommuneId = checked ? this.item.id : ""
this.item.update({ 'system.tacheCommuneId': tacheCommuneId })
}
}
}
+17
View File
@@ -0,0 +1,17 @@
import { RdDItem } from "../item.js";
export class RdDItemTache extends RdDItem {
static get defaultIcon() {
return "systems/foundryvtt-reve-de-dragon/assets/actions/tache.svg"
}
isTacheCommune() {
return this.system.tacheCommuneId != ""
}
getTacheOuCommune() {
if (this.isTacheCommune()) {
return game.items.get(this.system.tacheCommuneId)
}
return this
}
}
+25 -30
View File
@@ -16,22 +16,18 @@ class Migration {
async migrate() { }
async applyItemsUpdates(computeUpdates) {
await game.actors.forEach(async (actor) => {
await Promise.all(game.actors.map(actor => {
const actorItemUpdates = computeUpdates(actor.items).filter(it => it != undefined);
if (actorItemUpdates.length > 0) {
console.log(
this.code,
`Applying updates on actor ${actor.name} items`,
actorItemUpdates
);
await actor.updateEmbeddedDocuments("Item", actorItemUpdates);
console.log(this.code, `Applying updates on actor ${actor.name} items`, actorItemUpdates);
return actor.updateEmbeddedDocuments("Item", actorItemUpdates);
}
});
}))
const itemUpdates = computeUpdates(game.items).filter(it => it != undefined);
const itemUpdates = computeUpdates(game.items).filter(it => it != undefined)
if (itemUpdates.length > 0) {
console.log(this.code, "Applying updates on items", itemUpdates);
await Item.updateDocuments(itemUpdates);
console.log(this.code, "Applying updates on items", itemUpdates)
await Item.updateDocuments(itemUpdates)
}
}
}
@@ -58,13 +54,13 @@ class _1_5_34_migrationPngWebp {
//Migrate system png to webp
await Item.updateDocuments(itemsUpdates);
await Actor.updateDocuments(actorsUpdates);
game.actors.forEach(actor => {
if (actor.token?.img && actor.token.img.match(regexOldPngJpg)) {
actor.update({ "token.img": convertImgToWebp(actor.token.img) });
}
const actorItemsToUpdate = prepareDocumentsImgUpdate(actor.items);
actor.updateEmbeddedDocuments('Item', actorItemsToUpdate);
});
await Promise.all(game.actors
.filter(actor => actor.token?.img && actor.token.img.match(regexOldPngJpg))
.map(actor => actor.update({ "token.img": convertImgToWebp(actor.token.img) }))
)
await Promise.all(game.actors.map(actor =>
actor.updateEmbeddedDocuments('Item', prepareDocumentsImgUpdate(actor.items))
))
}
}
@@ -125,16 +121,15 @@ class _10_0_21_VehiculeStructureResistanceMax extends Migration {
get version() { return "10.0.21"; }
async migrate() {
await game.actors
.filter((actor) => actor.type == "vehicule")
.forEach(async (actor) => {
await actor.update({
await Promise.all(
game.actors.filter(actor => actor.type == "vehicule")
.map(actor => actor.update({
'system.etat.resistance.value': actor.system.resistance,
'system.etat.resistance.max': actor.system.resistance,
'system.etat.structure.value': actor.system.structure,
'system.etat.structure.max': actor.system.structure
})
});
}))
)
}
}
@@ -192,9 +187,9 @@ class _10_2_5_ArmesTirLancer extends Migration {
get version() { return "10.2.5"; }
migrateArmeTirLancer(it) {
let updates = foundry.utils.mergeObject({ _id: it.id }, this.getMapping(it).updates);
console.log(it.name, updates);
return updates;
const updates = foundry.utils.mergeObject({ _id: it.id }, this.getMapping(it).updates)
console.log(it.name, updates)
return updates
}
async migrate() {
@@ -359,7 +354,7 @@ class _10_4_6_ServicesEnCommerces extends Migration {
}
async transformInventaireCommerce(service) {
const serviceItems = (service.system.items ?? []);
const commerceItems = await Promise.all(serviceItems.map(async (it) => { return await this.transformToItemBoutique(it); }));
const commerceItems = await Promise.all(serviceItems.map((it) => this.transformToItemBoutique(it)))
return commerceItems.concat(Monnaie.monnaiesStandard());
}
@@ -439,7 +434,7 @@ class _10_7_0_MigrationBlessures extends Migration {
'system.blessures.graves.liste': [],
'system.blessures.critiques.liste': []
})
}));
}))
}
creerBlessure(gravite, graviteTexte, blessure, timestamp) {
const dateBlessure = timestamp.addJours(-blessure.jours);
@@ -791,6 +786,6 @@ export class Migrations {
}
compareVersions(a, b) {
return isNewerVersion(a.version, b.version) ? 1 : isNewerVersion(b.version, a.version) ? -1 : 0;
return foundry.utils.isNewerVersion(a.version, b.version) ? 1 : foundry.utils.isNewerVersion(b.version, a.version) ? -1 : 0;
}
}
+22 -1
View File
@@ -24,6 +24,12 @@ export class Misc {
return text.charAt(0).toLowerCase() + text.slice(1);
}
static stripHtml(html) {
const tmp = document.createElement("DIV")
tmp.innerHTML = html
return tmp.textContent || tmp.innerText || ""
}
static toSignedString(number) {
const value = parseInt(number)
const isPositiveNumber = value != NaN && value > 0;
@@ -225,7 +231,7 @@ export class Misc {
*/
static documentIfResponsible(document) {
if (Misc.isFirstConnectedGM() || (Misc.connectedGMs().length == 0 && Misc.isFirstOwnerPlayer(document))) {
if (document.isOwner) {
if (document?.isOwner) {
return document
}
}
@@ -322,4 +328,19 @@ export class Misc {
'-o-transform': rotation
};
}
static async random(count) {
const roll = new Roll(`1d${count}`)
await roll.evaluate()
return roll.total
}
static shuffled(source) {
const result = source.slice(0)
for (let i = result.length - 1; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
[result[i], result[j]] = [result[j], result[i]];
}
return result
}
}
+3 -5
View File
@@ -4,9 +4,8 @@ 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 { DIFF, ROLL_TYPE_COMP } 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",
@@ -134,7 +133,7 @@ export class Apprecier {
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 },
type: { allowed: [ROLL_TYPE_COMP], current: ROLL_TYPE_COMP, appreciation: true },
selected: {
carac: { key: this.appreciation.carac, forced: true },
comp: { key: competence, forced: true },
@@ -168,7 +167,7 @@ export class Apprecier {
async rollMoral(moral = undefined) {
if (this.raisons.length > 0) {
ChatMessage.create({
await ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor),
content: 'Pas de jet de moral:' + Misc.concat(this.raisons.map(r => `<br> - ${r}`))
})
@@ -176,7 +175,6 @@ export class Apprecier {
}
moral = moral ?? this.appreciation.moral
// TODO: jet de moral
await this.actor.jetDeMoral(moral, this.appreciation.bonmoment)
}
}
+32 -32
View File
@@ -3,38 +3,38 @@ import { Misc } from "./misc.js";
const TABLE_CARACTERISTIQUES_DERIVEES = {
// xp: coût pour passer du niveau inférieur à ce niveau
1: { xp: 3, niveau: -5, poids: "moins de 1kg", poidsMin: 0, poidsMax: 1, plusdom: -5, sconst: 0.5, sust: 0.1 },
2: { xp: 3, niveau: -4, poids: "1-5", poidsMin: 1, poidsMax: 5, plusdom: -4, sconst: 0.5, sust: 0.3 },
3: { xp: 4, niveau: -3, poids: "6-10", poidsMin: 6, poidsMax: 10, plusdom: -3, sconst: 1, sust: 0.5, beaute: 'hideux' },
4: { xp: 4, niveau: -2, poids: "11-20", poidsMin: 11, poidsMax: 20, plusdom: -3, sconst: 1, sust: 1, beaute: 'repoussant' },
5: { xp: 5, niveau: -1, poids: "21-30", poidsMin: 21, poidsMax: 30, plusdom: -2, sconst: 1, sust: 1, beaute: 'franchement très laid' },
6: { xp: 5, niveau: 0, poids: "31-40", poidsMin: 31, poidsMax: 40, plusdom: -1, sconst: 2, sust: 2, beaute: 'laid' },
7: { xp: 6, niveau: 0, poids: "41-50", poidsMin: 41, poidsMax: 50, plusdom: -1, sconst: 2, sust: 2, beaute: 'très désavantagé' },
8: { xp: 6, niveau: 0, poids: "51-60", poidsMin: 51, poidsMax: 60, plusdom: 0, sconst: 2, sust: 2, beaute: 'désavantagé' },
9: { xp: 7, niveau: 0, poids: "61-65", poidsMin: 61, poidsMax: 65, plusdom: 0, sconst: 3, sust: 2, beaute: 'pas terrible' },
10: { xp: 7, niveau: 0, poids: "66-70", poidsMin: 66, poidsMax: 70, plusdom: 0, sconst: 3, sust: 3, beaute: 'commun' },
11: { xp: 8, niveau: 1, poids: "71-75", poidsMin: 71, poidsMax: 75, plusdom: 0, sconst: 3, sust: 3, beaute: 'pas mal' },
12: { xp: 8, niveau: 1, poids: "76-80", poidsMin: 76, poidsMax: 80, plusdom: +1, sconst: 4, sust: 3, beaute: 'avantagé' },
13: { xp: 9, niveau: 2, poids: "81-90", poidsMin: 81, poidsMax: 90, plusdom: +1, sconst: 4, sust: 3, beaute: 'mignon' },
14: { xp: 9, niveau: 2, poids: "91-100", poidsMin: 91, poidsMax: 100, plusdom: +2, sconst: 4, sust: 4, beaute: 'beau' },
15: { xp: 10, niveau: 3, poids: "101-110", poidsMin: 101, poidsMax: 110, plusdom: +2, sconst: 5, sust: 4, beaute: 'très beau' },
16: { xp: 20, niveau: 3, poids: "111-120", poidsMin: 111, poidsMax: 120, plusdom: +3, sconst: 5, sust: 4, beaute: 'éblouissant' },
17: { xp: 30, niveau: 4, poids: "121-131", poidsMin: 121, poidsMax: 131, plusdom: +3, sconst: 5, sust: 5 },
18: { xp: 40, niveau: 4, poids: "131-141", poidsMin: 131, poidsMax: 141, plusdom: +4, sconst: 6, sust: 5 },
19: { xp: 50, niveau: 5, poids: "141-150", poidsMin: 141, poidsMax: 150, plusdom: +4, sconst: 6, sust: 5 },
20: { xp: 60, niveau: 5, poids: "151-160", poidsMin: 151, poidsMax: 160, plusdom: +4, sconst: 6, sust: 6 },
21: { xp: 70, niveau: 6, poids: "161-180", poidsMin: 161, poidsMax: 180, plusdom: +5, sconst: 7, sust: 6 },
22: { xp: 80, niveau: 6, poids: "181-200", poidsMin: 181, poidsMax: 200, plusdom: +5, sconst: 7, sust: 7 },
23: { xp: 90, niveau: 7, poids: "201-300", poidsMin: 201, poidsMax: 300, plusdom: +6, sconst: 7, sust: 8 },
24: { xp: 100, niveau: 7, poids: "301-400", poidsMin: 301, poidsMax: 400, plusdom: +6, sconst: 8, sust: 9 },
25: { xp: 110, niveau: 8, poids: "401-500", poidsMin: 401, poidsMax: 500, plusdom: +7, sconst: 8, sust: 10 },
26: { xp: 120, niveau: 8, poids: "501-600", poidsMin: 501, poidsMax: 600, plusdom: +7, sconst: 8, sust: 11 },
27: { xp: 130, niveau: 9, poids: "601-700", poidsMin: 601, poidsMax: 700, plusdom: +8, sconst: 9, sust: 12 },
28: { xp: 140, niveau: 9, poids: "701-800", poidsMin: 701, poidsMax: 800, plusdom: +8, sconst: 9, sust: 13 },
29: { xp: 150, niveau: 10, poids: "801-900", poidsMin: 801, poidsMax: 900, plusdom: +9, sconst: 9, sust: 14 },
30: { xp: 160, niveau: 10, poids: "901-1000", poidsMin: 901, poidsMax: 1000, plusdom: +9, sconst: 10, sust: 15 },
31: { xp: 170, niveau: 11, poids: "1001-1500", poidsMin: 1001, poidsMax: 1500, plusdom: +10, sconst: 10, sust: 16 },
32: { xp: 180, niveau: 11, poids: "1501-2000", poidsMin: 1501, poidsMax: 2000, plusdom: +11, sconst: 10, sust: 17 }
1: { xp: 3, niveau: -5, taille: 40, poids: "moins de 1kg", poidsMin: 0, poidsMax: 1, plusdom: -5, sconst: 0.5, sust: 0.1 },
2: { xp: 3, niveau: -4, taille: 70, poids: "1-5", poidsMin: 1, poidsMax: 5, plusdom: -4, sconst: 0.5, sust: 0.3 },
3: { xp: 4, niveau: -3, taille: 100, poids: "6-10", poidsMin: 6, poidsMax: 10, plusdom: -3, sconst: 1, sust: 0.5, beaute: 'hideux' },
4: { xp: 4, niveau: -2, taille: 120, poids: "11-20", poidsMin: 11, poidsMax: 20, plusdom: -3, sconst: 1, sust: 1, beaute: 'repoussant' },
5: { xp: 5, niveau: -1, taille: 135, poids: "21-30", poidsMin: 21, poidsMax: 30, plusdom: -2, sconst: 1, sust: 1, beaute: 'franchement très laid' },
6: { xp: 5, niveau: 0, taille: 145, poids: "31-40", poidsMin: 31, poidsMax: 40, plusdom: -1, sconst: 2, sust: 2, beaute: 'laid' },
7: { xp: 6, niveau: 0, taille: 150, poids: "41-50", poidsMin: 41, poidsMax: 50, plusdom: -1, sconst: 2, sust: 2, beaute: 'très désavantagé' },
8: { xp: 6, niveau: 0, taille: 155, poids: "51-60", poidsMin: 51, poidsMax: 60, plusdom: 0, sconst: 2, sust: 2, beaute: 'désavantagé' },
9: { xp: 7, niveau: 0, taille: 160, poids: "61-65", poidsMin: 61, poidsMax: 65, plusdom: 0, sconst: 3, sust: 2, beaute: 'pas terrible' },
10: { xp: 7, niveau: 0, taille: 170, poids: "66-70", poidsMin: 66, poidsMax: 70, plusdom: 0, sconst: 3, sust: 3, beaute: 'commun' },
11: { xp: 8, niveau: 1, taille: 175, poids: "71-75", poidsMin: 71, poidsMax: 75, plusdom: 0, sconst: 3, sust: 3, beaute: 'pas mal' },
12: { xp: 8, niveau: 1, taille: 180, poids: "76-80", poidsMin: 76, poidsMax: 80, plusdom: +1, sconst: 4, sust: 3, beaute: 'avantagé' },
13: { xp: 9, niveau: 2, taille: 185, poids: "81-90", poidsMin: 81, poidsMax: 90, plusdom: +1, sconst: 4, sust: 3, beaute: 'mignon' },
14: { xp: 9, niveau: 2, taille: 190, poids: "91-100", poidsMin: 91, poidsMax: 100, plusdom: +2, sconst: 4, sust: 4, beaute: 'beau' },
15: { xp: 10, niveau: 3, taille: 200, poids: "101-110", poidsMin: 101, poidsMax: 110, plusdom: +2, sconst: 5, sust: 4, beaute: 'très beau' },
16: { xp: 20, niveau: 3, taille: 210, poids: "111-120", poidsMin: 111, poidsMax: 120, plusdom: +3, sconst: 5, sust: 4, beaute: 'éblouissant' },
17: { xp: 30, niveau: 4, taille: 220, poids: "121-131", poidsMin: 121, poidsMax: 131, plusdom: +3, sconst: 5, sust: 5 },
18: { xp: 40, niveau: 4, taille: 230, poids: "131-141", poidsMin: 131, poidsMax: 141, plusdom: +4, sconst: 6, sust: 5 },
19: { xp: 50, niveau: 5, taille: 240, poids: "141-150", poidsMin: 141, poidsMax: 150, plusdom: +4, sconst: 6, sust: 5 },
20: { xp: 60, niveau: 5, taille: 250, poids: "151-160", poidsMin: 151, poidsMax: 160, plusdom: +4, sconst: 6, sust: 6 },
21: { xp: 70, niveau: 6, taille: 260, poids: "161-180", poidsMin: 161, poidsMax: 180, plusdom: +5, sconst: 7, sust: 6 },
22: { xp: 80, niveau: 6, taille: 270, poids: "181-200", poidsMin: 181, poidsMax: 200, plusdom: +5, sconst: 7, sust: 7 },
23: { xp: 90, niveau: 7, taille: 280, poids: "201-300", poidsMin: 201, poidsMax: 300, plusdom: +6, sconst: 7, sust: 8 },
24: { xp: 100, niveau: 7, taille: 290, poids: "301-400", poidsMin: 301, poidsMax: 400, plusdom: +6, sconst: 8, sust: 9 },
25: { xp: 110, niveau: 8, taille: 300, poids: "401-500", poidsMin: 401, poidsMax: 500, plusdom: +7, sconst: 8, sust: 10 },
26: { xp: 120, niveau: 8, taille: 310, poids: "501-600", poidsMin: 501, poidsMax: 600, plusdom: +7, sconst: 8, sust: 11 },
27: { xp: 130, niveau: 9, taille: 320, poids: "601-700", poidsMin: 601, poidsMax: 700, plusdom: +8, sconst: 9, sust: 12 },
28: { xp: 140, niveau: 9, taille: 330, poids: "701-800", poidsMin: 701, poidsMax: 800, plusdom: +8, sconst: 9, sust: 13 },
29: { xp: 150, niveau: 10, taille: 340, poids: "801-900", poidsMin: 801, poidsMax: 900, plusdom: +9, sconst: 9, sust: 14 },
30: { xp: 160, niveau: 10, taille: 350, poids: "901-1000", poidsMin: 901, poidsMax: 1000, plusdom: +9, sconst: 10, sust: 15 },
31: { xp: 170, niveau: 11, taille: 360, poids: "1001-1500", poidsMin: 1001, poidsMax: 1500, plusdom: +10, sconst: 10, sust: 16 },
32: { xp: 180, niveau: 11, taille: 370, poids: "1501-2000", poidsMin: 1501, poidsMax: 2000, plusdom: +11, sconst: 10, sust: 17 },
};
export const CARACS = {
+24 -37
View File
@@ -59,10 +59,11 @@ export class RdDCombatManager extends Combat {
static getCombatant(actorId, tokenId) {
return game.combat?.combatants.find(it => it.actor.id == actorId &&
it.token.id == tokenId
return game.combat?.combatants.find(it => it.actorId == actorId &&
it.tokenId == tokenId
)
}
static getRangInitiativeCombatant(actorId, tokenId) {
const combatant = RdDCombatManager.getCombatant(actorId, tokenId)
return combatant?.system.init?.rang
@@ -169,7 +170,7 @@ export class RdDCombatManager extends Combat {
}
static getFirstInitRollFormula(actor) {
const actions = actor.listActions({ isEquipe: true })
const actions = actor.listActions()
if (actions.length > 0) {
const action = actions[0]
const init = RdDCombatManager.getInitData(actor, action)
@@ -198,8 +199,8 @@ export class RdDCombatManager extends Combat {
<div>
Etant donné son ${action.name}, son initative pour ce premier round est désormais de ${initData.init}.
</div>`
ChatMessage.create({ content: msg });
game.combat.setInitiative(combatant._id, initData.init);
ChatMessage.create({ content: msg })
game.combat.setInitiative(combatant._id, initData.init)
}
}
}
@@ -306,7 +307,7 @@ export class RdDCombatManager extends Combat {
const possessions = actor.listActionsPossessions()
const actions = possessions.length > 0
? possessions
: actor.listActions({ isEquipe: true })
: actor.listActions()
return Misc.indexed(actions)
}
@@ -387,7 +388,7 @@ export class RdDCombat {
/* -------------------------------------------- */
static onMsgEncaisser(msg) {
let defender = canvas.tokens.get(msg.defenderToken.id).actor;
let defender = canvas.tokens.get(msg.defenderToken.id)?.actor;
if (Misc.isOwnerPlayer(defender)) {
let attackerRoll = msg.attackerRoll;
let attacker = msg.attackerId ? game.actors.get(msg.attackerId) : undefined;
@@ -466,24 +467,10 @@ export class RdDCombat {
this.defenderId = this.defender.id
this.attackerTokenId = attackerTokenId
this.defenderTokenId = defenderTokenId
this.attackerToken = RdDCombat.$extractAttackerTokenData(attacker, attackerTokenId)
this.defenderToken = RdDCombat.$extractDefenderTokenData(defender, defenderTokenId, target)
this.attackerToken = Targets.getTokenData(attacker, attackerTokenId)
this.defenderToken = Targets.getTokenData(defender, defenderTokenId, target)
}
static $extractAttackerTokenData(attacker, attackerTokenId) {
const token = canvas.tokens.get(attackerTokenId);
return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(attackerTokenId, attacker)
}
static $extractDefenderTokenData(defender, defenderTokenId, target) {
if (target) {
return Targets.extractTokenData(target)
}
const token = canvas.tokens.get(defenderTokenId);
return token ? Targets.extractTokenData(token) : Targets.buildActorTokenData(defenderTokenId, defender)
}
/* -------------------------------------------- */
async onEvent(button, event) {
const chatMessage = ChatUtility.getChatMessage(event);
@@ -623,7 +610,7 @@ export class RdDCombat {
async proposerAjustementTirLancer(rollData) {
if (['tir', 'lancer'].includes(rollData.competence.system.categorie)) {
if (this.defender.isEntiteBlurette()) {
ChatMessage.create({
await ChatMessage.create({
content: `<strong>La cible est une blurette, l'arme à distance sera perdue dans le blurêve`,
whisper: ChatUtility.getGMs()
})
@@ -638,7 +625,7 @@ export class RdDCombat {
},
Distance.ajustements(_token, defenderToken, { arme: rollData.arme, main: rollData.competence.system.categorie })
)
ChatMessage.create({
await ChatMessage.create({
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.hbs', info),
whisper: ChatUtility.getGMs()
})
@@ -657,7 +644,7 @@ export class RdDCombat {
opponentId: this.defender.id,
opponentTokenId: this.defenderTokenId,
},
type: { allowed: ['attaque'], current: 'attaque' },
type: { allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE },
selected: {},
passeArme: foundry.utils.randomID(16),
}
@@ -736,7 +723,7 @@ export class RdDCombat {
const choixDefense = await ChatMessage.create({
// message privé: du défenseur à lui même (et aux GMs)
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
speaker: ChatMessage.getSpeaker({ actor: this.defender, token: canvas.tokens.get(this.defenderTokenId) }),
alias: this.attacker?.getAlias(),
whisper: ChatUtility.getOwners(this.defender),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense.hbs', defenseData)
@@ -769,7 +756,7 @@ export class RdDCombat {
let rollData = this._prepareAttaque(competence, arme)
console.log("RdDCombat.attaque >>>", rollData)
if (arme) {
this.attacker.verifierForceMin(arme);
await this.attacker.verifierForceMin(arme);
}
await this.proposerAjustementTirLancer(rollData)
@@ -942,7 +929,7 @@ export class RdDCombat {
async _chatMessageDefense(paramDemandeDefense, defenderRoll) {
const choixDefense = await ChatMessage.create({
// message privé: du défenseur à lui même (et aux GMs)
speaker: ChatMessage.getSpeaker(this.defender, canvas.tokens.get(this.defenderTokenId)),
speaker: ChatMessage.getSpeaker({ actor: this.defender, token: canvas.tokens.get(this.defenderTokenId) }),
alias: this.attacker?.getAlias(),
whisper: ChatUtility.getOwners(this.defender),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-defense-v1.hbs', paramDemandeDefense),
@@ -1009,9 +996,9 @@ export class RdDCombat {
const arme = rollData.arme;
const avecArme = !['', 'sans-armes', 'armes-naturelles'].includes(arme?.system.categorie_parade ?? '');
const action = (rollData.attackerRoll ? (arme ? "la parade" : "l'esquive") : "l'attaque");
ChatUtility.createChatWithRollMode(
await ChatMessage.create(ChatUtility.adaptVisibility(
{ content: `<strong>Maladresse à ${action}!</strong> ` + await RdDRollTables.getMaladresse({ arme: avecArme }) },
this.defender)
{ actor: this.defender }))
}
/* -------------------------------------------- */
@@ -1135,9 +1122,9 @@ export class RdDCombat {
async infoAttaquantDesarme(rollData) {
if (/*TODO: parade?*/!rollData.attackerRoll?.particuliere) {
// TODO: attaquant doit jouer résistance et peut être désarmé p132
ChatUtility.createChatWithRollMode(
await ChatMessage.create(ChatUtility.adaptVisibility(
{ content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` },
this.defender)
{ actor: this.defender }))
}
}
@@ -1169,9 +1156,9 @@ export class RdDCombat {
console.log("RdDCombat._onParadeParticuliere >>>", defenderRoll);
if (!defenderRoll.attackerRoll.isPart) {
// TODO: attaquant doit jouer résistance et peut être désarmé p132
ChatUtility.createChatWithRollMode(
await ChatMessage.create(ChatUtility.adaptVisibility(
{ content: `(à gérer) L'attaquant doit jouer résistance et peut être désarmé (p132)` },
this.defender)
{ actor: this.defender }))
}
}
/* -------------------------------------------- */
@@ -1256,9 +1243,9 @@ export class RdDCombat {
/* -------------------------------------------- */
async _onEsquiveParticuliere(defenderRoll) {
console.log("RdDCombat._onEsquiveParticuliere >>>", defenderRoll);
ChatUtility.createChatWithRollMode(
await ChatMessage.create(ChatUtility.adaptVisibility(
{ content: "<strong>Vous pouvez esquiver une deuxième fois!</strong>" },
this.defender);
{ actor: this.defender }))
}
/* -------------------------------------------- */
+25 -23
View File
@@ -27,20 +27,8 @@ const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
export class RdDCommands {
static init() {
const rddCommands = new RdDCommands();
game.system.rdd.commands = rddCommands;
Hooks.on("chatMessage", (html, content, msg) => {
if (content[0] == '/') {
let regExp = /(\S+)/g;
let commands = content.match(regExp);
if (rddCommands.processChatCommand(commands, content, msg)) {
return false;
}
}
return true;
});
game.system.rdd.commands = new RdDCommands()
Hooks.on("chatMessage", (chatLog, message, msg) => game.system.rdd.commands.onChatMessage(message, msg))
}
constructor() {
@@ -216,12 +204,20 @@ export class RdDCommands {
}
onChatMessage(message, msg = {}) {
const content = Misc.stripHtml(message)
if (content[0] == '/') {
const commands = content.match(/(\S+)/g)
if (this.processChatCommand(commands, content, msg)) {
return false
}
}
return true
}
/* -------------------------------------------- */
/* Manage chat commands */
processChatCommand(commandLine, content = '', msg = {}) {
// Setup new message's visibility
ChatUtility.applyRollMode(msg)
msg.type = 0;
if (!this.commandsTable) {
this._registerCommands()
@@ -229,6 +225,9 @@ export class RdDCommands {
let command = commandLine[0].toLowerCase();
if (this._isCommandHandled(command)) {
// Setup new message's visibility
ChatUtility.applyRollMode(msg)
msg.type = 0;
let params = commandLine.slice(1);
this._processCommand(this.commandsTable, command, params, content, msg)
return true
@@ -341,11 +340,11 @@ export class RdDCommands {
const caracName = params[0];
let competence = length > 1 ? actors[0].getCompetence(Misc.join(params.slice(1, length), ' ')) : { name: undefined };
if (competence) {
for (let actor of actors) {
await actor.doRollCaracCompetence(caracName, competence.name, diff);
}
await Promise.all(
actors.map(it => it.doRollCaracCompetence(caracName, competence.name, diff))
)
}
return;
return
}
else {
ui.notifications.warn("Sélectionnez au moins un personnage pour lancer les dés")
@@ -368,7 +367,7 @@ export class RdDCommands {
const carac = params[0];
const competence = length > 1 ? '/' + Misc.join(params.slice(1, length), ' ') : ''
ChatMessage.create({ content: `@roll[${carac}${competence}/${diff}]` })
await ChatMessage.create({ content: `@roll[${carac}${competence}/${diff}]` })
}
}
@@ -467,7 +466,10 @@ export class RdDCommands {
async supprimerSignesDraconiquesEphemeres() {
if (game.user.isGM) {
game.actors.forEach(actor => actor.supprimerSignesDraconiques(it => it.system.ephemere))
await Promise.all(
game.actors.filter(actor => actor.isHautRevant())
.map(actor => actor.supprimerSignesDraconiques(it => it.system.ephemere))
)
}
else {
ui.notifications.warn("Seul le MJ est autorisé à utiliser la commande /signe");
+3 -3
View File
@@ -18,7 +18,7 @@ export class DeTMR extends foundry.dice.terms.Die {
static diceSoNiceData(system) {
return {
type: "dt",
type: "d8",
font: "HeuresDraconiques",
fontScale: 0.8,
labels: ['1', '2', '3', '4', '5', '6', 'd', '0'],
@@ -56,7 +56,7 @@ export class DeDraconique extends foundry.dice.terms.Die {
static diceSoNiceData(system) {
return {
type: "dr",
type: "d8",
font: "HeuresDraconiques",
fontScale: 0.8,
labels: ['1', '2', '3', '4', '5', '6', 'd', '0'],
@@ -96,7 +96,7 @@ export class DeHeure extends foundry.dice.terms.Die {
static diceSoNiceData(system) {
return {
type: "dh",
type: "d12",
font: "HeuresDraconiques",
fontScale: 1.2,
labels: ['v', 'i', 'f', 'o', 'd', 'e', 'l', 's', 'p', 'a', 'r', 'c'],
+140 -114
View File
@@ -15,21 +15,28 @@ export class RdDEmpoignade {
}
/* -------------------------------------------- */
static getActorEmpoignade(actorId) {
const actor = game.actors.get(actorId)
if (actor == undefined) {
ui.notifications.warn(`Impossible de retrouver l'acteur ${actorId}, l'empoignade ne peut pas être continuée.`)
}
return actor
}
static isCombatantEmpoignade(actorId, tokenId) {
const combatant = RdDCombatManager.getCombatant(actorId, tokenId)
return MAP_PHASE.empoignade.rang == combatant?.system.init?.rang
return combatant && MAP_PHASE.empoignade.rang == combatant?.system.init?.rang
}
static async ajustementEmpoignade(attacker, defender, adjust = 1) {
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
if (empoignade?.system.empoigneurid == defender.id) {
let empoignade = RdDEmpoignade.getEmpoignade(defender, attacker)
empoignade = RdDEmpoignade.getEmpoignade(defender, attacker)
return await RdDEmpoignade.$ajustementEmpoignade(empoignade, defender, attacker, - adjust);
}
return await RdDEmpoignade.$ajustementEmpoignade(empoignade, attacker, defender, adjust);
}
static async $ajustementEmpoignade(empoignade, attacker, defender, adjust) {
const empId = empoignade?.system.empoignadeid ?? foundry.utils.randomID(16);
const empFin = (empoignade?.system.pointsemp ?? 0) + adjust
@@ -73,30 +80,32 @@ export class RdDEmpoignade {
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Corps à corps", "melee")
});
})
$(html).on("click", '.defense-empoignade-esquive', event => {
const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
let defenseMode = event.currentTarget.attributes['data-defense-mode'].value
RdDEmpoignade.onDefenseEmpoignade(rollData, defenseMode, "Esquive", "derobee")
});
})
$(html).on("click", '.empoignade-poursuivre', event => {
let attackerId = event.currentTarget.attributes['data-attackerId'].value
let defenderId = event.currentTarget.attributes['data-defenderId'].value
RdDEmpoignade.onAttaqueEmpoignadeValidee(game.actors.get(attackerId), game.actors.get(defenderId))
});
const attacker = RdDEmpoignade.getActorFromEventTag(event, 'data-attackerId')
const defender = RdDEmpoignade.getActorFromEventTag(event, 'data-defenderId')
if (attacker && defender) {
RdDEmpoignade.onAttaqueEmpoignadeValidee(attacker, defender)
}
})
$(html).on("click", '.empoignade-entrainer-sol', event => {
const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
RdDEmpoignade.entrainerAuSol(rollData)
ChatUtility.remover(chatMessage)()
});
})
$(html).on("click", '.empoignade-projeter-sol', event => {
const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
RdDEmpoignade.projeterAuSol(rollData)
ChatUtility.remover(chatMessage)()
});
})
$(html).on("change", '.empoignade-perte-endurance', event => {
const chatMessage = ChatUtility.getChatMessage(event);
const rollData = RdDEmpoignade.$readRollEmpoignade(chatMessage);
@@ -104,7 +113,11 @@ export class RdDEmpoignade {
RdDEmpoignade.perteEndurance(rollData, event.currentTarget.value)
ChatUtility.remover(chatMessage)()
}
});
})
}
static getActorFromEventTag(event, tag) {
return RdDEmpoignade.getActorEmpoignade(event.currentTarget.attributes[tag]?.value ?? '<inconnu>')
}
/* -------------------------------------------- */
@@ -112,32 +125,31 @@ export class RdDEmpoignade {
// TODO: autoriser la perception? la comédie/séduction?
if (RdDEmpoignade.isEmpoignadeEnCours(actor)) {
ui.notifications.warn("Une empoignade est en cours ! Normalement, vous ne pouvez rien faire d'autre que continuer l'empoignade ou la rompre.")
return true;
return true
}
return false;
return false
}
/* -------------------------------------------- */
static $storeRollEmpoignade(msg, rollData) {
RdDEmpoignade.$reduceActorToIds(rollData);
ChatUtility.setMessageData(msg, "empoignade-roll-data", rollData);
ChatUtility.setMessageData(msg, "empoignade-roll-data", RdDEmpoignade.$reduceActorToIds(rollData))
}
static $reduceActorToIds(rollData) {
rollData.attacker = { id: rollData.attacker.id };
rollData.defender = { id: rollData.defender.id };
rollData.attacker = { id: rollData.attacker.id }
rollData.defender = { id: rollData.defender.id }
return rollData
}
/* -------------------------------------------- */
static $readRollEmpoignade(msg) {
const rollData = ChatUtility.getMessageData(msg, 'empoignade-roll-data');
RdDEmpoignade.$replaceIdsWithActors(rollData);
return rollData
return RdDEmpoignade.$replaceIdsWithActors(ChatUtility.getMessageData(msg, 'empoignade-roll-data'))
}
static $replaceIdsWithActors(rollData) {
rollData.attacker = game.actors.get(rollData.attacker.id);
rollData.defender = game.actors.get(rollData.defender.id);
rollData.attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
rollData.defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
return rollData
}
/* -------------------------------------------- */
@@ -147,19 +159,21 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static getEmpoignadeById(actor, id) {
return actor.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id)
return actor?.itemTypes[ITEM_TYPES.empoignade].find(it => it.system.empoignadeid == id)
}
/* -------------------------------------------- */
static getEmpoignade(attacker, defender) {
let emp = attacker.itemTypes[ITEM_TYPES.empoignade].find(it =>
(it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) ||
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
)
if (emp) {
return foundry.utils.duplicate(emp);
if (attacker && defender) {
const empoignade = attacker.itemTypes[ITEM_TYPES.empoignade].find(it =>
(it.system.empoigneurid == attacker.id && it.system.empoigneid == defender.id) ||
(it.system.empoigneurid == defender.id && it.system.empoigneid == attacker.id)
)
if (empoignade) {
return foundry.utils.duplicate(empoignade)
}
}
return undefined;
return undefined
}
/* -------------------------------------------- */
@@ -180,10 +194,14 @@ export class RdDEmpoignade {
}
static isActionAutorisee(mode, attacker, defender) {
const acting = RdDEmpoignade.isActionDefenseur(mode) ? defender : attacker;
if (!defender || !attacker) {
return false
}
const acting = RdDEmpoignade.isActionDefenseur(mode) ? defender : attacker
if (acting.getUserLevel(game.user) < CONST.DOCUMENT_OWNERSHIP_LEVELS.OWNER) {
ui.notifications.warn(`Vous n'êtes pas autorisé à choisir l'action de ${acting.name}`)
return false;
return false
}
return true
}
@@ -205,14 +223,11 @@ export class RdDEmpoignade {
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
const isNouvelle = empoignade == undefined;
empoignade = empoignade ?? (await RdDEmpoignade.createEmpoignade(attacker, defender))
//console.log("W.", empoignade, defender.hasArmeeMeleeEquipee())
if ((isNouvelle || empoignade.system.pointsemp == 0) && defender.hasArmeeMeleeEquipee()) {
ChatUtility.createChatWithRollMode(
{
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-valider.hbs`, { attacker: attacker, defender: defender })
},
attacker
)
await ChatMessage.create(ChatUtility.adaptVisibility(
{ content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-valider.hbs`, { attacker: attacker, defender: defender }) },
{ actor: attacker }
))
} else {
await this.onAttaqueEmpoignadeValidee(attacker, defender)
}
@@ -264,30 +279,34 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static async onAttaqueEmpoignadeFromItem(empoignade) {
let attacker = game.actors.get(empoignade.system.empoigneurid)
let defender = game.actors.get(empoignade.system.empoigneid)
await this.onAttaqueEmpoignadeValidee(attacker, defender)
const attacker = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneurid)
const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
if (attacker && defender) {
await this.onAttaqueEmpoignadeValidee(attacker, defender)
}
}
static async onImmobilisation(attacker, empoignade) {
const defender = game.actors.get(empoignade.system.empoigneid)
const empDefenseur = defender.itemTypes[ITEM_TYPES.empoignade]
.find(it => it.system.empoignadeid == empoignade.system.empoignadeid);
await defender.updateEmbeddedDocuments('Item', [{
_id: empDefenseur.id,
'system.immobilise': true
}])
const rollData = {
mode: "immobilise",
empoignade, attacker, defender,
isEmpoignade: true,
competence: attacker.getCompetenceCorpsACorps()
const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
if (defender) {
const empDefenseur = defender.itemTypes[ITEM_TYPES.empoignade]
.find(it => it.system.empoignadeid == empoignade.system.empoignadeid);
await defender.updateEmbeddedDocuments('Item', [{
_id: empDefenseur.id,
'system.immobilise': true
}])
const rollData = {
mode: "immobilise",
empoignade, attacker, defender,
isEmpoignade: true,
competence: attacker.getCompetenceCorpsACorps()
}
const msg = await ChatMessage.create({
whisper: ChatUtility.getOwners(attacker),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-immobilise.hbs`, rollData)
})
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
}
const msg = await ChatMessage.create({
whisper: ChatUtility.getOwners(attacker),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-empoignade-immobilise.hbs`, rollData)
})
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
}
/* -------------------------------------------- */
@@ -304,30 +323,30 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static async $onRollEmpoignade(rollData, isNouvelle = false) {
let attacker = game.actors.get(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id)
const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (attacker && defender) {
if (rollData.rolled.isSuccess && isNouvelle) {
RdDEmpoignade.$createEtatEmpoignade(rollData.empoignade)
}
if (rollData.rolled.isSuccess && isNouvelle) {
RdDEmpoignade.$createEtatEmpoignade(rollData.empoignade)
rollData.empoignade.isSuccess = rollData.rolled.isSuccess;
if (rollData.rolled.isPart) {
rollData.particuliere = "finesse";
}
let msg = await RdDRollResult.displayRollData(rollData, defender, 'chat-empoignade-resultat.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
}
rollData.empoignade.isSuccess = rollData.rolled.isSuccess;
if (rollData.rolled.isPart) {
rollData.particuliere = "finesse";
}
let msg = await RdDRollResult.displayRollData(rollData, defender, 'chat-empoignade-resultat.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
}
/* -------------------------------------------- */
static async onDefenseEmpoignade(attackerRoll, mode, competenceName = "Corps à corps", carac = "melee") {
let attacker = game.actors.get(attackerRoll.attacker.id)
let defender = game.actors.get(attackerRoll.defender.id)
const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (!RdDEmpoignade.isActionAutorisee(mode, attacker, defender)) {
return
}
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
if (!empoignade) {
@@ -367,7 +386,7 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static async $onRollContrerLiberer(rollData) {
let empoignade = rollData.empoignade
const empoignade = rollData.empoignade
if (rollData.mode == "contrer-empoigner" && !rollData.rolled.isSuccess) {
empoignade.system.pointsemp++
@@ -389,35 +408,40 @@ export class RdDEmpoignade {
static async $createEtatEmpoignade(empoignade) {
console.log("CREATE Empoignade", empoignade)
let defender = game.actors.get(empoignade.system.empoigneid)
let attacker = game.actors.get(empoignade.system.empoigneurid)
const attacker = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneurid)
const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
// Creer l'empoignade sur attaquant/defenseur
await attacker.creerObjetParMJ(empoignade)
await defender.creerObjetParMJ(empoignade)
if (attacker && defender) {
// Creer l'empoignade sur attaquant et defenseur
await attacker.creerObjetParMJ(empoignade)
await defender.creerObjetParMJ(empoignade)
}
}
/* -------------------------------------------- */
static async $updateEtatEmpoignade(empoignade, attacker, defender) {
const belligerants = [
attacker ?? game.actors.get(empoignade.system.empoigneurid),
defender ?? game.actors.get(empoignade.system.empoigneid)]
const removeEmp = empoignade.system.pointsemp == 0
attacker = attacker ?? RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneurid)
defender = defender ?? RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
if (removeEmp) {
const emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
return await attacker.deleteEmbeddedDocuments('Item', [emp.id])
}
else {
await Promise.all(
belligerants.map(async belligerant => {
const emp = RdDEmpoignade.getEmpoignadeById(belligerant, empoignade.system.empoignadeid)
return await belligerant.updateEmbeddedDocuments('Item', [{
_id: emp.id,
"system.pointsemp": empoignade.system.pointsemp,
"system.ausol": empoignade.system.ausol
}])
}))
if (attacker && defender) {
const belligerants = [attacker, defender]
const removeEmp = empoignade.system.pointsemp == 0
if (removeEmp) {
const emp = RdDEmpoignade.getEmpoignadeById(attacker, empoignade.system.empoignadeid)
return await attacker.deleteEmbeddedDocuments('Item', [emp.id])
}
else {
await Promise.all(
belligerants.map(async belligerant => {
const emp = RdDEmpoignade.getEmpoignadeById(belligerant, empoignade.system.empoignadeid)
return await belligerant.updateEmbeddedDocuments('Item', [{
_id: emp.id,
"system.pointsemp": empoignade.system.pointsemp,
"system.ausol": empoignade.system.ausol
}])
}))
}
}
}
@@ -425,19 +449,21 @@ export class RdDEmpoignade {
static async $deleteEmpoignade(empoignade) {
console.log("DELETE Empoignade", empoignade)
const defender = game.actors.get(empoignade.system.empoigneid)
const emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
await defender.deleteEmbeddedDocuments('Item', [emp.id])
const defender = RdDEmpoignade.getActorEmpoignade(empoignade.system.empoigneid)
if (defender) {
const emp = RdDEmpoignade.getEmpoignadeById(defender, empoignade.system.empoignadeid)
await defender.deleteEmbeddedDocuments('Item', [emp.id])
}
}
/* -------------------------------------------- */
static async entrainerAuSol(rollData) {
let attacker = game.actors.get(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id)
const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return
}
let empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
const empoignade = RdDEmpoignade.getEmpoignade(attacker, defender)
empoignade.system.ausol = true
await this.$updateEtatEmpoignade(empoignade)
@@ -445,14 +471,14 @@ export class RdDEmpoignade {
await attacker.setEffect(STATUSES.StatusProne, true);
await defender.setEffect(STATUSES.StatusProne, true);
let msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.hbs');
const msg = await RdDRollResult.displayRollData(rollData, attacker, 'chat-empoignade-entrainer-sol.hbs');
RdDEmpoignade.$storeRollEmpoignade(msg, rollData);
}
/* -------------------------------------------- */
static async projeterAuSol(rollData) {
let attacker = game.actors.get(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id)
const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (!RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return
}
@@ -467,8 +493,8 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static async perteEndurance(rollData, perteMode) {
let attacker = game.actors.get(rollData.attacker.id)
let defender = game.actors.get(rollData.defender.id)
const attacker = RdDEmpoignade.getActorEmpoignade(rollData.attacker.id)
const defender = RdDEmpoignade.getActorEmpoignade(rollData.defender.id)
if (perteMode == "none" || !RdDEmpoignade.isActionAutorisee("immobilise", attacker, defender)) {
return
}
@@ -501,11 +527,11 @@ export class RdDEmpoignade {
/* -------------------------------------------- */
static async deleteLinkedEmpoignade(actorId, empoignade) {
let actorDeleteId = (actorId == empoignade.system.empoigneurid) ? empoignade.system.empoigneid : empoignade.system.empoigneurid
let actor = game.actors.get(actorDeleteId)
let emp = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
if (emp) {
await actor.deleteEmbeddedDocuments('Item', [emp.id])
const actorDeleteId = (actorId == empoignade.system.empoigneurid) ? empoignade.system.empoigneid : empoignade.system.empoigneurid
const actor = RdDEmpoignade.getActorEmpoignade(actorDeleteId)
const empoignadeOpposant = this.getEmpoignadeById(actor, empoignade.system.empoignadeid)
if (actor && empoignadeOpposant) {
await actor.deleteEmbeddedDocuments('Item', [empoignadeOpposant.id])
}
}
+18 -2
View File
@@ -60,6 +60,7 @@ import { RdDItemRace } from "./item/race.js"
import { RdDItemSigneDraconique } from "./item/signedraconique.js"
import { RdDItemSort } from "./item-sort.js"
import { RdDItemSouffle } from "./item/souffle.js"
import { RdDItemTache } from "./item/tache.js"
import { RdDItemTete } from "./item/tete.js"
import { RdDRencontre } from "./item/rencontre.js"
@@ -76,6 +77,7 @@ import { RdDPotionItemSheet } from "./item/sheet-potion.js"
import { RdDRencontreItemSheet } from "./item/sheet-rencontre.js"
import { RdDServiceItemSheet } from "./item/sheet-service.js"
import { RdDSigneDraconiqueItemSheet } from "./item/sheet-signedraconique.js"
import { RdDTacheItemSheet } from "./item/sheet-tache.js"
import { AppAstrologie } from "./sommeil/app-astrologie.js"
import { AutoAdjustDarkness } from "./time/auto-adjust-darkness.js"
@@ -94,6 +96,7 @@ import ChatRollResult from "./roll/chat-roll-result.mjs"
import ExportPdf from "./actor/export-pdf/export-pdf.mjs"
import { DialogFlushByDate } from "./chat/dialog-flush-by-date.mjs"
import { Remote } from "./remote.mjs"
import { RdDActiveEffect } from "./effect/base-active-effect.js"
/**
* RdD system
@@ -133,6 +136,7 @@ export class SystemReveDeDragon {
service: RdDItemService,
signedraconique: RdDItemSigneDraconique,
souffle: RdDItemSouffle,
tache: RdDItemTache,
tarot: items.RdDModelTarot,
tete: RdDItemTete,
}
@@ -199,6 +203,7 @@ export class SystemReveDeDragon {
// Define custom Entity classes
console.log(`Initializing Reve de Dragon Documents`)
CONFIG.Actor.documentClass = RdDBaseActor
CONFIG.ActiveEffect.documentClass = RdDActiveEffect
CONFIG.Item.documentClass = RdDItem
CONFIG.Item.dataModels = {
monnaie: models.RdDModelMonnaie,
@@ -283,6 +288,7 @@ export class SystemReveDeDragon {
RdDItemSheetV1.register(RdDRencontreItemSheet)
RdDItemSheetV1.register(RdDServiceItemSheet)
RdDItemSheetV1.register(RdDSigneDraconiqueItemSheet)
RdDItemSheetV1.register(RdDTacheItemSheet)
RdDJournalSheet.register()
// préparation des différents modules
@@ -375,7 +381,17 @@ export class SystemReveDeDragon {
/* -------------------------------------------- */
game.system.rdd.calendrier = new RdDCalendrier()
if (Misc.isFirstConnectedGM()) {
new Migrations().migrate()
try {
new Migrations().migrate()
}
catch (erreur) {
const message = `<p>Erreur lors de la migration du système Rêve de Dragon: ${erreur}</p><p>Plus de détails sont sans doute disponibles dans la console de Foundry/du navigateur.</p><p>Merci de nous signaler cetter erreur qu'on puisse ous aider et réparer le problème.</p>`
ui.notifications.error(message)
await ChatMessage.create({
user: game.user.id,
content: message
})
}
this.messageDeBienvenue()
import("https://www.uberwald.me/fvtt_appcount/count-class-ready.js").then(moduleCounter => {
console.log("ClassCounter loaded", moduleCounter)
@@ -397,7 +413,7 @@ export class SystemReveDeDragon {
if (!game.user.isGM && game.user.character == undefined) {
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !")
ChatMessage.create({
content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !",
content: `<b>ATTENTION</b> Le joueur ${game.user.name} n'est connecté à aucun personnage !`,
user: game.user.id
})
}
+1 -1
View File
@@ -117,7 +117,7 @@ export class RdDMeteo {
meteo.nuage.description = RdDMeteo.nuage(meteo.nuage.force);
meteo.pluie.description = RdDMeteo.pluie(meteo.pluie.force);
ChatMessage.create({
await ChatMessage.create({
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-resultat-meteo.hbs', meteo),
whisper: ChatUtility.getGMs()
});
+1 -1
View File
@@ -95,7 +95,7 @@ export class RdDPossession {
}
static selectCompetenceDraconicOuPossession(rollData, rollingActor) {
rollData.competence = rollingActor.getDraconicOuPossession().find(it => true);
rollData.competence = rollingActor.getBestDraconic({possession: true})
if (rollingActor.isCreatureOuEntite()) {
rollData.carac = rollingActor.system.carac
rollData.competence.system.defaut_carac = CARACS.REVE
+2 -2
View File
@@ -98,7 +98,7 @@ export class RdDResolutionTable {
/* -------------------------------------------- */
static async rollData(rollData) {
rollData.rolled = await this.roll(rollData.caracValue, rollData.finalLevel, rollData);
return rollData;
return rollData
}
/* -------------------------------------------- */
@@ -107,7 +107,7 @@ export class RdDResolutionTable {
this._updateChancesWithBonus(chances, rollData.bonus, finalLevel);
this._updateChancesFactor(chances, rollData.diviseurSignificative);
chances.showDice = rollData.showDice;
chances.rollMode = rollData.rollMode;
chances.rollMode = rollData.current?.rollmode?.key ?? game.settings.get("core", "rollMode")
let rolled = await this.rollChances(chances, rollData.diviseurSignificative, rollData.forceDiceResult);
rolled.caracValue = caracValue;
+3 -5
View File
@@ -4,12 +4,10 @@ import { renderTemplate } from "./constants.js";
export class RdDRollResult {
static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.hbs') {
const chatMessage = await ChatUtility.createChatWithRollMode(
return await ChatMessage.create(ChatUtility.adaptVisibility(
{ content: await RdDRollResult.buildRollDataHtml(rollData, template) },
actor,
rollData.current?.rollmode?.key
)
return chatMessage
{ actor: actor, rollMode: rollData.current?.rollmode?.key ?? game.settings.get("core", "rollMode") }
))
}
static async buildRollDataHtml(rollData, template = 'chat-resultat-general.hbs') {
+22 -20
View File
@@ -34,9 +34,9 @@ export class RdDRollTables {
}
/* -------------------------------------------- */
static async getCompetence(toChat = false) {
static async getCompetence(toChat = false, rollMode = "gmroll") {
if (toChat == 'liste') {
return await RdDRollTables.listOrRoll('competences', 'Item', ['competence'], toChat, it => 1);
return await RdDRollTables.listOrRoll('competences', 'Item', ['competence'], toChat, rollMode, it => 1);
}
else {
return await RdDRollTables.drawItemFromRollTable("Détermination aléatoire de compétence", toChat);
@@ -44,56 +44,58 @@ export class RdDRollTables {
}
/* -------------------------------------------- */
static async getSouffle(toChat = false) {
return await RdDRollTables.listOrRoll('souffles-de-dragon', 'Item', ['souffle'], toChat);
static async getSouffle(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('souffles-de-dragon', 'Item', ['souffle'], toChat, rollMode);
}
/* -------------------------------------------- */
static async getQueue(toChat = false) {
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat);
static async getQueue(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat, rollMode);
}
static async getDesirLancinant(toChat = false) {
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat,
static async getDesirLancinant(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat, rollMode,
it => it.system.frequence,
it => it.system.categorie == 'lancinant');
}
static async getIdeeFixe(toChat = false) {
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat,
static async getIdeeFixe(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('queues-de-dragon', 'Item', ['queue'], toChat, rollMode,
it => it.system.frequence,
it => it.system.categorie == 'ideefixe');
}
/* -------------------------------------------- */
static async getTeteHR(toChat = false) {
return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-haut-revants', 'Item', ['tete'], toChat);
static async getTeteHR(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-haut-revants', 'Item', ['tete'], toChat, rollMode);
}
/* -------------------------------------------- */
static async getTete(toChat = false) {
return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-tous-personnages', 'Item', ['tete'], toChat);
static async getTete(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('tetes-de-dragon-pour-tous-personnages', 'Item', ['tete'], toChat, rollMode);
}
/* -------------------------------------------- */
static async getOmbre(toChat = false) {
return await RdDRollTables.listOrRoll('ombres-de-thanatos', 'Item', ['ombre'], toChat);
static async getOmbre(toChat = false, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('ombres-de-thanatos', 'Item', ['ombre'], toChat, rollMode);
}
/* -------------------------------------------- */
static async getTarot(toChat = true) {
return await RdDRollTables.listOrRoll('tarot-draconique', 'Item', ['tarot'], toChat);
static async getTarot(toChat = true, rollMode = "gmroll") {
return await RdDRollTables.listOrRoll('tarot-draconique', 'Item', ['tarot'], toChat, rollMode);
}
/* -------------------------------------------- */
static async listOrRoll(compendium, type, subTypes, toChat, itemFrequence = it => it.system.frequence, filter = it => true) {
static async listOrRoll(compendium, type, subTypes, toChat, rollMode,
itemFrequence = it => it.system.frequence,
filter = it => true) {
const table = new CompendiumTable(compendium, type, subTypes);
if (toChat == 'liste') {
return await table.toChatMessage(itemFrequence, filter);
}
const row = await table.getRandom(itemFrequence, filter);
if (row) {
await CompendiumTableHelpers.tableRowToChatMessage(row, type);
await CompendiumTableHelpers.tableRowToChatMessage(row, type, { rollMode: rollMode });
return row.document;
}
return undefined;
+24 -24
View File
@@ -49,7 +49,7 @@ export class RdDTMRDialog extends Dialog {
await PixiTMR.init()
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.hbs', tmrData);
if (tmrData.mode != 'visu' && !game.user.isGM) {
ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatUtility.getGMs() });
await ChatMessage.create({ content: actor.name + " est monté dans les TMR en mode : " + tmrData.mode, whisper: ChatUtility.getGMs() });
}
return new RdDTMRDialog(html, actor, tmrData)
}
@@ -138,7 +138,7 @@ export class RdDTMRDialog extends Dialog {
this.html.find('img.tmr-move').click(event => this.deplacementTMR(this.html.find(event.currentTarget)?.data('move')));
// Gestion du cout de montée en points de rêve
await this.actor.reveActuelIncDec(this.calculCoutMonteeTMR());
await this.actor.reveActuelIncDec(await this.calculCoutMonteeTMR());
this.cumulFatigue += this.fatigueParCase;
// Le reste...
@@ -305,8 +305,8 @@ export class RdDTMRDialog extends Dialog {
await this.$checkQuitterTMR();
}
calculCoutMonteeTMR() {
return ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse();
async calculCoutMonteeTMR() {
return ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - (await this.actor.countMonteeLaborieuse())
}
/* -------------------------------------------- */
@@ -501,7 +501,7 @@ export class RdDTMRDialog extends Dialog {
rencData.poesie = { extrait: result.poesie, reference: result.reference };
rencData.message = this.$formatMessageRencontre(rencData, result.message);
ChatMessage.create({
await ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.hbs`, rencData)
});
@@ -653,7 +653,7 @@ export class RdDTMRDialog extends Dialog {
this.restoreTMRAfterAction()
if (myRoll == 7) {
ChatUtility.tellToUser(myRoll + ": Rencontre en " + coordTMR);
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, this.actor.isMauvaiseRencontre())
return await game.system.rdd.rencontresTMR.getRencontreAleatoire(tmr, await this.actor.isMauvaiseRencontre())
} else {
ChatUtility.tellToUser(myRoll + ": Pas de rencontre en " + coordTMR);
return undefined;
@@ -682,7 +682,7 @@ export class RdDTMRDialog extends Dialog {
if (this.isCaseHumide(tmr)) {
let rollData = {
actor: this.actor,
competence: foundry.utils.duplicate(this.actor.getBestDraconic()),
competence: this.actor.getBestDraconic(),
tmr: tmr,
canClose: false,
diffLibre: -7,
@@ -708,7 +708,7 @@ export class RdDTMRDialog extends Dialog {
return;
}
rollData.poesie = await Poetique.getExtrait();
ChatMessage.create({
await ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData)
});
@@ -728,16 +728,16 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */
isCaseHumide(tmr) {
if (!(TMRUtility.isCaseHumide(tmr) || this.isCaseHumideAdditionelle(tmr))) {
return false;
return false
}
if (this.isCaseMaitrisee(tmr.coord)) {
ChatMessage.create({
content: tmr.label + ": cette case humide est déja maitrisée grâce à votre Tête <strong>Quête des Eaux</strong>",
whisper: ChatUtility.getOwners(this.actor)
});
return false;
})
return false
}
return true;
return true
}
/* -------------------------------------------- */
@@ -747,16 +747,16 @@ export class RdDTMRDialog extends Dialog {
content: tmr.label + ": Vous êtes sous le coup d'une Impraticabilité des Ponts : ce pont doit être maîtrisé comme une case humide.",
whisper: ChatUtility.getOwners(this.actor)
});
return true;
return true
}
if (this.isCaseInondee(tmr.coord)) {
ChatMessage.create({
content: tmr.label + ": cette case est inondée, elle doit être maîtrisée comme une case humide.",
whisper: ChatUtility.getOwners(this.actor)
});
return true;
return true
}
return false;
return false
}
/* -------------------------------------------- */
@@ -807,7 +807,7 @@ export class RdDTMRDialog extends Dialog {
async _conquerir(tmr, options) {
let rollData = {
actor: this.actor,
competence: foundry.utils.duplicate(this.actor.getBestDraconic()),
competence: this.actor.getBestDraconic(),
tmr: tmr,
canClose: options.canClose ?? false,
diffLibre: options.difficulte ?? -7,
@@ -825,7 +825,7 @@ export class RdDTMRDialog extends Dialog {
rollData.souffle = await this.actor.ajouterSouffle({ chat: false })
}
rollData.poesie = await Poetique.getExtrait()
ChatMessage.create({
await ChatMessage.create({
whisper: ChatUtility.getOwners(this.actor),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.hbs`, rollData)
})
@@ -876,7 +876,7 @@ export class RdDTMRDialog extends Dialog {
const reserveSecurite = EffetsDraconiques.isReserveEnSecurite(this.actor);
const reserveExtensible = this.isReserveExtensible(coord);
if (!EffetsDraconiques.isUrgenceDraconique(this.actor) && (reserveSecurite || reserveExtensible)) {
ChatMessage.create({
await ChatMessage.create({
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-demande-declencher-sort.hbs`, {
actor: this.actor,
sorts: sorts,
@@ -892,13 +892,13 @@ export class RdDTMRDialog extends Dialog {
}
/* -------------------------------------------- */
lancerSortEnReserve(coord, sortId) {
async lancerSortEnReserve(coord, sortId) {
const sort = this.getSortsReserve(coord)
.find(it => it.id == sortId);
if (sort) {
this.processSortReserve(sort);
await this.processSortReserve(sort);
} else {
ChatMessage.create({
await ChatMessage.create({
content: "Une erreur est survenue : impossible de récupérer le sort en réserve demandé.",
whisper: ChatUtility.getOwners(this.actor)
});
@@ -1137,12 +1137,12 @@ export class RdDTMRDialog extends Dialog {
if (!token) {
return
}
if (this.demiReve === token && this.isDemiReveCache()) {
if (this.isDemiReveCache() && [EffetsDraconiques.rencontre.code(), EffetsDraconiques.demiReve.code()].includes(token.code)) {
return
}
this.pixiTMR.positionToken(token);
this.pixiTMR.positionToken(token)
if (!this.allTokens.includes(token)) {
this.allTokens.push(token);
this.allTokens.push(token)
}
}
}
+1 -1
View File
@@ -49,7 +49,7 @@ export class RdDTokenHud {
static async addExtensionHudCombatV2(html, combatant, actor, token) {
const isPossession = actor.listActionsPossessions().length > 0;
const actionsCombat = isPossession ? [] : actor.listAttaques()
const actionsCombat = isPossession ? [] : actor.listActions()
const ajustements = combatant?.initiative ?
[
{ label: 'Initiative +1', action: 'delta', value: 1 },
+67 -26
View File
@@ -132,9 +132,9 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-derivee.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-creature.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-entitee.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-creature.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/comp-possession.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/carac-total.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/competence.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/competence-categorie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/xp-competences.hbs',
@@ -145,9 +145,10 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor/possessions.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/resonances.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/taches.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/livres.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvres.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/oeuvre.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/jeus.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/jeux.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/alchimie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/astrologie.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/chirurgie.hbs',
@@ -173,6 +174,11 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor/liens-vehicules.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/commerce-inventaire-item.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/tooltip-bonmoments.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/dialog-gerer-herbes.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/dialog-gerer-ingredients.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/dialog-gerer-deniers.hbs',
'systems/foundryvtt-reve-de-dragon/templates/actor/dialog-gerer-potions.hbs',
//Items
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete-script.hbs',
'systems/foundryvtt-reve-de-dragon/templates/scripts/autocomplete.hbs',
@@ -190,6 +196,7 @@ export class RdDUtility {
'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',
'systems/foundryvtt-reve-de-dragon/templates/item/tache-commune-flag.hbs',
// partial enums
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.hbs',
'systems/foundryvtt-reve-de-dragon/templates/enum-base-competence.hbs',
@@ -300,6 +307,7 @@ export class RdDUtility {
Handlebars.registerHelper('grammar-un', str => Grammar.articleIndetermine(str));
Handlebars.registerHelper('grammar-accord', (genre, ...args) => Grammar.accord(genre, args));
Handlebars.registerHelper('json-stringify', object => JSON.stringify(object))
Handlebars.registerHelper('escapeHtml', object => foundry.utils.escapeHTML(object))
// math
Handlebars.registerHelper('math-sum', (...values) => values.slice(0, -1).reduce(Misc.sum(), 0))
@@ -411,6 +419,7 @@ export class RdDUtility {
let objet = inventaires.find(objet => (id == objet._id));
if (objet) {
objet.estContenu = true;
objet.parentConteneurName = conteneur.name;
objetVersConteneur[id] = conteneur._id;
conteneur.subItems.push(objet);
}
@@ -471,6 +480,8 @@ export class RdDUtility {
item: item,
vide: isConteneur && item.system.contenu.length == 0,
ouvert: isConteneur && RdDUtility.getAfficheContenu(item._id),
sature: isConteneur && item.system.encTotal > item.system.capacite,
fillPercent: isConteneur ? Math.min(100, (item.system.encTotal / (item.system.capacite || 1)) * 100) : 0,
options: options
};
optionsArbre.ouvert = inventaire.ouvert
@@ -481,9 +492,9 @@ export class RdDUtility {
return ligneObjet;
}
static filterItemsPerTypeForSheet(formData, itemTypes) {
static filterItemsPerTypeForSheet(formData, itemTypes, triEquipement = 'name') {
Object.values(ITEM_TYPES).forEach(t => {
formData[t + 's'] = Misc.arrayOrEmpty(itemTypes[t])
formData[RdDItem.itemTypePluriel(t)] = Misc.arrayOrEmpty(itemTypes[t])
itemTypes[t].forEach(item => item.actions = item.itemActions())
})
@@ -491,7 +502,7 @@ export class RdDUtility {
formData.competences = formData.competences.concat(formData.competencecreatures)
formData.monnaies = formData.monnaies.sort(Monnaie.triValeurEntiere())
formData.inventaires = RdDUtility.prepareInventaire(itemTypes)
formData.inventaires = RdDUtility.prepareInventaire(itemTypes, triEquipement)
}
static buildInventaireConteneur(actorId, itemId, options) {
@@ -499,7 +510,7 @@ export class RdDUtility {
const item = actor?.items.get(itemId)
if (item?.type == ITEM_TYPES.conteneur) {
const formData = {}
RdDUtility.filterItemsPerTypeForSheet(formData, actor.itemTypes);
RdDUtility.filterItemsPerTypeForSheet(formData, actor.itemTypes, options?.triEquipement);
RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.inventaires);
item.subItems = formData.conteneurs.find(it => it._id == itemId)?.subItems;
@@ -508,11 +519,25 @@ export class RdDUtility {
return ''
}
static prepareInventaire(itemTypes) {
return RdDItem.getItemTypesInventaire('all')
static prepareInventaire(itemTypes, triEquipement = 'name') {
let items = RdDItem.getItemTypesInventaire('all')
.map(t => Misc.arrayOrEmpty(itemTypes[t]))
.reduce((a, b) => a.concat(b), [])
.sort(Misc.ascending(it => it.name))
.reduce((a, b) => a.concat(b), []);
items = items.filter(it => !(it.type === ITEM_TYPES.livre && it.system.estCopieLue));
switch (triEquipement) {
case 'type':
items.sort(Misc.ascending(it => Misc.typeName('Item', it.type)));
break;
case 'enc':
items.sort(Misc.ascending(it => it.system.encombrement ?? 0));
break;
case 'quantite':
items.sort(Misc.descending(it => it.system.quantite ?? 0));
break;
default:
items.sort(Misc.ascending(it => it.name));
}
return items;
}
/* -------------------------------------------- */
@@ -522,7 +547,23 @@ export class RdDUtility {
const profondeur = optionsArbre.profondeur;
optionsArbre.profondeur++;
const lignesContenu = conteneur.subItems.sort(Misc.ascending(it => it.name))
const sortBy = options.triEquipement || 'name';
let sorted = [...conteneur.subItems];
sorted = sorted.filter(it => !(it.type === ITEM_TYPES.livre && it.system.estCopieLue));
switch (sortBy) {
case 'type':
sorted.sort(Misc.ascending(it => Misc.typeName('Item', it.type)));
break;
case 'enc':
sorted.sort(Misc.ascending(it => it.system.encombrement ?? 0));
break;
case 'quantite':
sorted.sort(Misc.descending(it => it.system.quantite ?? 0));
break;
default:
sorted.sort(Misc.ascending(it => it.name));
}
const lignesContenu = sorted
.map(contenu => this.buildLigneInventaire(contenu, options, optionsArbre));
return `<ul class='item-list alterne-list ${display} list-item-margin${Math.min(profondeur, 6)}'>`
@@ -680,7 +721,7 @@ export class RdDUtility {
encaissement.dmg = dmg
if (ReglesOptionnelles.isUsing('localisation-aleatoire')) {
encaissement.dmg.loc = dmg.loc ?? await RdDUtility.getLocalisation(targetActor.type)
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps;'
encaissement.dmg.loc.label = encaissement.dmg.loc.label ?? 'Corps'
}
else {
encaissement.dmg.loc = { label: '' }
@@ -689,9 +730,9 @@ export class RdDUtility {
encaissement.armure = armure
encaissement.penetration = dmg.penetration
encaissement.total = jetTotal
encaissement.vie = await RdDUtility._evaluatePerte(encaissement.vie, over20);
encaissement.endurance = await RdDUtility._evaluatePerte(encaissement.endurance, over20);
return encaissement;
encaissement.vie = await RdDUtility._evaluatePerte(encaissement.vie, over20)
encaissement.endurance = await RdDUtility._evaluatePerte(encaissement.endurance, over20)
return encaissement
}
/* -------------------------------------------- */
@@ -750,12 +791,12 @@ export class RdDUtility {
actor.tmrApp.positionnerDemiReve(coord);
});
// Gestion spécifique des sorts en réserve multiples (ie têtes)
$(html).on("click", '.declencher-sort-reserve', event => {
$(html).on("click", '.declencher-sort-reserve', async event => {
let coord = event.currentTarget.attributes['data-tmr-coord'].value;
let sortId = event.currentTarget.attributes['data-sort-id'].value;
let actorId = event.currentTarget.attributes['data-actor-id'].value;
let actor = game.actors.get(actorId);
actor.tmrApp.lancerSortEnReserve(coord, sortId);
await actor.tmrApp.lancerSortEnReserve(coord, sortId);
// TODO: supprimer le message?
});
@@ -844,12 +885,12 @@ export class RdDUtility {
return game.user.character;
}
if (msgPlayer != undefined) {
msgPlayer += "<br>vous pouvez sélectionner un seul token lié à un personnage";
msgPlayer += "<br>vous pouvez sélectionner un seul token lié à un personnage"
msgPlayer += "<br>vous devez être connecté comme joueur avec un personnage sélectionné";
ui.notifications.warn(msgPlayer);
ChatMessage.create({ content: msgPlayer, whisper: [game.user] });
ChatMessage.create({ content: msgPlayer, whisper: [game.user] })
}
return undefined;
return undefined
}
static doWithSelectedActor(onSelected = () => { }, filter = actor => true) {
@@ -942,9 +983,9 @@ export class RdDUtility {
content: `<p>Etes vous certain de vouloir supprimer: ${item.name}?</p>`,
title: `Supprimer ${item.name}`,
buttonLabel: "Supprimer",
onAction: () => {
onAction: async () => {
console.log('Delete : ', itemId);
actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false });
await actor.deleteEmbeddedDocuments('Item', [itemId], { renderSheet: false });
}
};
if (item.isConteneurNonVide()) {
@@ -955,9 +996,9 @@ export class RdDUtility {
'deleteall': {
icon: '<i class="fas fa-check"></i>',
label: "Supprimer conteneur et contenu",
callback: () => {
callback: async () => {
console.log("Delete : ", itemId);
actor.deleteAllConteneur(itemId, { renderSheet: false });
await actor.deleteAllConteneur(itemId, { renderSheet: false });
}
}
});
@@ -995,10 +1036,10 @@ export class RdDUtility {
}
/*-------------------------------------------- */
static checkThanatosXP(item) {
static async checkThanatosXP(item) {
if (item.isCompetencePersonnage() && item.name.includes('Thanatos')) {
let message = "Vous avez mis des points d'Expérience en Thanatos !<br>Vous devez réduire manuellement d'un même montant d'XP une autre compétence Draconique.";
ChatMessage.create({
await ChatMessage.create({
whisper: ChatUtility.getUserAndGMs(),
content: message
});
+10 -6
View File
@@ -43,13 +43,15 @@ export default class ChatRollResult {
async display(roll, impacts) {
this.prepareDisplay(roll)
const chatMessage = await ChatUtility.createChatWithRollMode(
const chatMessage = await ChatMessage.create(ChatUtility.adaptVisibility(
{
content: await this.buildRollHtml(roll)
},
roll.active.actor,
roll.current?.rollmode?.key
)
{
actor: roll.active.actor,
rollMode: roll.current?.rollmode?.key
}
))
await this.saveChatMessageRoll(chatMessage, roll, impacts)
return chatMessage
@@ -105,8 +107,8 @@ export default class ChatRollResult {
if (attaque &&
(roll.rolled.isEchec || !roll.current.defense.isEsquive) &&
(attaque.particuliere == 'force' || 'charge' == attaque.tactique?.key)) {
const taille = defender.system.carac.taille.value
const impact = attacker.system.carac.force.value + roll.attackerRoll?.dmg.dmgArme
const taille = defender.getTaille()
const impact = attacker.getForce() + roll.attackerRoll?.dmg.dmgArme
return {
raison: 'charge' == attaque.tactique?.key ? 'charge' : 'particulière en force',
taille: taille,
@@ -200,6 +202,7 @@ export default class ChatRollResult {
const chatMessage = ChatUtility.getChatMessage(event)
const savedRoll = this.loadChatMessageRoll(chatMessage)
const actor = this.getActiveActor(savedRoll)
Misc.doIfOwner(actor, it => it.rollAppelChance(
() => this.onAppelChanceSuccess(savedRoll, chatMessage),
() => this.onAppelChanceEchec(savedRoll, chatMessage))
@@ -208,6 +211,7 @@ export default class ChatRollResult {
async onAppelChanceSuccess(roll, chatMessage) {
roll.type.retry = true
roll.type.appelChance = true
await this.updateChatMessage(chatMessage, roll)
const callbacks = [ChatUtility.remover(chatMessage)]
+13 -4
View File
@@ -9,6 +9,8 @@ export const ROLL_TYPE_MEDITATION = 'meditation'
export const ROLL_TYPE_OEUVRE = 'oeuvre'
export const ROLL_TYPE_SORT = 'sort'
export const ROLL_TYPE_TACHE = 'tache'
export const ROLL_TYPE_APPEL_CHANCE = 'appel-chance'
export const ROLL_TYPE_REVE_RESISTANCE = 'reve-resistance'
export const ATTAQUE_ROLL_TYPES = [ROLL_TYPE_ATTAQUE]
export const COMBAT_ROLL_TYPES = [ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE]
@@ -25,11 +27,18 @@ 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: "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.LIBRE]: { key: DIFF.LIBRE, label: "Diff. libre", libre: true, visible: true, max: 0 },
[DIFF.ATTAQUE]: { key: DIFF.ATTAQUE, label: "Diff. attaque", libre: true, visible: true, max: 0 },
[DIFF.IMPOSEE]: { key: DIFF.IMPOSEE, label: "Diff. imposée", libre: false, visible: true, max: 20 },
[DIFF.DEFENSE]: { key: DIFF.DEFENSE, label: "Diff. 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 },
}
export class RollConstants {
static findCompetence(rollData, name) {
return rollData.active.actor.getCompetence(name, { onMessage: message => { } })
}
}
+21 -22
View File
@@ -50,6 +50,8 @@ 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";
import { RollTypeAppelChance } from "./roll-type-appel-chance.mjs";
import { RollTypeReveResistance } from "./roll-type-resistance.mjs";
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
@@ -65,7 +67,8 @@ export const ALL_ROLL_TYPES = [
new RollTypeCuisine(),
new RollTypeOeuvre(),
new RollTypeJeu(),
// new RollTypeResistance ??
new RollTypeAppelChance(),
new RollTypeReveResistance(),
// new RollTypeFixedCarac ??
]
@@ -77,7 +80,6 @@ const ROLL_PARTS = [
new RollPartCarac(),
new RollPartComp(),
new RollPartDiff(),
new RollPartApprecier(),
new RollPartAttaque(),
new RollPartPossession(),
@@ -89,17 +91,17 @@ const ROLL_PARTS = [
new RollPartOeuvre(),
new RollPartJeu(),
new RollPartSign(),
new RollPartEcailles(),
new RollPartEtat(),
new RollPartDiff(),
new RollPartConditions(),
new RollPartEtat(),
new RollPartSign(),
new RollPartEncTotal(),
new RollPartSurEnc(),
new RollPartEthylisme(),
new RollPartEcailles(),
new RollPartMalusArmure(),
new RollPartEmpoignadeTaille(),
new RollPartEmpoignade(),
new RollPartEncTotal(),
new RollPartSurEnc(),
new RollPartAppelMoral(),
new RollPartMoral(),
new RollPartCoeur(),
@@ -290,7 +292,6 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
return rollData.type?.allowed
? ROLL_PARTS.filter(p => RollDialog.$isIntersecting(rollData.type.allowed, p.rollTypes))
: ROLL_PARTS
}
/** pre-configure les paramètres des différentes parties de la fenêtre (par exemple, prépare les listes de caractéristiques/compétences */
@@ -378,15 +379,15 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
this.hooks = []
this.rollData = rollData
this.rollOptions = {
this.rollOptions = foundry.utils.mergeObject(rollOptions, {
callbacks: [
async r => await r.active.actor.appliquerAjoutExperience(r),
async r => await r.active.actor.ajoutExperience(r),
async r => await r.active.actor.appliquerAppelMoral(r),
...(rollOptions.callbacks ?? [])
],
onRollDone: rollOptions.onRollDone ?? RollDialog.onRollDoneDoNothing,
onClose: rollOptions.onClose ?? RollDialog.onCloseDoNothing
}
})
this.chatRollResult = new ChatRollResult()
this.rollParts = RollDialog.getAllowedParts(rollData)
@@ -428,9 +429,10 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
.filter(it => it.section == ROLLDIALOG_SECTION.ACTION)
.filter(it => it.isActive(rollData))
.map(it => it.title(rollData))
.filter(it => it != undefined)
.reduce(Misc.joining(' '));
if (this.rollOptions.title) {
return `${this.rollOptions.title} ${title}`
return `${this.rollOptions.title}: ${title}`
}
return title
}
@@ -478,17 +480,14 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
.map(m => m.toTypeData(rollData))
RollBasicParts.loadSurprises(rollData, this.getSelectedType().code)
rollData.type.label = this.getSelectedType()?.title(rollData)
const visibleRollParts = this.getActiveParts()
visibleRollParts.forEach(p => p.applyExternalImpacts(visibleRollParts, rollData))
this.setSpecialComp(visibleRollParts);
visibleRollParts.forEach(p => p.prepareContext(rollData))
this.getActiveParts().forEach(p => p.applyExternalImpacts(this.getActiveParts(), rollData))
this.setSpecialComp(this.getActiveParts());
this.getActiveParts().forEach(p => p.prepareContext(rollData))
RollDialog.calculAjustement(rollData)
const templates = visibleRollParts.map(p => p.toTemplateData())
const templates = this.getActiveParts().map(p => p.toTemplateData())
const context = await super._prepareContext()
return foundry.utils.mergeObject(
{
@@ -569,7 +568,7 @@ export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2
}
async defaultCallback(roll, rolled) {
await roll.active.actor.appliquerAjoutExperience(roll)
await roll.active.actor.ajoutExperience(roll)
await roll.active.actor.appliquerAppelMoral(roll)
}
+2 -1
View File
@@ -8,7 +8,8 @@ export class RollPartAction extends RollPart {
get section() { return ROLLDIALOG_SECTION.ACTION }
title(rollData) {
return rollData.type.label
const current = this.getCurrent(rollData)
return current.verb
}
prepareContext(rollData) {
+2 -1
View File
@@ -1,4 +1,5 @@
import { Grammar } from "../grammar.js"
import { CARACS } from "../rdd-carac.js"
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
import { ROLL_TYPE_SORT } from "./roll-constants.mjs"
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
@@ -20,7 +21,7 @@ export class RollPartAstrologique extends RollPartCheckbox {
}
isJetChance(rollData) {
return Grammar.includesLowerCaseNoAccent(rollData.current.carac.key, 'chance')
return Grammar.includesLowerCaseNoAccent(rollData.current.carac.key, CARACS.CHANCE)
}
$isUsingAstrologie() {
+5 -2
View File
@@ -35,7 +35,8 @@ export class RollPartAttaque extends RollPartSelect {
loadRefs(rollData) {
const refs = this.getRefs(rollData)
const attaques = rollData.active.actor.listAttaques()
const attaques = rollData.active.actor.listActions()
.filter(it => !it.initOnly)
.sort(Misc.descending(it => it.comp?.system.niveau ?? -8))
refs.all = attaques.map(it => RollPartAttaque.$extractAttaque(it, rollData))
this.filterAttaquesInitiative(rollData)
@@ -186,7 +187,9 @@ export class RollPartAttaque extends RollPartSelect {
part.setDiff(rollData, { type: DIFF.DEFAUT })
}
else {
part.setDiff(rollData, { type: DIFF.ATTAQUE, diff: current.initialDiff })
if (!rollData.type.appelChance){
part.setDiff(rollData, { type: DIFF.ATTAQUE, diff: current.initialDiff })
}
current.initialDiff = undefined
}
break
+6 -3
View File
@@ -27,7 +27,7 @@ export class RollPartComp extends RollPartSelect {
const selected = this.getSelected(rollData)
const all = this.$getActorComps(rollData)
const selectedComp = selected.key
if (selected.forced && selectedComp) {
if (selected.forced && selectedComp!= undefined ) {
refs.all = all.filter(comp => Grammar.equalsInsensitive(comp.label, selectedComp))
if (refs.all.length == 0) {
if (selected.key && selected.key.length > 0) {
@@ -47,8 +47,11 @@ export class RollPartComp extends RollPartSelect {
const current = this.getCurrent(rollData)
const selectedCarac = RollPart.getSelectedPart(rollData, PART_CARAC)
const selectedDiff = RollPart.getSelectedPart(rollData, PART_DIFF)
this.rollPartCarac.selectByKey(rollData, selectedCarac?.key ?? current.comp.system.defaut_carac)
this.rollPartDiff.setDiff(rollData, selectedDiff?.value ?? current.comp.system.default_diffLibre)
if (!rollData.type.appelChance){
this.rollPartCarac.selectByKey(rollData, selectedCarac?.key ?? current.comp.system.defaut_carac)
this.rollPartDiff.setDiff(rollData, selectedDiff?.value ?? current.comp.system.default_diffLibre)
}
}
}
+6
View File
@@ -10,6 +10,11 @@ export class RollPartConditions extends RollPart {
settingMin() { return RollPart.settingKey(this, 'min') }
settingMax() { return RollPart.settingKey(this, 'max') }
visible(rollData) {
const current = this.getCurrent(rollData)
return !current.hide
}
onReady(rollParts) {
game.settings.register(SYSTEM_RDD, this.settingMin(),
{
@@ -36,6 +41,7 @@ export class RollPartConditions extends RollPart {
restore(rollData) {
const current = this.getCurrent(rollData)
current.value = this.getSaved(rollData)?.value ?? current.value ?? 0
current.hide = this.getSaved(rollData)?.hide
}
+27 -14
View File
@@ -1,6 +1,6 @@
import { ITEM_TYPES } from "../constants.js"
import { CARACS } from "../rdd-carac.js"
import { ROLL_TYPE_CUISINE } from "./roll-constants.mjs"
import { ROLL_TYPE_CUISINE, RollConstants } 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"
@@ -18,7 +18,11 @@ export class RollPartCuisine extends RollPartSelect {
get rollTypes() { return [ROLL_TYPE_CUISINE] }
isValid(rollData) { return rollData.active.actor.isPersonnage() }
isValid(rollData) {
return rollData.active.actor.isPersonnage()
&& RollConstants.findCompetence(rollData, 'Cuisine')
}
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_CUISINE) }
restore(rollData) {
@@ -38,19 +42,22 @@ export class RollPartCuisine extends RollPartSelect {
loadRefs(rollData) {
const refs = this.getRefs(rollData)
const actor = rollData.active.actor
refs.cuisine = actor.getCompetence('Cuisine')
refs.cuisine = RollConstants.findCompetence(rollData, 'Cuisine')
const recettes = actor.items
if (!refs.cuisine) {
refs.preparations = []
return
}
const recettes = rollData.active.actor.items
.filter(it => it.type == ITEM_TYPES.recettecuisine)
.map(RollPartCuisine.$extractPreparationRecette)
.map(it => RollPartCuisine.$extractPreparationRecette(refs.cuisine, it))
const ingredientsBruts = actor.items
const ingredientsBruts = rollData.active.actor.items
.filter(it => it.getUtilisationCuisine() == 'brut')
.map(RollPartCuisine.$extractPreparationBrut)
.map(it => RollPartCuisine.$extractPreparationBrut(refs.cuisine, it))
refs.preparations = [RollPartCuisine.$preparationBasique(), ...recettes, ...ingredientsBruts]
refs.preparations.forEach(p => p.comp = refs.cuisine)
refs.preparations = [RollPartCuisine.$preparationBasique(refs.cuisine), ...recettes, ...ingredientsBruts]
if (refs.preparations.length > 0) {
this.$selectPreparation(rollData)
this.$restoreSavedOptions(rollData)
@@ -73,7 +80,7 @@ export class RollPartCuisine extends RollPartSelect {
choices(refs) { return refs.preparations }
static $preparationBasique() {
static $preparationBasique(cuisine) {
return {
key: '',
label: "Improvisation du moment",
@@ -85,10 +92,12 @@ export class RollPartCuisine extends RollPartSelect {
proportionsMax: 50,
value: 0,
fabriquer: false,
qualite: cuisine.system.niveau,
comp: cuisine,
}
}
static $extractPreparationRecette(recette) {
static $extractPreparationRecette(cuisine, recette) {
const proportions = recette.system.sust ?? 1
return {
key: recette.id,
@@ -102,10 +111,12 @@ export class RollPartCuisine extends RollPartSelect {
value: -recette.system.niveau,
recette: recette,
fabriquer: true,
qualite: recette.system.niveau,
comp: cuisine,
}
}
static $extractPreparationBrut(ingredient) {
static $extractPreparationBrut(cuisine, ingredient) {
return {
key: ingredient.id,
label: ingredient.name + ' cuisiné',
@@ -118,6 +129,8 @@ export class RollPartCuisine extends RollPartSelect {
value: 0,
ingredient: ingredient,
fabriquer: true,
qualite: cuisine.system.niveau,
comp: cuisine,
}
}
@@ -150,7 +163,7 @@ export class RollPartCuisine extends RollPartSelect {
this.$selectPreparation(rollDialog.rollData, selectOptions[index]?.value)
rollDialog.render()
})
checkboxFabriquer?.addEventListener("change", e => {
current.fabriquer = e.currentTarget.checked
})
+5 -1
View File
@@ -131,7 +131,11 @@ export class RollPartDefense extends RollPartSelect {
switch (part.code) {
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_DIFF:
if (!rollData.type.appelChance) {
return part.setDiff(rollData, this.getDiffDefense(rollData))
}
return
case PART_SIGN: return part.setArme(rollData, this.getArmeDisparate(rollData), current.forceRequise)
}
}
+2 -2
View File
@@ -14,7 +14,7 @@ const EXCLUDED_ROLL_TYPES = [
export class RollPartDiff extends RollPart {
get code() { return PART_DIFF }
get section() { return ROLLDIALOG_SECTION.CHOIX }
get section() { return ROLLDIALOG_SECTION.CONDITIONS }
restore(rollData) {
const current = this.getCurrent(rollData)
@@ -37,7 +37,7 @@ export class RollPartDiff extends RollPart {
}
const current = this.getCurrent(rollData)
/* TODO: affiner les cas où afficher ou non. devrait s'afficher pour les jets basiques (même si pas d'opposant sélectionné)*/
return Object.values(DIFF).includes(current.type)
return (DIFF.AUCUN !=current.type) && Object.values(DIFF).includes(current.type)
}
prepareContext(rollData) {
+18 -13
View File
@@ -1,13 +1,12 @@
import { ITEM_TYPES } from "../constants.js"
import { CARACS } from "../rdd-carac.js"
import { ROLL_TYPE_JEU } from "./roll-constants.mjs"
import { ROLL_TYPE_JEU, RollConstants } 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, 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"
@@ -19,15 +18,21 @@ export class RollPartJeu extends RollPartSelect {
get section() { return ROLLDIALOG_SECTION.CHOIX }
get rollTypes() { return [ROLL_TYPE_JEU] }
isValid(rollData) { return rollData.active.actor.isPersonnage() }
isValid(rollData) {
return rollData.active.actor.isPersonnage()
&& RollConstants.findCompetence(rollData, 'Jeu')
}
visible(rollData) { return RollPart.isRollType(rollData, ROLL_TYPE_JEU) }
loadRefs(rollData) {
const refs = this.getRefs(rollData)
const actor = rollData.active.actor
const compJeu = actor.getCompetence(COMPETENCE_JEU)
refs.jeux = actor.itemTypes[ITEM_TYPES.jeu]
const compJeu = RollConstants.findCompetence(rollData, 'Jeu')
if (!compJeu) {
refs.jeux = []
return
}
refs.jeux = rollData.active.actor.itemTypes[ITEM_TYPES.jeu]
.map(it => RollPartJeu.$extractJeu(it, compJeu))
if (refs.jeux.length > 0) {
@@ -51,22 +56,22 @@ export class RollPartJeu extends RollPartSelect {
}
}
static $getJeuBase(jeu, comp, caracs) {
if (jeu.system.base < comp.system.niveau) {
static $getJeuBase(jeu, compJeu, caracs) {
if (jeu.system.base < compJeu.system.niveau) {
return undefined
}
return new RdDItem({
id: comp.id,
id: compJeu.id,
name: `Jeu ${Misc.lowerFirst(jeu.name)}`,
type: ITEM_TYPES.competence,
img: comp.img,
img: compJeu.img,
system: foundry.utils.mergeObject(
{
niveau: jeu.system.base,
base: jeu.system.base,
default_carac: caracs.length > 0 ? caracs[0] : CARACS.CHANCE
},
comp.system,
compJeu.system,
{ overwrite: false }
)
})
@@ -90,7 +95,7 @@ export class RollPartJeu extends RollPartSelect {
static forceCompJeu(rollData) {
const jeu = rollData.current[PART_JEU].base ?? rollData.current[PART_JEU].comp
if (jeu){
if (jeu) {
rollData.refs[PART_COMP].comps = [jeu].map(it => RollPartComp.extractComp(it))
}
else {
+1 -1
View File
@@ -30,7 +30,7 @@ export class RollPartPossession extends RollPartSelect {
choices(refs) { return refs.all }
$getActorConjurations(rollData) {
const competences = rollData.active.actor.getDraconicOuPossession()
const competences = rollData.active.actor.getBestDraconic({possession: true})
return competences.map(RollPartPossession.extractPossession)
}
+9 -4
View File
@@ -28,7 +28,8 @@ export class RollPartSort extends RollPartSelect {
this.setCurrent(rollData, {
key: saved.key,
isReserve: saved.isReserve,
ptreve: saved.ptreve
ptreve: saved.ptreve,
value: saved.value,
})
}
@@ -37,7 +38,8 @@ export class RollPartSort extends RollPartSelect {
this.setSaved(targetData, {
key: current.key,
isReserve: current.isReserve,
ptreve: current.ptreve
ptreve: current.ptreve,
value: current.value,
})
}
@@ -98,7 +100,7 @@ export class RollPartSort extends RollPartSelect {
const sort = { label: current.label, value: current.value }
const reserve = current.isReserve ? [{ label: `Mise en réserve en ${this.getCoord(rollData)}` }] : []
const bonusCase = current.bonusCase ? [{ label: `Bonus case +${current.bonusCase}%` }] : []
const reve = { label: `Rêve ${current.ptreve}` }
const reve = { label: `Dépense de rêve ${current.ptreve}` }
return [sort, ...bonusCase, reve, ...reserve]
}
return []
@@ -106,9 +108,12 @@ export class RollPartSort extends RollPartSelect {
$selectSort(rollData, values) {
const current = this.selectByKey(rollData, values.key)
if (values.ptreve) {
if (values.ptreve != undefined) {
current.ptreve = values.ptreve
}
if (current.isDiffVariable && values.value != undefined) {
current.value = values.value
}
if (values.isReserve != undefined) {
current.isReserve = values.isReserve
}
+13 -7
View File
@@ -22,8 +22,8 @@ export class RollPartTache extends RollPartSelect {
refs.forced = selected.forced
refs.all = rollData.active.actor.itemTypes[ITEM_TYPES.tache]
.filter(tache => !selected.forced || tache.id == selected.key)
.filter(tache => tache.system.points_de_tache_courant < tache.system.points_de_tache)
.map(tache => RollPartTache.$extractTache(tache, rollData.active.actor))
.filter(extract => !extract.finished)
refs.taches = refs.all
if (refs.taches.length > 0) {
@@ -34,12 +34,15 @@ export class RollPartTache extends RollPartSelect {
choices(refs) { return refs.taches }
static $extractTache(tache, actor) {
const tacheOuCommune = tache.getTacheOuCommune()
return {
key: tache.id,
label: tache.name,
value: tache.system.difficulte,
tache: tache,
comp: actor.getCompetence(tache.system.competence)
tacheCommune: tache.system.tacheCommune,
value: tacheOuCommune.system.difficulte,
tache: tacheOuCommune,
comp: actor.getCompetence(tacheOuCommune.system.competence),
finished: tacheOuCommune.system.points_de_tache_courant >= tacheOuCommune.system.points_de_tache
}
}
@@ -81,9 +84,12 @@ export class RollPartTache extends RollPartSelect {
}
onCreateUpdateItem(rollDialog, item, options, id) {
if (item.type == ITEM_TYPES.tache && item.parent?.id == rollDialog.rollData.active.actor.id) {
this.loadRefs(rollDialog.rollData)
rollDialog.render()
if (item.type == ITEM_TYPES.tache) {
if (item.parent?.id == rollDialog.rollData.active.actor.id || item.isTacheCommune()) {
// TODO: filtrer davantage
this.loadRefs(rollDialog.rollData)
rollDialog.render()
}
}
}

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