Compare commits

..

124 Commits

Author SHA1 Message Date
15510b99d8 Merge pull request 'feature/v13-corrections' (#794) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 2m45s
Reviewed-on: https, #794
2026-01-19 21:44:59 +01:00
fa30705989 Affichage de l'XP des sorts et caractéristiques 2026-01-17 03:45:42 +01:00
04f550dd21 Fix jet de résistance V2
sans cométence s'il n'y a pas de sélection
2026-01-16 08:47:51 +01:00
850cae3979 Attaques V2 depuis onglet combat 2026-01-16 08:47:50 +01:00
7b514d5159 Background arme inutilisable 2026-01-14 23:55:03 +01:00
d78ede4f59 Fix missing import 2026-01-14 23:47:01 +01:00
3de00fd001 Merge pull request 'Correction chat appel moral' (#793) from feature/v13-corrections into v13
All checks were successful
Release Creation / build (release) Successful in 2m28s
Reviewed-on: https, #793
2026-01-13 22:08:14 +01:00
1b340e526c Simplifications en cherchant bug rêve actuel
Parfois, le rêve actuel est ajouté dans les caractéristiques des
feuilles de personnage.

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

Cas plus étrange, un jet de chance alors que le jet sauvegardé
n'avait pas d'actorId
2025-12-11 03:12:48 +01:00
894161c0bf Fix: Encombrement décimal 2025-12-11 03:12:48 +01:00
6882b4819c Correction: ajout de notes 2025-12-11 03:12:48 +01:00
275c144ea2 Préparation v13.0.22 2025-12-11 03:12:48 +01:00
3c5cfbb609 Merge pull request 'v13.0.21 - La folie d'Illysis' (#786) from feature/v13-possession-v2 into v13
All checks were successful
Release Creation / build (release) Successful in 3m21s
Reviewed-on: https, #786
2025-12-08 20:23:57 +01:00
36c771518d v13.0.21 2025-12-08 20:12:17 +01:00
dd7a3700dc Appréciation des services 2025-12-08 20:10:56 +01:00
f0736015a7 Surcharge de couleurs de style
Les titres dans les descriptions n'étaient pas bien affichés dans la
fenêtre de jet
2025-12-08 19:40:21 +01:00
aae603d798 Appréciation de plats 2025-12-08 19:39:21 +01:00
d9bc6309fb Correction des bonus des Cyans 2025-12-08 01:42:57 +01:00
c14361919c Update compendiums 2025-12-08 01:42:55 +01:00
b26c39cf21 Ajout des options d'appréciation
L'appréciation utilise:

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

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

Ajout des jets de moral très heureux.

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

- le défenseur diminue le nombre de points d'empoignade
- amélioration des messages liés à l'empoignade
- ajout de choix de pertes d'endurance à infliger
2025-11-24 18:04:43 +01:00
3f19886342 Fix affichage sur perte d'endurance
décaller l'ajout d'effets après l'update permet
d'éviter les résultats "invisibles"
2025-11-24 18:04:43 +01:00
9a5afc918e Fix suppression effets 2025-11-24 18:04:43 +01:00
2ac35ef5d1 Corrections de styles incorrects
- combo de sélection des dommages d'empoignade
- boutons de navigation dans les journaux
- boutons de blessures dans la feuille de personnage
2025-11-24 18:04:42 +01:00
33c6b35601 Merge pull request '## 13.0.19 - L'introspection d'Illysis' (#784) from feature/v13-combats-v2 into v13
All checks were successful
Release Creation / build (release) Successful in 2m10s
Reviewed-on: https, #784
2025-11-14 17:46:26 +01:00
82f870db05 Bouton pour jet de résistance
Ajout d'un bouton à côté de la carac rêve
2025-11-13 01:13:47 +01:00
878efab321 Correction expérience sur résistance 2025-11-13 00:10:08 +01:00
659ddbd0a4 Jet V2 - Ajout des écailles 2025-11-12 23:09:10 +01:00
22b9e11021 Correction particulières 2025-11-12 22:21:27 +01:00
02ec8880fc Correction combat V2 avec plusieurs joueurs
Les messages de défense fonctionnent sur les jets V2
2025-11-12 22:10:51 +01:00
521cf50b7b Pas de suppression surenc/demireve
L'icône surencombrement ne peut plus être supprimée si on est
sur-encombré.
2025-11-12 22:10:51 +01:00
1cc6fab3a9 Autoriser attaque sans initiative 2025-11-12 22:10:51 +01:00
7baccbabb9 Gestion des droits jets V2 2025-11-12 22:10:42 +01:00
d9b24b0f97 Correction sur changelog
All checks were successful
Release Creation / build (release) Successful in 2m37s
2025-11-12 15:21:43 +01:00
d504a0e131 Merge pull request '13.0.17 - Le reflet d'Illysis' (#783) from feature/v13-mineurs into v13
Reviewed-on: https, #783
2025-11-12 15:19:43 +01:00
09ca86a7fd Suppression de message d'erreur
Si un acteur n'a pas toutes les compétences (ie: invocation), les
messages indiquant que les compétences sont manquantes ne
sont plus affichés
2025-11-11 23:09:28 +01:00
5b68837023 Ajout icone service écuries 2025-11-11 23:09:28 +01:00
7452c54c04 Feuille personnage avec police 2025-11-11 23:09:28 +01:00
af1976b9d8 Update release script
All checks were successful
Release Creation / build (release) Successful in 1m32s
2025-11-08 00:44:16 +01:00
9fe45ce99f Update release script
Some checks failed
Release Creation / build (release) Failing after 1m14s
2025-11-08 00:33:26 +01:00
852964e77b Update release script
Some checks failed
Release Creation / build (release) Failing after 1m32s
2025-11-08 00:29:16 +01:00
b87dea1661 Update release script
Some checks failed
Release Creation / build (release) Failing after 2m22s
2025-11-08 00:24:27 +01:00
d2835c7472 Update release script
Some checks failed
Release Creation / build (release) Failing after 52s
2025-11-08 00:22:18 +01:00
f3c58424e5 Update release script
Some checks failed
Release Creation / build (release) Failing after 5s
2025-11-08 00:06:19 +01:00
c600eb3965 Update release script
Some checks failed
Release Creation / build (release) Has been cancelled
2025-11-08 00:04:57 +01:00
4a7848cb04 Fix other CSS dakr/light theme issues
Some checks failed
Release Creation / build (release) Has been cancelled
2025-11-08 00:02:51 +01:00
0d62b60e38 Merge pull request 'v13.0.16 - La paix d'Illysis' (#782) from VincentVk/foundryvtt-reve-de-dragon:v13 into v13
Reviewed-on: https://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/pulls/782
2025-11-02 09:55:25 +01:00
9b91850731 Export de personnage en pdf
Première version d'export de personnage pdf
2025-11-01 01:28:44 +01:00
05c7a91f93 Correction d'un problème à l'ouverture
Pour un personnage saisis dans d'anciennes versions avec un sort
de coût entier, la feuille de personnage ne pouvait pas s'ouvrir
2025-11-01 00:44:26 +01:00
f83fdb3b8f Fix: fenêtre jets V2 hors combat
la fenêtre ne marchait pas hors d'un combat
2025-10-29 02:03:43 +01:00
1344 changed files with 122275 additions and 12415 deletions

View File

@@ -6,71 +6,70 @@ on:
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: localhost
steps: steps:
- run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner." - run: echo "💡 The ${{ gitea.repository }} repository will cloned to the runner."
#- uses: actions/checkout@v3 - name: Add NODE/NPM bin directory to PATH
- uses: RouxAntoine/checkout@v3.5.4 shell: bash
with: run: echo "/opt/alt/alt-nodejs20/root/usr/bin/" >> $GITHUB_PATH
ref: 'v13'
# get part of the tag after the `v` - uses: RouxAntoine/checkout@v3.5.4
- name: Extract tag version number with:
id: get_version ref: "v13"
uses: battila7/get-version-action@v2
# Substitute the Manifest and Download URLs in the module.json # get part of the tag after the `v`
- name: Substitute Manifest and Download Links For Versioned Ones - name: Extract tag version number
id: sub_manifest_link_version id: get_version
uses: microsoft/variable-substitution@v1 uses: battila7/get-version-action@v2
with:
files: 'system.json'
env:
version: ${{steps.get_version.outputs.version-without-v}}
url: https://www.uberwald.me/gitea/${{gitea.repository}}
manifest: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/system.json
download: https://www.uberwald.me/gitea/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/rddsystem.zip
- name: Set up Node.js # Substitute the Manifest and Download URLs in the module.json
uses: actions/setup-node@v2 - name: Substitute Manifest and Download Links For Versioned Ones
with: id: sub_manifest_link_version
node-version: '18' # Use the node version your project requires uses: microsoft/variable-substitution@v1
with:
files: "system.json"
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
download: https://gitea.scriptarium.org/${{gitea.repository}}/releases/download/${{github.event.release.tag_name}}/rddsystem.zip
- name: Install dependencies - name: Set up Node.js
run: npm install uses: actions/setup-node@v2
with:
node-version: "18" # Use the node version your project requires
- name: Build the compendiums - name: Install dependencies
run: node ./tools/packCompendiumsToDist.mjs run: npm install
# Create a zip file with all files required by the module to add to the release - name: Build the compendiums
- run: | run: node ./tools/packCompendiumsToDist.mjs
apt update -y
apt install -y zip
- run: zip -r ./rddsystem.zip system.json template.json README.md LICENSE.txt assets/ css/ fonts/ icons lang/ module/ packs/ pic/ sounds/ styles/ templates/ - name: Create ZIP file
run: zip -r ./rddsystem.zip system.json template.json README.md LICENSE.txt assets/ css/ fonts/ icons lang/ module/ packs/ pic/ sounds/ styles/ templates/
- name: setup go - name: setup go
uses: actions/setup-go@v3 uses: actions/setup-go@v3
with: with:
go-version: '>=1.20.1' go-version: ">=1.20.1"
- name: Use Go Action - name: Use Go Action
id: use-go-action id: use-go-action
uses: https://gitea.com/actions/release-action@main uses: https://gitea.com/actions/release-action@main
with: with:
files: |- files: |-
./rddsystem.zip ./rddsystem.zip
system.json system.json
api_key: '${{secrets.ALLOW_PUSH_RELEASE}}' api_key: "${{secrets.RDD_PUBLISH_RELEASE}}"
- name: Publish to Foundry server - name: Publish to Foundry server
uses: djlechuck/foundryvtt-publish-package-action@v1 uses: djlechuck/foundryvtt-publish-package-action@v1
with: with:
token: ${{ secrets.FOUNDRYVTT_RELEASE_TOKEN }} token: ${{ secrets.RDD_PUBLISH_RELEASE_FOUNDRY }}
id: 'foundryvtt-reve-de-dragon' id: "foundryvtt-reve-de-dragon"
version: ${{github.event.release.tag_name}} version: ${{github.event.release.tag_name}}
manifest: 'https://www.uberwald.me/gitea/${{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://www.uberwald.me/gitea/public/foundryvtt-reve-de-dragon/raw/branch/v13/changelog.md' notes: "https://gitea.scriptarium.org/Scriptarium/foundryvtt-reve-de-dragon/raw/branch/v13/changelog.md"
compatibility-minimum: '13' compatibility-minimum: "13"
compatibility-verified: '13' compatibility-verified: "13"

View File

@@ -25,4 +25,7 @@ Merci à eux !!
Toute la propriété intellectuelle leur appartient, ce système est une adaptation destinée à fonctionner sous FoundryVTT. Toute la propriété intellectuelle leur appartient, ce système est une adaptation destinée à fonctionner sous FoundryVTT.
L'ensemble du code est sous licence Creative Commons. L'ensemble du code est sous licence Creative Commons.
# Licences
- L'export pdf utilise la librairie [pdf-lib](https://pdf-lib.js.org/) sous licence [MIT](pdf-lib-LICENSE.md)

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><defs><linearGradient x1="0" x2="1" y1="1" y2="0" id="lorc-shattered-sword-gradient-4"><stop offset="0%" stop-color="#4a4a4a" stop-opacity="1"></stop><stop offset="100%" stop-color="#c9c9c9" stop-opacity="1"></stop></linearGradient><radialGradient id="lorc-shattered-sword-gradient-5"><stop offset="0%" stop-color="#9013fe" stop-opacity="1"></stop><stop offset="100%" stop-color="#85562c" stop-opacity="1"></stop></radialGradient><radialGradient id="lorc-shattered-sword-gradient-7"><stop offset="0%" stop-color="#9013fe" stop-opacity="1"></stop><stop offset="100%" stop-color="#85562c" stop-opacity="1"></stop></radialGradient></defs><g class="" transform="translate(1,-2)" style=""><path d="m496.223 16.818-48.475 44.205 48.475 4.575v-48.78zm-41.55 1.22-68.91 11.28-7.04 65.547 75.95-76.828zM352.26 77.907l-87.887 50.3 15.447 41.026 82.662-16.87-10.222-74.456zm64.34 25.022-32.967 67.443 24.842 70.684 54.314-134.19-46.19-3.937zm-271.362 72.808c-10.02.155-20.714 3.165-30.79 9.057 4.143 8.863 3.382 18.708-2.776 24.873-6.158 6.165-15.993 6.927-24.846 2.78-12.923 22.167-11.88 47.34 2.485 61.73l29.84-29.87c58.655 42.87 109.37 92.94 150.57 151.24l-36.19 36.23 6.61-6.604c14.283 14.298 39.192 15.42 61.23 2.732-4.88-9.197-4.366-19.74 2.107-26.22 6.47-6.478 17-6.993 26.185-2.112 12.66-22.062 11.54-47-2.732-61.3l-28.248 28.28c-57.035-42.41-107.91-92.665-151.426-150.386l35.455-35.492-6.61 6.603c-7.834-7.843-18.863-11.726-30.862-11.542zm108.45 4.512c-17.61 17.41-39.674 39.21-62.22 61.375a728.952 728.952 0 0 0 27.407 30.094l59.063-59.126-24.25-32.344zm78.28 32.688L297 219.968l-65 65.063a728.12 728.12 0 0 0 35 32.376c22.02-23.134 43.764-46.41 64.97-69.406v-35.063zM173.47 313.25c-31.146 40.858-67.877 74.323-108.905 101.875 4.13 13.708 16.394 26.374 30.624 30.563 29.466-41.26 61.113-79.902 100.97-109.97a637.777 637.777 0 0 0-22.688-22.468zM44.5 410.28l-20.844 20.845c7.133 24.65 27.843 44.912 53.72 53.438l19.28-19.313c-26.948-4.28-48.314-26.91-51.875-52.938l-.28-2.03z" fill="#fff" fill-opacity="1" transform="translate(51.2, 51.2) scale(0.8, 0.8) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

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

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

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

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

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

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

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

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

View File

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

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

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

Before

Width:  |  Height:  |  Size: 28 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

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

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

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -1,4 +1,154 @@
# 13.0 # 13.0
## 13.0.29 - Le tricorne d'Illysis
- gestion des attaques avec jets V2 depuis l'onglet de combat
- les jets de résistance en mode V2 fonctionnent sans sélection de compétence
- affichage de l'expérience correspondant aux sorts pour aider à la création
- affichage de l'équivallent d'expérience des caractéristiques
## 13.0.28 - La quadrature d'Illysis
- Les ajustements de portée sont calculés pour les attaques à distance
- L'appel au moral dans le tchat ne déplace plus les boutons d'appel à la chance
- Correction d'apparence V13
- la fenêtre de choix des status utilisés est affichée correctement
- la fenêtrre d'astrologir MJ est affichée correctement
## 13.0.27 - Les lunettes d'Illysis
- Les heures ne sont plus affichées en doublon sur les messages
- Les conteneurs ouverts sont mis à jour si leur contenu change
- Le style des icones d'objets est homogénéisé
- Ajout d'icônes: coffre, tissu de soie, parchemin
- Amélioration des choix d'actions de combat
- le choix d'initiative limite les attaques disponibles
- les compétences sont triées dans l'ordre décroissant
## 13.0.26 - La ménagerie d'Illysis
- Correction: on peut de nouveau modifier les caractéristiques des créatures
## 13.0.24 - Le grand oubli d'Illysis
- ajout d'un bouton pour supprimer les anciens messages du tchat
- correction de messages d'erreur 'User ... lacks permission' / 'Active Effect ... does not exist'
- les joueurs peuvent affecter leurs enchantements aux objets enchantables de leur équipement
- correction des boutons pour lancer les maladresses
- utilisation des tables de compendium
- correction des droits pour mise à jour du message
- correction de la cuisine
- reprise de l'image de cuisine dans l'équipement
- prise en compte de la difficulté pour préparer la nourriture brute
## 13.0.23 - Le marché d'Illysis
- Améliorations
- lors de la consommation suite à un achat, les jets d'appréciation/éthylisme
sont faits par l'acheteur. Du coup, c'est lui qui lance le jet d'appréciation
(pour un service ou un plat de qualité), et ses dés sont utilisés avec dice-so-nice
- les créatures ont le statut Inconscient quand leur endurance est à 0
- Fenêtre de jets V2
- les soins de blessures sont correctement appliqués
- correction d'affichage jet sans compétence/avec compétence
- correction de la prise en compte des tactiques
- correction du filtrage des défenses selon l'attaque
- lorsque le mode de visibilité des jets général est changé, les fenêtres de jets suivent ce changement
## 13.0.22 - Les reflets d'Illysis
- Améliorations
- Changements d'icones pour les Acteurs et Scènes
- Corrections diverses
- l'encombrement total est affiché avec deux décimales
- le poids des monnaies est de nouveau décimal
- Erreurs de typographie diverses
- Mise en réserve de sort par le Gardien
- Fenêtre de jets V2
- utilisation pour les jets quelconques
- la fenêtre de jet pour les jets depuis un lien texte
- affichage des ajustements dans la fenêtre d'attaque avec arme à distance
- gestion des défenses contre les armes à distance
- pas de tactiques pour les attaques à distance
- attaque depuis l'onglet combat de la feuille de personnage, sans token sélectionné
- défense contre possession
- correction du mode "méditation" quand le haut-rêvant ne connait pas de méditation
- correction du mode "jeu" quand le personnage ne connait pas de jeux
- correction du mode "oeuvre" quand le personnage ne connait pas d'oeuvres
- Corrections liées à Foundry v12/v13
- Fix ajout de notes dans le journal par un joueur (/chrono, ou clic sur le libelé de l'heure dans l'horloge)
## 13.0.21 - La folie d'Illysis
- Jets d'appréciation et de moral
- concerne la danse, musique, chant, jeu, les oeuvres, la nourriture, les services
- gestion des compétences d'appréciation pour les oeuvres
- pas de jet de moral si la qualité n'est pas suffisante (inférieure au moral,
à la compétence, moral déjà gagné pour la même raison)
- jet d'appréciation avec en option la compétence et la qualité
- jet de moral très heureux (pour Spasme)
- les jets de moral sont liés à des "bon moments"
- la liste des bons moments passés par un acteur est remise à zéro à Château Dormant
- Fenêtre de jet v2
- les possessions sont maintenant gérées avec les fenêtres V2
- on peut choisir sa voie de draconic pour contrer une possession ou conjurer
- La zone de saisie dans les journaux est mieux adaptée
- Correction des bonus de caractéristiques des cyans
## 13.0.20 - L'immobilisme d'Illysis
- Centrage du logo de pause
- Ajout d'un statut malade/empoisonné
- Fenêtre de jet v2
- correction du compteur empoignade
- amélioration des messages liés à l'empoignade
- amélioration des choix de perte d'endurance
- correction de la dépense de rêve sur lancement de sort
- ajustement astrologique sur rituels
## 13.0.19 - L'introspection d'Illysis
- Ajout d'un bouton pour les jets de résistance sous rêve actuel
- Fenêtre de jet v2
- restrictions au propriétaire du personnage
- ouverture de la fenêtre de jets
- appel à la chance
- appel à la destinée
- fermeture par défaut selon le type de jets:
- jets d'attaque
- jets de défense
- jets imposés par un choix d'action
- lancer de sorts
- jets suite à appel à la chance
- gestion des écailles d'efficacité sur les armes
- permettre de faire une attaque même si l'initiative n'est pas faite
- les messages de défense s'affichent correctement avec plusieurs joueurs
- les particulières en force/rapidité sont correctement affichées dans le tchat
- l'expérience sur jet de résistance est limitée à 1 point
## 13.0.18 - Le reflet d'Illysis
- Mise à jour de la feuille de personnage pdf template (avec police correcte)
- Ajout d'une icône "écurie" pour les services des commerces & auberges
- Suppression de message d'erreur sur compétence
manquante à l'ouverture des acteurs d'invocation
## 13.0.17 - Le chant d'Illysis
- Corrections CSS
- Migration Uberwald -> Scriptarium
## 13.0.16 - La paix d'Illysis
- Export de personnages sous forme de feuille de personnage pdf
- Correction d'un problème à l'ouverture de personnages saisis dans d'anciennes versions
- Fenêtre de jet v2
- on peut faire des jets en dehors des combats
## 13.0.15 - Les pièces d'Illysis ## 13.0.15 - Les pièces d'Illysis
- On peut de nouveau acheter dans les commerces - On peut de nouveau acheter dans les commerces
@@ -91,7 +241,7 @@
- ajout d'un status "Force insuffisante" - ajout d'un status "Force insuffisante"
- clarification des maladresses à l'attaque (en demi surprise, ou à cause d'un échec total) - clarification des maladresses à l'attaque (en demi surprise, ou à cause d'un échec total)
- Nouvelle fenêtre de jets de dés - Nouvelle fenêtre de jets de dés
- ajout du statut "Force insuffisante" aux acteurs si la - ajout du statut "Force insuffisante" aux acteurs si la
force est insuffisante pour l'arme force est insuffisante pour l'arme
- avancement du mode attaque - avancement du mode attaque
- choix de tactique - choix de tactique

View File

@@ -60,10 +60,14 @@
/* Fonts */ /* Fonts */
.sheet header.sheet-header h1 input, .sheet header.sheet-header h1 input,
.window-app .window-header, .window-app .window-header,
#actors .directory-list, #sidebar {
#navigation #scene-list .scene.nav-item {
font-family: "GoudyAcc"; font-family: "GoudyAcc";
} }
.sheet header.sheet-header h1 input .chat-message,
.window-app .window-header .chat-message,
#sidebar .chat-message {
font-family: "CaslonAntique";
}
/* For title, sidebar character and scene */ /* For title, sidebar character and scene */
.sheet nav.sheet-tabs, .sheet nav.sheet-tabs,
.window-app input, .window-app input,
@@ -71,17 +75,16 @@
.sheet header.sheet-header .flex-group-center.flex-fatigue, .sheet header.sheet-header .flex-group-center.flex-fatigue,
select, select,
.item-checkbox, .item-checkbox,
#sidebar, #players {
#players,
#navigation #nav-toggle {
font-family: "CaslonAntique"; font-family: "CaslonAntique";
/* For sheet parts; For nav and title */ /* For sheet parts; For nav and title */
} }
:root { body {
/* =================== 2. DEBUGGING HIGHLIGHTERS ============ */ /* =================== 2. DEBUGGING HIGHLIGHTERS ============ */
/* =================== 3. some constants ============ */ /* =================== 3. some constants ============ */
--fieldset-background: url(/ui/parchment.jpg); --fieldset-background: url(/ui/parchment.jpg);
--rdd-color-text-primary: hsla(0, 0%, 4%, 0.9); --rdd-color-text-primary: hsla(0, 0%, 4%, 0.9);
--color-text-primary: hsla(0, 0%, 4%, 0.9);
--rdd-input-background: hsla(0, 0%, 0%, 0.1); --rdd-input-background: hsla(0, 0%, 0%, 0.1);
--rdd-color-border-input: hsla(0, 0%, 0%, 0.2); --rdd-color-border-input: hsla(0, 0%, 0%, 0.2);
--rdd-bg-input: hsla(0, 0%, 100%, 0.1); --rdd-bg-input: hsla(0, 0%, 100%, 0.1);
@@ -99,7 +102,9 @@ select,
--gradient-warning: linear-gradient(150deg, hsla(32, 100%, 50%, 0.3), hsla(52, 60%, 50%, 0.1), hsla(32, 60%, 50%, 0.1), hsla(32, 100%, 50%, 0.3)); --gradient-warning: linear-gradient(150deg, hsla(32, 100%, 50%, 0.3), hsla(52, 60%, 50%, 0.1), hsla(32, 60%, 50%, 0.1), hsla(32, 100%, 50%, 0.3));
--gradient-silver-light: linear-gradient(30deg, rgba(61, 55, 93, 0.2), rgba(178, 179, 196, 0.1), rgba(59, 62, 63, 0.2), rgba(206, 204, 199, 0.1), rgba(61, 46, 49, 0.2)); --gradient-silver-light: linear-gradient(30deg, rgba(61, 55, 93, 0.2), rgba(178, 179, 196, 0.1), rgba(59, 62, 63, 0.2), rgba(206, 204, 199, 0.1), rgba(61, 46, 49, 0.2));
--gradient-daylight: conic-gradient(from 0deg, hsla(50, 100%, 80%, 0.7), hsla(30, 30%, 40%, 0.1) 25%, hsla(250, 50%, 40%, 0.1) 25%, hsla(250, 30%, 30%, 0.7) 50%, hsla(250, 50%, 40%, 0.1) 75%, hsla(30, 30%, 40%, 0.1) 75%, hsla(50, 100%, 80%, 0.7)); --gradient-daylight: conic-gradient(from 0deg, hsla(50, 100%, 80%, 0.7), hsla(30, 30%, 40%, 0.1) 25%, hsla(250, 50%, 40%, 0.1) 25%, hsla(250, 30%, 30%, 0.7) 50%, hsla(250, 50%, 40%, 0.1) 75%, hsla(30, 30%, 40%, 0.1) 75%, hsla(50, 100%, 80%, 0.7));
--background-custom-button: linear-gradient(to bottom, hsla(208, 38%, 21%, 0.988) 5%, hsla(202, 42%, 14%, 0.671) 100%); --background-color-button: hsl(25, 5%, 60%);
--background-color-custom-button: hsla(208, 38%, 21%, 0.988);
--background-custom-button: linear-gradient(to bottom, var(--background-color-custom-button) 5%, hsla(202, 42%, 14%, 0.671) 100%);
--background-custom-button-hover: linear-gradient(to bottom, hsl(0, 100%, 25%) 5%, hsl(0, 97%, 12%) 100%); --background-custom-button-hover: linear-gradient(to bottom, hsl(0, 100%, 25%) 5%, hsl(0, 97%, 12%) 100%);
--background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%); --background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%);
--background-tooltip: hsla(60, 12%, 85%, 0.95); --background-tooltip: hsla(60, 12%, 85%, 0.95);
@@ -593,6 +598,9 @@ select,
font-size: 1.2rem; font-size: 1.2rem;
font-weight: bold; font-weight: bold;
} }
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section[name="resistance"] {
align-items: flex-end;
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section { .system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
@@ -607,6 +615,12 @@ select,
margin: 0 1rem; margin: 0 1rem;
padding: 0; padding: 0;
} }
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section img.flag-resistance {
max-width: 1.5rem;
max-height: 1.5rem;
text-align: right;
filter: invert(0.6);
}
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions { .system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@@ -674,7 +688,7 @@ select,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat { .system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat {
font-family: CaslonAntique; font-family: CaslonAntique;
display: grid; display: grid;
grid-template-areas: "img header buttons" "img resume buttons" "details details details" "actions actions actions"; grid-template-areas: "img header buttons" "img resume buttons" "details details details" "description description description" "actions actions actions";
grid-template-columns: 3rem 1fr 1.4rem; grid-template-columns: 3rem 1fr 1.4rem;
grid-template-rows: max-content max-content max-content max-content; grid-template-rows: max-content max-content max-content max-content;
gap: 0 0.5rem; gap: 0 0.5rem;
@@ -730,6 +744,17 @@ select,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-actions a img { .system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-actions a img {
margin-right: 0.5rem; margin-right: 0.5rem;
} }
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-description,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-description {
grid-area: description;
text-align: justify;
display: flex;
flex-direction: column;
}
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-description div,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-description div {
display: block;
}
.system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons, .system-foundryvtt-reve-de-dragon .chat-message div.roll-chat div.chat-buttons,
.system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-buttons { .system-foundryvtt-reve-de-dragon .dialog-content div.roll-chat div.chat-buttons {
grid-area: buttons; grid-area: buttons;
@@ -765,6 +790,15 @@ select,
.system-foundryvtt-reve-de-dragon .window-header { .system-foundryvtt-reve-de-dragon .window-header {
background: rgba(0, 0, 0, 0.75); background: rgba(0, 0, 0, 0.75);
} }
.system-foundryvtt-reve-de-dragon .journal-entry-content {
background: url(../assets/ui/bg_left.webp) no-repeat left top;
color: var(--rdd-color-text-primary);
}
.system-foundryvtt-reve-de-dragon .journal-page-header h1,
.system-foundryvtt-reve-de-dragon .journal-page-header h2 .journal-page-header h3,
.system-foundryvtt-reve-de-dragon .journal-page-header h4 {
color: var(--rdd-color-text-primary);
}
.system-foundryvtt-reve-de-dragon .application .window-content { .system-foundryvtt-reve-de-dragon .application .window-content {
margin: 0; margin: 0;
padding: 0.2rem; padding: 0.2rem;
@@ -779,7 +813,7 @@ select,
.system-foundryvtt-reve-de-dragon .strong-text { .system-foundryvtt-reve-de-dragon .strong-text {
font-weight: bold; font-weight: bold;
} }
.system-foundryvtt-reve-de-dragon i:is(.fas, .far, .fa-solid, .fa-regular, .fa-sharp ) { .system-foundryvtt-reve-de-dragon i:is(.fas, .far, .fa-solid, .fa-regular, .fa-sharp) {
font-size: smaller; font-size: smaller;
} }
.system-foundryvtt-reve-de-dragon .sheet-header h1.charname { .system-foundryvtt-reve-de-dragon .sheet-header h1.charname {
@@ -818,7 +852,7 @@ select,
margin-top: -8px; margin-top: -8px;
margin-bottom: -8px; margin-bottom: -8px;
} }
.system-foundryvtt-reve-de-dragon .sheet-header :is(.header-compteurs,.header-etats,.profile-img, .profile-img-token) { .system-foundryvtt-reve-de-dragon .sheet-header :is(.header-compteurs, .header-etats, .profile-img, .profile-img-token) {
padding: 0 0.4rem; padding: 0 0.4rem;
} }
.system-foundryvtt-reve-de-dragon .sheet-header div.header-etats { .system-foundryvtt-reve-de-dragon .sheet-header div.header-etats {
@@ -855,11 +889,11 @@ select,
object-fit: contain; object-fit: contain;
} }
.system-foundryvtt-reve-de-dragon img.equipement-inutilisable { .system-foundryvtt-reve-de-dragon img.equipement-inutilisable {
vertical-align: bottom ; vertical-align: bottom;
max-width: 1.4rem; max-width: 1.4rem;
max-height: 1.4rem; max-height: 1.4rem;
border: 1px; border: 1px;
background: center / contain no-repeat url('../../icons/templates/icone_parchement_vierge.webp'); background: center / contain no-repeat url("../icons/templates/icone_parchement_vierge.webp");
} }
.system-foundryvtt-reve-de-dragon .sheet-header .header-compteurs { .system-foundryvtt-reve-de-dragon .sheet-header .header-compteurs {
width: calc(60% - 110px - 1rem); width: calc(60% - 110px - 1rem);
@@ -927,7 +961,14 @@ select,
.system-foundryvtt-reve-de-dragon div.tmrdialog div.tmr-actions { .system-foundryvtt-reve-de-dragon div.tmrdialog div.tmr-actions {
vertical-align: top; vertical-align: top;
flex-basis: inherit; flex-basis: inherit;
flex: 'flex-shrink'; flex: "flex-shrink";
}
.system-foundryvtt-reve-de-dragon :is(section.scenes-sidebar, section.compendium-sidebar) li.directory-item.folder a {
text-shadow: 1px 1px 2px var(--rdd-color-text-primary);
color: var(--color-background-chat-message);
}
.system-foundryvtt-reve-de-dragon :is(section.scenes-sidebar, section.compendium-sidebar) li.directory-item.folder a:hover {
text-shadow: 1px 0px 0px #ff6600;
} }
.system-foundryvtt-reve-de-dragon .tabs .item.active, .system-foundryvtt-reve-de-dragon .tabs .item.active,
.system-foundryvtt-reve-de-dragon .blessures-list li ul li:first-child:hover, .system-foundryvtt-reve-de-dragon .blessures-list li ul li:first-child:hover,
@@ -1054,7 +1095,7 @@ select,
justify-content: space-between; justify-content: space-between;
} }
.system-foundryvtt-reve-de-dragon .flex-shrink { .system-foundryvtt-reve-de-dragon .flex-shrink {
flex: 'flex-shrink'; flex: "flex-shrink";
flex-shrink: 0; flex-shrink: 0;
} }
.system-foundryvtt-reve-de-dragon .flex-grow, .system-foundryvtt-reve-de-dragon .flex-grow,
@@ -1169,6 +1210,10 @@ select,
color: rgba(173, 36, 26, 0.9); color: rgba(173, 36, 26, 0.9);
text-shadow: 1px 1px 4px #3c3c3c; text-shadow: 1px 1px 4px #3c3c3c;
} }
.system-foundryvtt-reve-de-dragon .rdd-dialog.status-effects li {
display: flex;
flex-direction: row;
}
.system-foundryvtt-reve-de-dragon .rdd-dialog-select img.select-img { .system-foundryvtt-reve-de-dragon .rdd-dialog-select img.select-img {
-webkit-box-flex: 0; -webkit-box-flex: 0;
-ms-flex: 0 0 48px; -ms-flex: 0 0 48px;
@@ -1272,7 +1317,7 @@ select,
border: 0; border: 0;
vertical-align: bottom; vertical-align: bottom;
} }
.system-foundryvtt-reve-de-dragon :is(.button-img,.button-effect-img,.tmr-move):hover { .system-foundryvtt-reve-de-dragon :is(.button-img, .button-effect-img, .tmr-move):hover {
color: var(--color-controls-hover); color: var(--color-controls-hover);
border: 1px solid var(--color-control-border-hover); border: 1px solid var(--color-control-border-hover);
text-shadow: 1px 0px 0px #ff6600; text-shadow: 1px 0px 0px #ff6600;
@@ -1364,12 +1409,22 @@ select,
margin-inline: 0.1rem; margin-inline: 0.1rem;
margin-block: 0.1rem; margin-block: 0.1rem;
} }
.system-foundryvtt-reve-de-dragon .prosemirror menu {
background-color: var(--color-background-chat-message);
}
.system-foundryvtt-reve-de-dragon .app.sheet fieldset :is(label, input) { .system-foundryvtt-reve-de-dragon .app.sheet fieldset :is(label, input) {
font-family: CaslonAntique; font-family: CaslonAntique;
text-align: justify; text-align: justify;
font-size: 1rem; font-size: 1rem;
letter-spacing: 1px; letter-spacing: 1px;
} }
.system-foundryvtt-reve-de-dragon .app.sheet input.attribute-value {
background-color: rgba(0, 0, 0, 0.05);
border: 1px solid var(--color-border-light-tertiary);
padding: 1px 3px;
height: var(--form-field-height);
border-radius: 3px;
}
.system-foundryvtt-reve-de-dragon .app.sheet div.form-group { .system-foundryvtt-reve-de-dragon .app.sheet div.form-group {
clear: both; clear: both;
display: flex; display: flex;
@@ -1378,19 +1433,22 @@ select,
margin: 0.1rem 0; margin: 0.1rem 0;
align-items: center; align-items: center;
} }
.system-foundryvtt-reve-de-dragon .prosemirror menu {
background-color: var(--color-background-chat-message);
}
.system-foundryvtt-reve-de-dragon .app.sheet .editor.prosemirror { .system-foundryvtt-reve-de-dragon .app.sheet .editor.prosemirror {
height: fit-content; height: fit-content;
min-height: 5rem; min-height: 6rem;
} }
.system-foundryvtt-reve-de-dragon .app.sheet .editor.prosemirror .editor-container { .system-foundryvtt-reve-de-dragon .app.sheet .editor.prosemirror .editor-container {
min-height: 5rem; min-height: 6rem;
height: 8rem; height: calc(100% - 3rem);
margin: 0; margin: 0;
flex: none; flex: none;
} }
.system-foundryvtt-reve-de-dragon .app.sheet.journal-entry-page .editor.prosemirror {
height: 100%;
}
.system-foundryvtt-reve-de-dragon .app.sheet.journal-entry-page .editor.prosemirror .editor-container {
height: calc(100% - 6rem);
}
.system-foundryvtt-reve-de-dragon .large-editor { .system-foundryvtt-reve-de-dragon .large-editor {
border: 2; border: 2;
height: fit-content; height: fit-content;
@@ -1400,24 +1458,24 @@ select,
.system-foundryvtt-reve-de-dragon .editor { .system-foundryvtt-reve-de-dragon .editor {
border: 2; border: 2;
height: fit-content; height: fit-content;
min-height: 5rem; min-height: 6rem;
padding: 0 3px; padding: 0 3px;
} }
.system-foundryvtt-reve-de-dragon .medium-editor { .system-foundryvtt-reve-de-dragon .medium-editor {
border: 2; border: 2;
min-height: 8rem; min-height: 9rem;
padding: 0 3px; padding: 0 3px;
align-items: top; align-items: top;
} }
.system-foundryvtt-reve-de-dragon .small-editor { .system-foundryvtt-reve-de-dragon .small-editor {
border: 2; border: 2;
min-height: 2rem; min-height: 4rem;
padding: 0 3px; padding: 0 3px;
} }
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon.sheet :is(.large-editor,.editor,.medium-editor,.small-editor) { .system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon.sheet :is(.large-editor, .editor, .medium-editor, .small-editor) {
align-items: start; align-items: start;
} }
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon.sheet :is(.large-editor,.editor,.medium-editor,.small-editor) .editor.prosemirror { .system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon.sheet :is(.large-editor, .editor, .medium-editor, .small-editor) .editor.prosemirror {
align-items: normal; align-items: normal;
} }
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon .tox .tox-editor-container { .system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon .tox .tox-editor-container {
@@ -1432,8 +1490,8 @@ select,
} }
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon .tabs { .system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon .tabs {
height: 40px; height: 40px;
border-top: 1px solid #AAA; border-top: 1px solid #aaa;
border-bottom: 1px solid #AAA; border-bottom: 1px solid #aaa;
} }
.system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon .tabs .item { .system-foundryvtt-reve-de-dragon .foundryvtt-reve-de-dragon .tabs .item {
line-height: 40px; line-height: 40px;
@@ -1474,6 +1532,7 @@ select,
} }
.system-foundryvtt-reve-de-dragon .item-actions-controls img, .system-foundryvtt-reve-de-dragon .item-actions-controls img,
.system-foundryvtt-reve-de-dragon .item-controls img { .system-foundryvtt-reve-de-dragon .item-controls img {
vertical-align: text-bottom;
display: inline; display: inline;
max-width: 1rem; max-width: 1rem;
max-height: 1rem; max-height: 1rem;
@@ -1486,10 +1545,17 @@ select,
font-size: 0.8em; font-size: 0.8em;
color: var(--color-controls-light); color: var(--color-controls-light);
} }
.system-foundryvtt-reve-de-dragon .item-actions-controls img:hover, .system-foundryvtt-reve-de-dragon .item-actions-controls a:hover,
.system-foundryvtt-reve-de-dragon .item-controls img:hover, .system-foundryvtt-reve-de-dragon .item-controls a:hover {
.system-foundryvtt-reve-de-dragon .item-actions-controls i:is(.fas, .far, .fa-solid, .fa-regular):hover, text-shadow: 1px 0px 0px #ff6600;
.system-foundryvtt-reve-de-dragon .item-controls i:is(.fas, .far, .fa-solid, .fa-regular):hover { }
.system-foundryvtt-reve-de-dragon .item-actions-controls a img:hover,
.system-foundryvtt-reve-de-dragon .item-controls a img:hover {
opacity: 0.6;
filter: drop-shadow(1px 1px 1px #009966) invert(0.8);
}
.system-foundryvtt-reve-de-dragon .item-actions-controls a i:is(.fas, .far, .fa-solid, .fa-regular):hover,
.system-foundryvtt-reve-de-dragon .item-controls a i:is(.fas, .far, .fa-solid, .fa-regular):hover {
opacity: 0.6; opacity: 0.6;
} }
.system-foundryvtt-reve-de-dragon .rdd-roll-dialog .description-sort { .system-foundryvtt-reve-de-dragon .rdd-roll-dialog .description-sort {
@@ -1589,28 +1655,18 @@ select,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar .permissions-list, .system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar .permissions-list,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs, .system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs,
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs, .system-foundryvtt-reve-de-dragon .application .window-content nav.tabs,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs, .system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs {
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs button, color: var(--rdd-color-text-primary);
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs button, }
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs button, .system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body button .count,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body nav.tabs button .count, .system-foundryvtt-reve-de-dragon .application .window-content button .count,
.system-foundryvtt-reve-de-dragon .application .window-content nav.tabs button .count, .system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar button .count,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar nav.tabs button .count,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body button, .system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body button,
.system-foundryvtt-reve-de-dragon .application .window-content button, .system-foundryvtt-reve-de-dragon .application .window-content button,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar button { .system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar button {
background-color: var(--background-color-button);
color: var(--rdd-color-text-primary); color: var(--rdd-color-text-primary);
} }
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body a,
.system-foundryvtt-reve-de-dragon .application .window-content a,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar a {
color: var(--color-dark-3);
}
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body a.filter.active,
.system-foundryvtt-reve-de-dragon .application .window-content a.filter.active,
.system-foundryvtt-reve-de-dragon .journal-entry .journal-sidebar a.filter.active {
color: var(--color-dark-1);
}
.system-foundryvtt-reve-de-dragon .window-app .window-content { .system-foundryvtt-reve-de-dragon .window-app .window-content {
background: url(../assets/ui/bg_left.webp) no-repeat left top; background: url(../assets/ui/bg_left.webp) no-repeat left top;
color: var(--rdd-color-text-primary); color: var(--rdd-color-text-primary);
@@ -1641,34 +1697,34 @@ select,
padding-right: 0.5rem; padding-right: 0.5rem;
max-width: 7rem; max-width: 7rem;
} }
.system-foundryvtt-reve-de-dragon select:is(.number-x,.number-x2,.number-x3,.number-x4,.number-x5) { .system-foundryvtt-reve-de-dragon select:is(.number-x, .number-x2, .number-x3, .number-x4, .number-x5) {
padding-right: 0.2rem; padding-right: 0.2rem;
text-align: center; text-align: center;
} }
.system-foundryvtt-reve-de-dragon input:is(.number,.number-x,.number-x2,.number-x3,.number-x4,.number-x5) { .system-foundryvtt-reve-de-dragon input:is(.number, .number-x, .number-x2, .number-x3, .number-x4, .number-x5) {
padding-right: 0.2rem; padding-right: 0.2rem;
text-align: right; text-align: right;
} }
.system-foundryvtt-reve-de-dragon :is(input,select).number-x { .system-foundryvtt-reve-de-dragon :is(input, select).number-x {
max-width: 1.4rem; max-width: 1.4rem;
min-width: 1rem; min-width: 1rem;
} }
.system-foundryvtt-reve-de-dragon :is(input,select).number-x2 { .system-foundryvtt-reve-de-dragon :is(input, select).number-x2 {
max-width: 2.4rem; max-width: 2.4rem;
min-width: 2rem; min-width: 2rem;
} }
.system-foundryvtt-reve-de-dragon :is(input,select).number-x3 { .system-foundryvtt-reve-de-dragon :is(input, select).number-x3 {
max-width: 3.4rem; max-width: 3.4rem;
min-width: 3rem; min-width: 3rem;
} }
.system-foundryvtt-reve-de-dragon :is(input,select).number-x4 { .system-foundryvtt-reve-de-dragon :is(input, select).number-x4 {
max-width: 4.4rem; max-width: 4.4rem;
min-width: 4rem; min-width: 4rem;
} }
.system-foundryvtt-reve-de-dragon :is(input,select).number-x5 { .system-foundryvtt-reve-de-dragon :is(input, select).number-x5 {
max-width: 4.4rem; max-width: 4.4rem;
} }
.system-foundryvtt-reve-de-dragon form.rdddialogchrono input[type=datetime-local] { .system-foundryvtt-reve-de-dragon form.rdddialogchrono input[type="datetime-local"] {
min-width: 20px; min-width: 20px;
padding: 0; padding: 0;
background: rgba(0, 0, 0, 0.05); background: rgba(0, 0, 0, 0.05);
@@ -1682,25 +1738,121 @@ select,
.system-foundryvtt-reve-de-dragon form.app-personnage-aleatoire h2 { .system-foundryvtt-reve-de-dragon form.app-personnage-aleatoire h2 {
min-width: 30rem; min-width: 30rem;
} }
.system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.theme-astral { .system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.theme-astral {
width: 14rem; width: 14rem;
margin: 0.4rem; margin: 0.4rem;
} }
.system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.horloge-roue { .system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-roue {
position: relative; position: relative;
left: calc(50% - 6.5rem); left: calc(50% - 6.5rem);
width: 13rem; width: 13rem;
height: 13rem; height: 13rem;
} }
.system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.horloge-roue div.horloge-heure { .system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-roue div.horloge-heure {
position: absolute; position: absolute;
width: 1.8rem; width: 1.8rem;
height: 1.8rem; height: 1.8rem;
} }
.system-foundryvtt-reve-de-dragon .app-calendar-astrologie div.horloge-roue div.horloge-heure img.horloge-heure-img { .system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-roue div.horloge-heure img.horloge-heure-img {
width: 2rem; width: 2rem;
height: 2rem; height: 2rem;
} }
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-01 {
top: calc(50% - 1rem + 0 * 41%);
left: calc(50% - 1rem + -1 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-02 {
top: calc(50% - 1rem + -0.5 * 41%);
left: calc(50% - 1rem + -0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-03 {
top: calc(50% - 1rem + -0.8660254 * 41%);
left: calc(50% - 1rem + -0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-04 {
top: calc(50% - 1rem + -1 * 41%);
left: calc(50% - 1rem + 0 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-05 {
top: calc(50% - 1rem + -0.8660254 * 41%);
left: calc(50% - 1rem + 0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-06 {
top: calc(50% - 1rem + -0.5 * 41%);
left: calc(50% - 1rem + 0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-07 {
top: calc(50% - 1rem + 0 * 41%);
left: calc(50% - 1rem + 1 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-08 {
top: calc(50% - 1rem + 0.5 * 41%);
left: calc(50% - 1rem + 0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-09 {
top: calc(50% - 1rem + 0.8660254 * 41%);
left: calc(50% - 1rem + 0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-10 {
top: calc(50% - 1rem + 1 * 41%);
left: calc(50% - 1rem + 0 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-11 {
top: calc(50% - 1rem + 0.8660254 * 41%);
left: calc(50% - 1rem + -0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-heure.heure-12 {
top: calc(50% - 1rem + 0.5 * 41%);
left: calc(50% - 1rem + -0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-01 {
top: calc(50% - 0.4rem + 0 * 28%);
left: calc(50% - 0.4rem + -1 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-02 {
top: calc(50% - 0.4rem + -0.5 * 28%);
left: calc(50% - 0.4rem + -0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-03 {
top: calc(50% - 0.4rem + -0.8660254 * 28%);
left: calc(50% - 0.4rem + -0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-04 {
top: calc(50% - 0.4rem + -1 * 28%);
left: calc(50% - 0.4rem + 0 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-05 {
top: calc(50% - 0.4rem + -0.8660254 * 28%);
left: calc(50% - 0.4rem + 0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-06 {
top: calc(50% - 0.4rem + -0.5 * 28%);
left: calc(50% - 0.4rem + 0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-07 {
top: calc(50% - 0.4rem + 0 * 28%);
left: calc(50% - 0.4rem + 1 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-08 {
top: calc(50% - 0.4rem + 0.5 * 28%);
left: calc(50% - 0.4rem + 0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-09 {
top: calc(50% - 0.4rem + 0.8660254 * 28%);
left: calc(50% - 0.4rem + 0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-10 {
top: calc(50% - 0.4rem + 1 * 28%);
left: calc(50% - 0.4rem + 0 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-11 {
top: calc(50% - 0.4rem + 0.8660254 * 28%);
left: calc(50% - 0.4rem + -0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .rdd-calendar-astrologie div.horloge-ajustement.heure-12 {
top: calc(50% - 0.4rem + 0.5 * 28%);
left: calc(50% - 0.4rem + -0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .window-app .window-content, .system-foundryvtt-reve-de-dragon .window-app .window-content,
.system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body, .system-foundryvtt-reve-de-dragon .window-app.sheet .window-content .sheet-body,
.system-foundryvtt-reve-de-dragon .application .window-content { .system-foundryvtt-reve-de-dragon .application .window-content {
@@ -1760,7 +1912,7 @@ select,
text-align: left; text-align: left;
width: 2rem; width: 2rem;
} }
.system-foundryvtt-reve-de-dragon .compteur a i:is(.fas,.far):hover { .system-foundryvtt-reve-de-dragon .compteur a i:is(.fas, .far):hover {
opacity: 0.7; opacity: 0.7;
} }
.system-foundryvtt-reve-de-dragon .select-diff { .system-foundryvtt-reve-de-dragon .select-diff {
@@ -2182,7 +2334,7 @@ select,
.system-foundryvtt-reve-de-dragon #sidebar-tabs > .collapsed, .system-foundryvtt-reve-de-dragon #sidebar-tabs > .collapsed,
.system-foundryvtt-reve-de-dragon #chat-controls .chat-control-icon { .system-foundryvtt-reve-de-dragon #chat-controls .chat-control-icon {
color: rgba(220, 220, 220, 0.75); color: rgba(220, 220, 220, 0.75);
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.75); text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.75);
} }
.system-foundryvtt-reve-de-dragon .sidebar-tab .directory-list .entity { .system-foundryvtt-reve-de-dragon .sidebar-tab .directory-list .entity {
border-top: 1px dashed rgba(0, 0, 0, 0.25); border-top: 1px dashed rgba(0, 0, 0, 0.25);
@@ -2238,19 +2390,19 @@ select,
vertical-align: bottom; vertical-align: bottom;
} }
.system-foundryvtt-reve-de-dragon #sidebar-tabs menu button:is( .system-foundryvtt-reve-de-dragon #sidebar-tabs menu button:is(
[data-tab="chat"], [data-tab="chat"],
[data-tab="combat"], [data-tab="combat"],
[data-tab="scenes"], [data-tab="scenes"],
[data-tab="actors"], [data-tab="actors"],
[data-tab="items"], [data-tab="items"],
[data-tab="journal"], [data-tab="journal"],
[data-tab="cards"], [data-tab="cards"],
[data-tab="macros"], [data-tab="macros"],
[data-tab="tables"], [data-tab="tables"],
[data-tab="playlists"], [data-tab="playlists"],
[data-tab="compendium"], [data-tab="compendium"],
[data-tab="settings"] [data-tab="settings"]
)::before { )::before {
content: none; content: none;
} }
.system-foundryvtt-reve-de-dragon #sidebar-tabs menu button { .system-foundryvtt-reve-de-dragon #sidebar-tabs menu button {
@@ -2318,7 +2470,12 @@ select,
max-height: calc(100vh - 156px); max-height: calc(100vh - 156px);
height: auto; height: auto;
} }
.system-foundryvtt-reve-de-dragon #controls :is(.scene-control.active,.control-tool.active, .scene-control:hover, .control-tool:hover) { .system-foundryvtt-reve-de-dragon #controls :is(
.scene-control.active,
.control-tool.active,
.scene-control:hover,
.control-tool:hover
) {
background: #482e1c; background: #482e1c;
background-origin: padding-box; background-origin: padding-box;
border-image: url(../assets/ui/footer-button.webp) 10 repeat; border-image: url(../assets/ui/footer-button.webp) 10 repeat;
@@ -2540,103 +2697,7 @@ select,
top: calc(50% - 0.7rem + 0.5 * 38%); top: calc(50% - 0.7rem + 0.5 * 38%);
left: calc(50% - 0.7rem + -0.8660254 * 41%); left: calc(50% - 0.7rem + -0.8660254 * 41%);
} }
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-01 { .system-foundryvtt-reve-de-dragon .calendar-boutons-heure .calendar-btn:is(.calendar-lyre, .calendar-vaisseau) img {
top: calc(50% - 1rem + 0 * 41%);
left: calc(50% - 1rem + -1 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-02 {
top: calc(50% - 1rem + -0.5 * 41%);
left: calc(50% - 1rem + -0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-03 {
top: calc(50% - 1rem + -0.8660254 * 41%);
left: calc(50% - 1rem + -0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-04 {
top: calc(50% - 1rem + -1 * 41%);
left: calc(50% - 1rem + 0 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-05 {
top: calc(50% - 1rem + -0.8660254 * 41%);
left: calc(50% - 1rem + 0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-06 {
top: calc(50% - 1rem + -0.5 * 41%);
left: calc(50% - 1rem + 0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-07 {
top: calc(50% - 1rem + 0 * 41%);
left: calc(50% - 1rem + 1 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-08 {
top: calc(50% - 1rem + 0.5 * 41%);
left: calc(50% - 1rem + 0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-09 {
top: calc(50% - 1rem + 0.8660254 * 41%);
left: calc(50% - 1rem + 0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-10 {
top: calc(50% - 1rem + 1 * 41%);
left: calc(50% - 1rem + 0 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-11 {
top: calc(50% - 1rem + 0.8660254 * 41%);
left: calc(50% - 1rem + -0.5 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-heure.heure-12 {
top: calc(50% - 1rem + 0.5 * 41%);
left: calc(50% - 1rem + -0.8660254 * 41%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-01 {
top: calc(50% - 0.4rem + 0 * 28%);
left: calc(50% - 0.4rem + -1 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-02 {
top: calc(50% - 0.4rem + -0.5 * 28%);
left: calc(50% - 0.4rem + -0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-03 {
top: calc(50% - 0.4rem + -0.8660254 * 28%);
left: calc(50% - 0.4rem + -0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-04 {
top: calc(50% - 0.4rem + -1 * 28%);
left: calc(50% - 0.4rem + 0 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-05 {
top: calc(50% - 0.4rem + -0.8660254 * 28%);
left: calc(50% - 0.4rem + 0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-06 {
top: calc(50% - 0.4rem + -0.5 * 28%);
left: calc(50% - 0.4rem + 0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-07 {
top: calc(50% - 0.4rem + 0 * 28%);
left: calc(50% - 0.4rem + 1 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-08 {
top: calc(50% - 0.4rem + 0.5 * 28%);
left: calc(50% - 0.4rem + 0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-09 {
top: calc(50% - 0.4rem + 0.8660254 * 28%);
left: calc(50% - 0.4rem + 0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-10 {
top: calc(50% - 0.4rem + 1 * 28%);
left: calc(50% - 0.4rem + 0 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-11 {
top: calc(50% - 0.4rem + 0.8660254 * 28%);
left: calc(50% - 0.4rem + -0.5 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-astrologie div.horloge-ajustement.heure-12 {
top: calc(50% - 0.4rem + 0.5 * 28%);
left: calc(50% - 0.4rem + -0.8660254 * 28%);
}
.system-foundryvtt-reve-de-dragon .calendar-boutons-heure .calendar-btn:is(.calendar-lyre,.calendar-vaisseau) img {
color: hsla(0, 0%, 100%, 0.5); color: hsla(0, 0%, 100%, 0.5);
border: none; border: none;
vertical-align: bottom; vertical-align: bottom;
@@ -2676,7 +2737,7 @@ select,
.system-foundryvtt-reve-de-dragon .calendar-vaisseau { .system-foundryvtt-reve-de-dragon .calendar-vaisseau {
grid-column: 9/10; grid-column: 9/10;
} }
.system-foundryvtt-reve-de-dragon :is(.calendar-lyre,.calendar-vaisseau) { .system-foundryvtt-reve-de-dragon :is(.calendar-lyre, .calendar-vaisseau) {
display: flex; display: flex;
flex-direction: row; flex-direction: row;
} }
@@ -2688,12 +2749,12 @@ select,
visibility: hidden; visibility: hidden;
} }
.system-foundryvtt-reve-de-dragon div.horloge-digitale { .system-foundryvtt-reve-de-dragon div.horloge-digitale {
color: #CCC; color: #ccc;
background: hsl(0, 0%, 20%); background: hsl(0, 0%, 20%);
text-align: center; text-align: center;
width: 100%; width: 100%;
} }
.system-foundryvtt-reve-de-dragon div.horloge-digitale :is(.calendar-heure-texte,.calendar-minute-texte) { .system-foundryvtt-reve-de-dragon div.horloge-digitale :is(.calendar-heure-texte, .calendar-minute-texte) {
font-size: 1rem; font-size: 1rem;
pointer-events: all; pointer-events: all;
margin: 0; margin: 0;
@@ -2786,8 +2847,23 @@ select,
.system-foundryvtt-reve-de-dragon aside#tooltip .toolclip p.faint { .system-foundryvtt-reve-de-dragon aside#tooltip .toolclip p.faint {
color: var(--color-tooltip-faint); color: var(--color-tooltip-faint);
} }
.system-foundryvtt-reve-de-dragon .chat-card-info {
font-size: 1.1rem;
display: flex;
flex-direction: row;
}
.system-foundryvtt-reve-de-dragon .chat-card-info img {
margin: 0 0.5rem;
max-width: 1rem;
max-height: 1rem;
filter: invert(0.8);
}
.system-foundryvtt-reve-de-dragon .jet-astrologie {
color: var(--major-button-color) !important;
}
.system-foundryvtt-reve-de-dragon .chat-card-button, .system-foundryvtt-reve-de-dragon .chat-card-button,
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed { .system-foundryvtt-reve-de-dragon .chat-card-button-checked,
.system-foundryvtt-reve-de-dragon select.chat-card-select {
border-radius: 0.2rem; border-radius: 0.2rem;
cursor: pointer; cursor: pointer;
font-family: CaslonPro; font-family: CaslonPro;
@@ -2800,29 +2876,27 @@ select,
display: inline-block; display: inline-block;
} }
.system-foundryvtt-reve-de-dragon .chat-card-button img, .system-foundryvtt-reve-de-dragon .chat-card-button img,
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed img { .system-foundryvtt-reve-de-dragon .chat-card-button-checked img,
.system-foundryvtt-reve-de-dragon select.chat-card-select img {
max-width: 1rem; max-width: 1rem;
max-height: 1rem; max-height: 1rem;
} }
.system-foundryvtt-reve-de-dragon .chat-card-info { .system-foundryvtt-reve-de-dragon select.chat-card-select {
font-size: 1.1rem; width: calc(100% - 0.6rem);
display: flex; color: var(--major-button-color);
flex-direction: row; background-color: var(--background-color-custom-button);
} }
.system-foundryvtt-reve-de-dragon .chat-card-info img { .system-foundryvtt-reve-de-dragon select.chat-card-select option {
margin: 0 0.5rem; background-color: var(--background-color-custom-button);
max-width: 1rem;
max-height: 1rem;
filter: invert(0.8);
} }
.system-foundryvtt-reve-de-dragon .chat-card-button { .system-foundryvtt-reve-de-dragon .chat-card-button {
text-shadow: 1px 1px #4d3534; text-shadow: 1px 1px #4d3534;
box-shadow: inset 1x 1px #a6827e; box-shadow: inset 1x 1px #a6827e;
color: var(--major-button-color); color: var(--major-button-color);
background: var(--background-custom-button); background: var(--background-custom-button);
background-color: #7d5d3b00; background-color: var(--background-color-custom-button);
} }
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed { .system-foundryvtt-reve-de-dragon .chat-card-button-checked {
text-shadow: 1px 1px hsla(202, 30%, 70%, 0.5); text-shadow: 1px 1px hsla(202, 30%, 70%, 0.5);
box-shadow: inset -1px -1px #a6827e; box-shadow: inset -1px -1px #a6827e;
color: hsla(202, 42%, 14%, 0.7); color: hsla(202, 42%, 14%, 0.7);
@@ -2832,11 +2906,11 @@ select,
.system-foundryvtt-reve-de-dragon .chat-card-button:hover { .system-foundryvtt-reve-de-dragon .chat-card-button:hover {
background: var(--background-custom-button-hover); background: var(--background-custom-button-hover);
} }
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed:hover { .system-foundryvtt-reve-de-dragon .chat-card-button-checked:hover {
background: var(--background-custom-button-hover); background: var(--background-custom-button-hover);
} }
.system-foundryvtt-reve-de-dragon .chat-card-button:active, .system-foundryvtt-reve-de-dragon .chat-card-button:active,
.system-foundryvtt-reve-de-dragon .chat-card-button-pushed:active { .system-foundryvtt-reve-de-dragon .chat-card-button-checked:active {
position: relative; position: relative;
top: 1px; top: 1px;
} }
@@ -2903,7 +2977,7 @@ select,
background: none; background: none;
} }
.system-foundryvtt-reve-de-dragon #pause > h3 { .system-foundryvtt-reve-de-dragon #pause > h3 {
color: #CCC; color: #ccc;
} }
.system-foundryvtt-reve-de-dragon #pause > img { .system-foundryvtt-reve-de-dragon #pause > img {
content: url(../assets/ui/rdd_pause.webp); content: url(../assets/ui/rdd_pause.webp);
@@ -2918,7 +2992,7 @@ select,
height: 68px; height: 68px;
} }
.system-foundryvtt-reve-de-dragon div.vl { .system-foundryvtt-reve-de-dragon div.vl {
border: 1px solid ; border: 1px solid;
border-color: hsla(0, 0%, 0%, 0.5); border-color: hsla(0, 0%, 0%, 0.5);
height: inherit; height: inherit;
min-height: max-content; min-height: max-content;

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

BIN
icons/objets/coffre.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

BIN
icons/objets/parchemin.webp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.0 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 5.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.1 KiB

After

Width:  |  Height:  |  Size: 9.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 6.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.3 KiB

5
info-message.html Normal file
View File

@@ -0,0 +1,5 @@
<h3>Joyeuses fêtes</h3>
<p>
VincentVK, LeRatierBretonnien et toute l'équipe de Scriptrarium vous
souhaitent de joyeuses et oniriques fêtes !
</p>

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@@ -9,7 +9,7 @@ import { ReglesOptionnelles } from "./settings/regles-optionnelles.js";
import { RdDSheetUtility } from "./rdd-sheet-utility.js"; import { RdDSheetUtility } from "./rdd-sheet-utility.js";
import { MAINS_DIRECTRICES } from "./actor.js"; import { MAINS_DIRECTRICES } from "./actor.js";
import { RdDBaseActorReveSheet } from "./actor/base-actor-reve-sheet.js"; import { RdDBaseActorReveSheet } from "./actor/base-actor-reve-sheet.js";
import { ITEM_TYPES } from "./constants.js"; import { ACTOR_TYPES, ITEM_TYPES } from "./constants.js";
import { RdDItem } from "./item.js"; import { RdDItem } from "./item.js";
import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemBlessure } from "./item/blessure.js"; import { RdDItemBlessure } from "./item/blessure.js";
@@ -18,6 +18,8 @@ import { RdDBaseActorSangSheet } from "./actor/base-actor-sang-sheet.js";
import { RdDCoeur } from "./coeur/rdd-coeur.js"; import { RdDCoeur } from "./coeur/rdd-coeur.js";
import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js"; import { AppPersonnageAleatoire } from "./actor/random/app-personnage-aleatoire.js";
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js"; import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
import { MORAL } from "./moral/apprecier.mjs";
import { RdDItemSort } from "./item-sort.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
/** /**
@@ -51,18 +53,23 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
surprise: RdDBonus.find(this.actor.getSurprise(false)).label, surprise: RdDBonus.find(this.actor.getSurprise(false)).label,
resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures), resumeBlessures: this.actor.computeResumeBlessure(this.actor.system.blessures),
caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute), caracTotal: RdDCarac.computeTotal(this.actor.system.carac, this.actor.system.beaute),
caracTotalXp: RdDCarac.computeTotalXp(this.actor.system.carac, this.actor.system.beaute),
surEncombrementMessage: this.actor.isSurenc() ? "Sur-Encombrement!" : "", surEncombrementMessage: this.actor.isSurenc() ? "Sur-Encombrement!" : "",
malusArmure: this.actor.getMalusArmure() malusArmure: this.actor.getMalusArmure()
}) })
this.timerRecherche = undefined; this.timerRecherche = undefined;
if (formData.type == 'personnage') { if (formData.type == ACTOR_TYPES.personnage) {
formData.options.mainsDirectrices = MAINS_DIRECTRICES; formData.options.mainsDirectrices = MAINS_DIRECTRICES;
formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie) formData.byCateg = Misc.classify(formData.competences, it => it.system.categorie)
formData.calc.comptageArchetype = RdDItemCompetence.computeResumeArchetype(formData.competences); foundry.utils.mergeObject(formData.calc, {
formData.calc.competenceXPTotal = RdDItemCompetence.computeTotalXP(formData.competences); comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.competences),
formData.calc.fatigue = RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max); competenceXPTotal: RdDItemCompetence.computeTotalXP(formData.competences),
sortsXPTotal: RdDItemSort.computeTotalXP(this.actor.itemTypes[ITEM_TYPES.sort]),
fatigue: RdDUtility.calculFatigueHtml(formData.system.sante.fatigue.value, formData.system.sante.endurance.max)
})
formData.competences.forEach(item => { formData.competences.forEach(item => {
item.system.isHidden = this.options.recherche item.system.isHidden = this.options.recherche
@@ -208,7 +215,8 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
} }
// Points de reve actuel // Points de reve actuel
this.html.find('.roll-reve-actuel').click(async event => await this.actor.rollCarac(CARACS.REVE_ACTUEL, { resistance: true })) this.html.find('.roll-reve-actuel').click(async event => await this.actor.rollReveActuel({ resistance: false }))
this.html.find('.button-reve-resistance').click(async event => await this.actor.rollReveActuel({ diff: -8, resistance: true }))
this.html.find('.action-empoignade').click(async event => await RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor))) this.html.find('.action-empoignade').click(async event => await RdDEmpoignade.onAttaqueEmpoignadeFromItem(RdDSheetUtility.getItem(event, this.actor)))
this.html.find('.roll-arme').click(async event => { this.html.find('.roll-arme').click(async event => {
@@ -274,9 +282,9 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
this.html.find('.seuil-reve-value').change(async event => await this.actor.setPointsDeSeuil(event.currentTarget.value)) this.html.find('.seuil-reve-value').change(async event => await this.actor.setPointsDeSeuil(event.currentTarget.value))
this.html.find('.stress-test').click(async event => await this.actor.transformerStress()) this.html.find('.stress-test').click(async event => await this.actor.transformerStress())
this.html.find('.moral-malheureux').click(async event => await this.actor.jetDeMoral('malheureuse')) this.html.find('.moral-malheureux').click(async event => await this.actor.jetDeMoral(MORAL.MALHEUREUX))
this.html.find('.moral-neutre').click(async event => await this.actor.jetDeMoral('neutre')) this.html.find('.moral-neutre').click(async event => await this.actor.jetDeMoral(MORAL.NEUTRE))
this.html.find('.moral-heureux').click(async event => await this.actor.jetDeMoral('heureuse')) this.html.find('.moral-heureux').click(async event => await this.actor.jetDeMoral(MORAL.HEUREUX))
this.html.find('.button-ethylisme').click(async event => await this.actor.jetEthylisme()) this.html.find('.button-ethylisme').click(async event => await this.actor.jetEthylisme())
this.html.find('.ptreve-actuel-plus').click(async event => await this.actor.reveActuelIncDec(1)) this.html.find('.ptreve-actuel-plus').click(async event => await this.actor.reveActuelIncDec(1))

View File

@@ -41,18 +41,20 @@ import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemSigneDraconique } from "./item/signedraconique.js"; import { RdDItemSigneDraconique } from "./item/signedraconique.js";
import { RdDRencontre } from "./item/rencontre.js"; import { RdDRencontre } from "./item/rencontre.js";
import { DialogSelect } from "./dialog-select.js"; import { DialogSelect } from "./dialog-select.js";
import { PAS_DE_DRACONIC, POSSESSION_SANS_DRACONIC } from "./item/base-items.js"; import { CATEGORIES_COMPETENCES, PAS_DE_DRACONIC, POSSESSION_SANS_DRACONIC } from "./item/base-items.js";
import { RdDRollResult } from "./rdd-roll-result.js"; import { RdDRollResult } from "./rdd-roll-result.js";
import { RdDInitiative } from "./initiative.mjs"; import { RdDInitiative } from "./initiative.mjs";
import RollDialog from "./roll/roll-dialog.mjs"; import RollDialog from "./roll/roll-dialog.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2, ROLL_DIALOG_V2_TEST } from "./settings/options-avancees.js"; import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
import { ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_SORT } from "./roll/roll-constants.mjs"; import { ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_SORT } from "./roll/roll-constants.mjs";
import { PART_TACHE } from "./roll/roll-part-tache.mjs"; import { PART_TACHE } from "./roll/roll-part-tache.mjs";
import { PART_COMP } from "./roll/roll-part-comp.mjs"; import { PART_COMP } from "./roll/roll-part-comp.mjs";
import { PART_OEUVRE } from "./roll/roll-part-oeuvre.mjs"; import { PART_OEUVRE } from "./roll/roll-part-oeuvre.mjs";
import { PART_CUISINE } from "./roll/roll-part-cuisine.mjs"; import { PART_CUISINE } from "./roll/roll-part-cuisine.mjs";
import { PART_SORT } from "./roll/roll-part-sort.mjs"; import { RdDPossessionV2 } from "./rdd-possession-v2.mjs";
import { Apprecier, MORAL, SITUATION_MORAL } from "./moral/apprecier.mjs";
import { Distance } from "./combat/distance.mjs";
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre'] export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
@@ -131,11 +133,6 @@ export class RdDActor extends RdDBaseActorSang {
return etatGeneral return etatGeneral
} }
/* -------------------------------------------- */
getActivePoisons() {
return foundry.utils.duplicate(this.items.filter(item => item.type == 'poison' && item.system.active))
}
/* -------------------------------------------- */ /* -------------------------------------------- */
getMalusArmure() { getMalusArmure() {
return this.itemTypes[ITEM_TYPES.armure].filter(it => it.system.equipe) return this.itemTypes[ITEM_TYPES.armure].filter(it => it.system.equipe)
@@ -166,12 +163,15 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
getDemiReve() { return this.system.reve.tmrpos.coord } getDemiReve() { return this.system.reve.tmrpos.coord }
getDraconics() { return this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == 'draconic') } getDraconics() {
return this.isHautRevant()
? this.itemTypes[ITEM_TYPES.competence].filter(it => it.system.categorie == CATEGORIES_COMPETENCES.draconic.key)
: []
}
getBestDraconic() { return foundry.utils.duplicate([...this.getDraconics(), PAS_DE_DRACONIC].sort(Misc.descending(it => it.system.niveau)).find(it => true)) } getBestDraconic() { return foundry.utils.duplicate([...this.getDraconics(), PAS_DE_DRACONIC].sort(Misc.descending(it => it.system.niveau)).find(it => true)) }
getDraconicOuPossession() {
return [...this.getDraconics().filter(it => it.system.niveau >= 0), POSSESSION_SANS_DRACONIC] getConjurationNaturelle() {
.sort(Misc.descending(it => it.system.niveau)) return new RdDItemCompetence(POSSESSION_SANS_DRACONIC)
.find(it => true)
} }
isForceInsuffisante(forceRequise) { isForceInsuffisante(forceRequise) {
@@ -190,7 +190,10 @@ export class RdDActor extends RdDBaseActorSang {
const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main) const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
const ecaillesEfficacite = arme.system.magique ? arme.system.ecaille_efficacite : 0; const ecaillesEfficacite = arme.system.magique ? arme.system.ecaille_efficacite : 0;
const comp = this.getCompetence(RdDActor.$getCompetenceAction(arme, main)) const comp = this.getCompetence(arme.getCompetenceAction(main), { onMessage: message => { console.info(message) } })
if (!comp) {
return
}
const unique = [comp.id, arme.name, dommages, forceRequise, ecaillesEfficacite].join('|'); const unique = [comp.id, arme.name, dommages, forceRequise, ecaillesEfficacite].join('|');
if (uniques.includes(unique)) { if (uniques.includes(unique)) {
return return
@@ -203,7 +206,7 @@ export class RdDActor extends RdDBaseActorSang {
const niveau = comp?.system.niveau ?? (['(lancer)', '(tir)'].includes(main) ? -8 : -6) const niveau = comp?.system.niveau ?? (['(lancer)', '(tir)'].includes(main) ? -8 : -6)
const ajustement = (arme.parent?.getEtatGeneral() ?? 0) + ecaillesEfficacite const ajustement = (arme.parent?.getEtatGeneral() ?? 0) + ecaillesEfficacite
actions.push({ const attaque = {
label: arme.name + (main ? ' ' + main : ''), label: arme.name + (main ? ' ' + main : ''),
action: 'attaque', action: 'attaque',
initOnly: false, initOnly: false,
@@ -215,19 +218,18 @@ export class RdDActor extends RdDBaseActorSang {
dommages: dommages, dommages: dommages,
forceRequise: forceRequise, forceRequise: forceRequise,
initiative: RdDInitiative.getRollInitiative(caracValue, niveau, ajustement) initiative: RdDInitiative.getRollInitiative(caracValue, niveau, ajustement)
}) };
attaque.isDistance = Distance.typeAttaqueDistance(attaque),
actions.push(attaque)
} }
addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS) addAttaque(RdDItemArme.empoignade(this), ATTAQUE_TYPE.CORPS_A_CORPS)
this.itemTypes[ITEM_TYPES.arme] this.itemTypes[ITEM_TYPES.arme]
.filter(it => it.isAttaque()) .filter(it => it.isAttaque())
.sort(Misc.ascending(it => it.name)) .sort(Misc.ascending(it => it.name))
.forEach(arme => { .forEach(arme => arme.getTypeAttaques().forEach(t => addAttaque(arme, t)))
if (arme.system.unemain && arme.system.competence && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.UNE_MAIN) }
if (arme.system.deuxmains && arme.system.competence && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.DEUX_MAINS) }
if (arme.system.lancer && arme.system.resistance > 0) { addAttaque(arme, ATTAQUE_TYPE.LANCER) }
if (arme.system.tir) { addAttaque(arme, ATTAQUE_TYPE.TIR) }
})
addAttaque(RdDItemArme.pugilat(this), ATTAQUE_TYPE.CORPS_A_CORPS) addAttaque(RdDItemArme.pugilat(this), ATTAQUE_TYPE.CORPS_A_CORPS)
return actions return actions
@@ -244,16 +246,6 @@ export class RdDActor extends RdDBaseActorSang {
} }
} }
static $getCompetenceAction(arme, main) {
switch (main) {
case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains()
case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains()
case ATTAQUE_TYPE.LANCER: return arme.system.lancer
case ATTAQUE_TYPE.TIR: return arme.system.tir
default: return arme.system.competence
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async $perteReveEnchantementsChateauDormants() { async $perteReveEnchantementsChateauDormants() {
const toUpdate = this.items.filter(it => [ITEM_TYPES.potion, ITEM_TYPES.gemme].includes(it.type)) const toUpdate = this.items.filter(it => [ITEM_TYPES.potion, ITEM_TYPES.gemme].includes(it.type))
@@ -343,10 +335,6 @@ export class RdDActor extends RdDBaseActorSang {
await this._recupererVie(message, isMaladeEmpoisonne); await this._recupererVie(message, isMaladeEmpoisonne);
} }
getMaladiesPoisons() {
return this.items.filter(item => item.type == 'maladie' || (item.type == 'poison' && item.system.active));
}
_messageRecuperationMaladiePoisons(maladiesPoisons, message) { _messageRecuperationMaladiePoisons(maladiesPoisons, message) {
if (maladiesPoisons.length > 0) { if (maladiesPoisons.length > 0) {
const identifies = maladiesPoisons.filter(it => it.system.identifie); const identifies = maladiesPoisons.filter(it => it.system.identifie);
@@ -378,15 +366,15 @@ export class RdDActor extends RdDBaseActorSang {
content: "" content: ""
}; };
await this._recuperationSante(message); await this._recuperationSante(message)
await this._recupereMoralChateauDormant(message); await this._recupereMoralChateauDormant(message)
await this._recupereChance(); await this._recupereChance()
await this.transformerStress(); await this.transformerStress()
await this.retourSeuilDeReve(message); await this.retourSeuilDeReve(message)
await this.setBonusPotionSoin(0); await this.setBonusPotionSoin(0)
await this.retourSust(message); await this.retourSust(message)
await this.$perteReveEnchantementsChateauDormants(); await this.$perteReveEnchantementsChateauDormants()
await this.$suppressionLancementsSort(); await this.$suppressionLancementsSort()
await RdDCoeur.applyCoeurChateauDormant(this, message); await RdDCoeur.applyCoeurChateauDormant(this, message);
if (message.content != "") { if (message.content != "") {
message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`; message.content = `A la fin Chateau Dormant, ${message.content}<br>Un nouveau jour se lève`;
@@ -430,11 +418,13 @@ export class RdDActor extends RdDBaseActorSang {
} }
async _recupereMoralChateauDormant(message) { async _recupereMoralChateauDormant(message) {
await this.update({ 'system.compteurs.bonmoments': [] }, { render: false })
if (!ReglesOptionnelles.isUsing("recuperation-moral")) { return } if (!ReglesOptionnelles.isUsing("recuperation-moral")) { return }
const etatMoral = this.system.sommeil?.moral ?? 'neutre'; const etatMoral = this.system.sommeil?.moral ?? MORAL.NEUTRE
const jetMoral = await this._jetDeMoral(etatMoral); const jetMoral = await this._jetDeMoral(etatMoral)
message.content += ` -- le jet de moral est ${etatMoral}, le moral ` + this._messageAjustementMoral(jetMoral.ajustement); message.content += ` -- le jet de moral est ${etatMoral}, le moral ` + this._messageAjustementMoral(jetMoral.ajustement)
} }
_messageAjustementMoral(ajustement) { _messageAjustementMoral(ajustement) {
@@ -708,14 +698,14 @@ export class RdDActor extends RdDBaseActorSang {
const rencontre = await game.system.rdd.rencontresTMR.getReveDeDragon(force); const rencontre = await game.system.rdd.rencontresTMR.getReveDeDragon(force);
let rollData = { let rollData = {
actor: this, actor: this,
competence: this.getDraconicOuPossession(), competence: this.getDraconicOuPossession().find(it => true),
canClose: false, canClose: false,
rencontre: rencontre, rencontre: rencontre,
tmr: true, tmr: true,
use: { libre: false, conditions: false }, use: { libre: false, conditions: false },
forceCarac: { 'reve-actuel': { label: "Rêve Actuel", value: this.getReveActuel() } } forceCarac: this.getCaracReveActuel()
} }
rollData.competence.system.defaut_carac = 'reve-actuel'; rollData.competence.system.defaut_carac = CARACS.REVE_ACTUEL
const dialog = await RdDRoll.create(this, rollData, const dialog = await RdDRoll.create(this, rollData,
{ html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-reve-de-dragon.hbs' }, { html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-reve-de-dragon.hbs' },
@@ -1102,12 +1092,13 @@ export class RdDActor extends RdDBaseActorSang {
} }
$createSortReserve(sort) { $createSortReserve(sort) {
const ptReve = Number.isInteger(sort.system.ptreve) ? Number(sort.system.ptreve) : Number(sort.system.ptreve.match(/\d+/))
this.createEmbeddedDocuments("Item", this.createEmbeddedDocuments("Item",
[{ [{
type: ITEM_TYPES.sortreserve, type: ITEM_TYPES.sortreserve,
name: sort.name, name: sort.name,
img: sort.img, img: sort.img,
system: { sortid: sort.id, draconic: sort.system.draconic, ptreve: Number(sort.system.ptreve.match(/\d+/)), coord: 'A1', heurecible: 'Vaisseau' } system: { sortid: sort.id, draconic: sort.system.draconic, ptreve: ptReve, coord: 'A1', heurecible: 'Vaisseau' }
}], }],
{ renderSheet: true }) { renderSheet: true })
} }
@@ -1211,17 +1202,21 @@ export class RdDActor extends RdDBaseActorSang {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async jetDeMoral(situation, messageReussi = undefined, messageManque = undefined) { async jetDeMoral(situation, bonmoment = "") {
const jetMoral = await this._jetDeMoral(situation); if (bonmoment != "" && bonmoment != undefined && this.system.compteurs.bonmoments.includes(bonmoment)) {
const finMessage = (jetMoral.succes ? messageReussi : messageManque) ?? (jetMoral.ajustement == 0 ? "Vous gardez votre moral" : jetMoral.ajustement > 0 ? "Vous gagnez du moral" : "Vous perdez du moral"); ui.notifications.info(`${this.name} a déjà gagné du moral après avoir passé un bon moment (${bonmoment}) pendant la journée, pas de gain de moral`)
return
}
const jetMoral = await this._jetDeMoral(situation, bonmoment)
const finMessage = (jetMoral.ajustement == 0 ? "Vous gardez votre moral" : jetMoral.ajustement > 0 ? "Vous gagnez du moral" : "Vous perdez du moral");
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getOwners(this), whisper: ChatUtility.getOwners(this),
content: `${finMessage} - jet ${jetMoral.succes ? "réussi" : "manqué"} en situation ${situation} (${jetMoral.jet}/${jetMoral.difficulte}).` content: `${finMessage} - jet ${jetMoral.succes ? "réussi" : "manqué"} en situation ${SITUATION_MORAL[situation] ?? situation} (${jetMoral.jet}/${jetMoral.difficulte}).`
}); })
return jetMoral.ajustement; return jetMoral.ajustement
} }
async _jetDeMoral(situation) { async _jetDeMoral(situation, bonmoment = "") {
const moralActuel = Misc.toInt(this.system.compteurs.moral.value); const moralActuel = Misc.toInt(this.system.compteurs.moral.value);
const jet = await RdDDice.rollTotal("1d20"); const jet = await RdDDice.rollTotal("1d20");
const difficulte = 10 + moralActuel; const difficulte = 10 + moralActuel;
@@ -1233,14 +1228,18 @@ export class RdDActor extends RdDBaseActorSang {
difficulte: difficulte, difficulte: difficulte,
succes: succes, succes: succes,
ajustement: this._calculAjustementMoral(succes, moralActuel, situation) ajustement: this._calculAjustementMoral(succes, moralActuel, situation)
}; }
await this.moralIncDec(jetMoral.ajustement); await this.moralIncDec(jetMoral.ajustement, bonmoment);
return jetMoral; return jetMoral;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async moralIncDec(ajustementMoral) { async moralIncDec(ajustementMoral, bonmoment = "") {
if (ajustementMoral != 0) { if (ajustementMoral != 0) {
if (ajustementMoral > 0 && bonmoment != "" && bonmoment != undefined) {
const bonmoments = [...this.system.compteurs.bonmoments, bonmoment]
await this.update({ 'system.compteurs.bonmoments': bonmoments }, { render: false })
}
const startMoral = parseInt(this.system.compteurs.moral.value) const startMoral = parseInt(this.system.compteurs.moral.value)
const moralTheorique = startMoral + ajustementMoral const moralTheorique = startMoral + ajustementMoral
if (moralTheorique > 3) { // exaltation if (moralTheorique > 3) { // exaltation
@@ -1261,13 +1260,14 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
_calculAjustementMoral(succes, moral, situation) { _calculAjustementMoral(succes, moral, situation) {
switch (situation) { switch (situation) {
case 'heureux': case 'heureuse': return succes ? 1 : 0; case MORAL.TRESHEUREUX: return succes ? 2 : 1
case 'malheureuse': case 'malheureux': return succes ? 0 : -1; case MORAL.HEUREUX: case 'heureuse': return succes ? 1 : 0
case 'neutre': case MORAL.MALHEUREUX: case 'malheureuse': return succes ? 0 : -1
if (succes && moral < 0) return 1; case MORAL.NEUTRE:
if (!succes && moral > 0) return -1; if (succes && moral < 0) return 1
if (!succes && moral > 0) return -1
} }
return 0; return 0
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -1316,6 +1316,15 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
async consommerNourritureboisson(itemId, choix = { doses: 1, seForcer: false, supprimerSiZero: false }) { async consommerNourritureboisson(itemId, choix = { doses: 1, seForcer: false, supprimerSiZero: false }) {
const item = this.getItem(itemId)
if (!item.getUtilisationCuisine()) {
return
}
if (choix.doses > item.system.quantite) {
ui.notifications.warn(`Il n'y a pas assez de ${item.name} pour manger ${choix.doses}`)
return
}
if (!this.isOwner) { if (!this.isOwner) {
RdDBaseActor.remoteActorCall({ RdDBaseActor.remoteActorCall({
tokenId: this.token?.id, tokenId: this.token?.id,
@@ -1324,35 +1333,26 @@ export class RdDActor extends RdDBaseActorSang {
}) })
return return
} }
const item = this.getItem(itemId)
if (!item.getUtilisationCuisine()) {
return;
}
if (choix.doses > item.system.quantite) {
ui.notifications.warn(`Il n'y a pas assez de ${item.name} pour manger ${choix.doses}`)
return;
}
if (!this._apprecierCuisine(item, choix.seForcer)) {
ui.notifications.info(`${this.name} ne n'arrive pas à manger de ${item.name}`)
return;
}
await this.manger(item, choix.doses, { diminuerQuantite: false });
await this.boire(item, choix.doses, { diminuerQuantite: false });
await item.diminuerQuantite(choix.doses, choix);
}
async _apprecierCuisine(item, seForcer) { if (await this._surmonterExotisme(item)) {
const surmonteExotisme = await this._surmonterExotisme(item, seForcer); if (item.system.qualite > 0) {
if (surmonteExotisme) { new Apprecier(this, item.system.appreciation, item.system.qualite).apprecier()
await this.apprecier(CARACS.ODORATGOUT, 'cuisine', item.system.qualite, item.system.boisson ? "apprécie la boisson" : "apprécie le plat"); }
await this.onConsommerNourritureboisson(item, choix)
} }
else if (seForcer) { else if (choix.seForcer) {
await this.jetDeMoral('malheureux'); await this.jetDeMoral(MORAL.MALHEUREUX)
await this.onConsommerNourritureboisson(item, choix)
} }
else { else {
return false; ui.notifications.info(`${this.name} ne n'arrive pas à manger de ${item.name}`)
} }
return true; }
async onConsommerNourritureboisson(item, choix) {
await this.manger(item, choix.doses, { diminuerQuantite: false })
await this.boire(item, choix.doses, { diminuerQuantite: false })
await item.diminuerQuantite(choix.doses, choix)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -1365,7 +1365,7 @@ export class RdDActor extends RdDBaseActorSang {
const rolled = await this.doRollCaracCompetence(CARACS.VOLONTE, competence, difficulte, { title: `tente de surmonter l'exotisme de ${item.name}` }) const rolled = await this.doRollCaracCompetence(CARACS.VOLONTE, competence, difficulte, { title: `tente de surmonter l'exotisme de ${item.name}` })
return rolled.isSuccess return rolled.isSuccess
} }
return true; return true
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -1378,7 +1378,7 @@ export class RdDActor extends RdDBaseActorSang {
} }
const rolled = await this.doRollCaracCompetence(carac, undefined, 0, { title }); const rolled = await this.doRollCaracCompetence(carac, undefined, 0, { title });
if (rolled?.isSuccess) { if (rolled?.isSuccess) {
await this.jetDeMoral('heureux'); await this.jetDeMoral(MORAL.HEUREUX);
} }
} }
@@ -1445,7 +1445,7 @@ export class RdDActor extends RdDBaseActorSang {
ethylismeData.perteEndurance = await this.santeIncDec("endurance", -perte); ethylismeData.perteEndurance = await this.santeIncDec("endurance", -perte);
if (!ethylisme.jet_moral) { if (!ethylisme.jet_moral) {
ethylismeData.jetMoral = await this._jetDeMoral('heureuse'); ethylismeData.jetMoral = await this._jetDeMoral(MORAL.HEUREUX, "Ethylisme");
if (ethylismeData.jetMoral.ajustement == 1) { if (ethylismeData.jetMoral.ajustement == 1) {
ethylismeData.moralAlcool = 'heureux'; ethylismeData.moralAlcool = 'heureux';
ethylisme.jet_moral = true; ethylisme.jet_moral = true;
@@ -1453,7 +1453,7 @@ export class RdDActor extends RdDBaseActorSang {
ethylismeData.jetMoral.ajustement = -1; ethylismeData.jetMoral.ajustement = -1;
ethylismeData.moralAlcool = 'triste'; ethylismeData.moralAlcool = 'triste';
ethylisme.jet_moral = true; ethylisme.jet_moral = true;
await this.moralIncDec(-1); await this.moralIncDec(-1, "Ethylisme");
} }
} }
if (ethylisme.value < 0) { if (ethylisme.value < 0) {
@@ -1647,7 +1647,8 @@ export class RdDActor extends RdDBaseActorSang {
return return
} }
hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM) hideChatMessage = hideChatMessage == 'hide' || (Misc.isRollModeHiddenToPlayer() && !game.user.isGM)
let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence, rollData.jetResistance); let xpData = await this._appliquerExperience(rollData.rolled, rollData.selectedCarac.label, rollData.competence,
rollData.v2 ? rollData.type.resistance : rollData.jetResistance);
if (xpData.length) { if (xpData.length) {
const content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-gain-xp.hbs`, { const content = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-actor-gain-xp.hbs`, {
actor: this, actor: this,
@@ -1745,16 +1746,16 @@ export class RdDActor extends RdDBaseActorSang {
type: { allowed: [ROLL_TYPE_SORT], current: ROLL_TYPE_SORT } type: { allowed: [ROLL_TYPE_SORT], current: ROLL_TYPE_SORT }
}; };
const dialog = await RollDialog.create(rollData, { const dialog = await RollDialog.create(rollData, {
callbacks: [roll => { callbacks: [async roll => {
this.tmrApp?.restoreTMRAfterAction(); await this.tmrApp?.restoreTMRAfterAction();
if (roll.closeTMR) { if (roll.closeTMR) {
this.tmrApp?.close(); await this.tmrApp?.close();
this.tmrApp = undefined; this.tmrApp = undefined;
} }
}], }],
onRollDone: RollDialog.onRollDoneClose, onRollDone: RollDialog.onRollDoneClose,
onClose: () => { onClose: async () => {
this.tmrApp?.restoreTMRAfterAction(); await this.tmrApp?.restoreTMRAfterAction();
} }
}); });
this.tmrApp?.setTMRPendingAction(dialog); this.tmrApp?.setTMRPendingAction(dialog);
@@ -1935,7 +1936,7 @@ export class RdDActor extends RdDBaseActorSang {
async getTacheBlessure(blesse, blessure) { async getTacheBlessure(blesse, blessure) {
const gravite = blessure?.system.gravite ?? 0; const gravite = blessure?.system.gravite ?? 0;
if (gravite > 0) { if (gravite > 0) {
const tache = this.itemTypes['tache'].find(it => it.system.itemId == blessure.id) const tache = this.itemTypes[ITEM_TYPES.tache].find(it => it.system.itemId == blessure.id)
?? await RdDItemBlessure.createTacheSoinBlessure(this, gravite); ?? await RdDItemBlessure.createTacheSoinBlessure(this, gravite);
await blessure?.updateTacheSoinBlessure(tache); await blessure?.updateTacheSoinBlessure(tache);
return tache return tache
@@ -1955,8 +1956,7 @@ export class RdDActor extends RdDBaseActorSang {
diff: { value: diff ?? 0 } diff: { value: diff ?? 0 }
} }
} }
RollDialog.create(rollData, foundry.utils.mergeObject(options, { onRollDone: RollDialog.onRollDoneClose })) return await RollDialog.create(rollData, options)
return
} }
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
@@ -1990,8 +1990,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { tache: { key: tache.id, forced: options.forced } }, selected: { tache: { key: tache.id, forced: options.forced } },
type: { allowed: [PART_TACHE], current: PART_TACHE } type: { allowed: [PART_TACHE], current: PART_TACHE }
} }
RollDialog.create(rollData, options) return await RollDialog.create(rollData, options)
return
} }
const compData = this.getCompetence(tache.system.competence) const compData = this.getCompetence(tache.system.competence)
@@ -2035,8 +2034,8 @@ export class RdDActor extends RdDBaseActorSang {
await this.santeIncDec("fatigue", rollData.tache.system.fatigue); await this.santeIncDec("fatigue", rollData.tache.system.fatigue);
await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-tache.hbs'); await RdDRollResult.displayRollData(rollData, this, 'chat-resultat-tache.hbs');
if (options?.onRollAutomate) { if (options?.callbacks) {
options.onRollAutomate(rollData); await Promise.all(callbacks.map(callback => callback(rollData)))
} }
} }
@@ -2050,8 +2049,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { jeu: { key: jeu.id } }, selected: { jeu: { key: jeu.id } },
type: { allowed: [ROLL_TYPE_JEU], current: ROLL_TYPE_JEU } type: { allowed: [ROLL_TYPE_JEU], current: ROLL_TYPE_JEU }
} }
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose }) return await RollDialog.create(rollData)
return
} }
const listCarac = jeu.system.caraccomp.toLowerCase().split(/[.,:\/-]/).map(it => it.trim()); const listCarac = jeu.system.caraccomp.toLowerCase().split(/[.,:\/-]/).map(it => it.trim());
@@ -2079,8 +2077,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { meditation: { key: id } }, selected: { meditation: { key: id } },
type: { allowed: [ROLL_TYPE_MEDITATION], current: ROLL_TYPE_MEDITATION } type: { allowed: [ROLL_TYPE_MEDITATION], current: ROLL_TYPE_MEDITATION }
} }
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose }) return await RollDialog.create(rollData)
return
} }
const competence = foundry.utils.duplicate(this.getCompetence(meditation.system.competence)); const competence = foundry.utils.duplicate(this.getCompetence(meditation.system.competence));
@@ -2279,7 +2276,7 @@ export class RdDActor extends RdDBaseActorSang {
const xpCompetence = competence ? xp - xpCarac : 0; const xpCompetence = competence ? xp - xpCarac : 0;
if (jetResistance) { if (jetResistance) {
const message = `Jet de résistance ${jetResistance}, l'expérience est limitée à 1`; const message = `Jet de résistance, l'expérience est limitée à 1`;
ui.notifications.info(message); ui.notifications.info(message);
console.log(message) console.log(message)
// max 1 xp sur jets de résistance // max 1 xp sur jets de résistance
@@ -2509,77 +2506,16 @@ export class RdDActor extends RdDBaseActorSang {
if (!blessure.system.premierssoins.done) { if (!blessure.system.premierssoins.done) {
const tache = await this.getTacheBlessure(blesse, blessure); const tache = await this.getTacheBlessure(blesse, blessure);
return await this.rollTache(tache.id, { return await this.rollTache(tache.id, {
onRollAutomate: async r => blesse.onRollTachePremiersSoins(blessureId, r), callbacks: [async r => await blesse.onRollTachePremiersSoins(blessureId, r, this.id)],
title: 'Premiers soins', title: 'Premiers soins', forced: true
forced: true
}); });
} }
else if (!blessure.system.soinscomplets.done) { else if (!blessure.system.soinscomplets.done) {
const diff = blessure.system.difficulte + (blessure.system.premierssoins.bonus ?? 0); const diff = blessure.system.difficulte + (blessure.system.premierssoins.bonus ?? 0);
return await this.rollCaracCompetence(CARACS.DEXTERITE, "Chirurgie", diff, { return await this.rollCaracCompetence(CARACS.DEXTERITE, "Chirurgie", diff, {
title: "Soins complets", callbacks: [async r => await blesse.onRollSoinsComplets(blessureId, r, this.id)],
onRollAutomate: r => blesse.onRollSoinsComplets(blessureId, r), onRollDone: RollDialog.onRollDoneClose,
forced: true title: "Soins complets", forced: true
})
}
}
}
async onRollTachePremiersSoins(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollTachePremiersSoins', args: [blessureId, rollData]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && !blessure.system.premierssoins.done) {
const tache = rollData.tache;
if (rollData.rolled.isETotal) {
await blessure.update({
'system.difficulte': blessure.system.difficulte - 1,
'system.premierssoins.tache': Math.max(0, tache.system.points_de_tache_courant)
})
}
else {
const bonus = tache.system.points_de_tache_courant - tache.system.points_de_tache
await blessure.update({
'system.premierssoins': {
done: (bonus >= 0),
bonus: Math.max(0, bonus),
tache: Math.max(0, tache.system.points_de_tache_courant)
}
})
if (bonus >= 0) {
await this.deleteEmbeddedDocuments('Item', [tache.id])
}
}
}
}
async onRollSoinsComplets(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollSoinsComplets', args: [blessureId, rollData]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && blessure.system.premierssoins.done && !blessure.system.soinscomplets.done) {
// TODO: update de la blessure: passer par le MJ!
if (rollData.rolled.isETotal) {
await blessure.setSoinsBlessure({
difficulte: blessure.system.difficulte - 1,
premierssoins: { done: false, bonus: 0 }, soinscomplets: { done: false, bonus: 0 },
})
}
else {
// soins complets finis
await blessure.setSoinsBlessure({
soinscomplets: { done: true, bonus: Math.max(0, rollData.rolled.ptTache) },
}) })
} }
} }
@@ -2587,7 +2523,12 @@ export class RdDActor extends RdDBaseActorSang {
/* -------------------------------------------- */ /* -------------------------------------------- */
conjurerPossession(possession) { conjurerPossession(possession) {
RdDPossession.onConjurerPossession(this, possession) if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
RdDPossessionV2.rollConjurerPossession(this, possession)
}
else {
RdDPossession.onConjurerPossession(this, possession)
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -2990,15 +2931,6 @@ export class RdDActor extends RdDBaseActorSang {
await this.diminuerQuantiteObjet(potion.id, 1, { supprimerSiZero: potion.supprimer }); await this.diminuerQuantiteObjet(potion.id, 1, { supprimerSiZero: potion.supprimer });
} }
/* -------------------------------------------- */
async onUpdateActor(update, options, actorId) {
const updatedEndurance = update?.system?.sante?.endurance
if (updatedEndurance && options.diff) {
await this.setEffect(STATUSES.StatusUnconscious, updatedEndurance.value == 0)
}
await super.onUpdateActor(update, options, actorId)
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async onPreUpdateItem(item, change, options, id) { async onPreUpdateItem(item, change, options, id) {
if (item.isCompetencePersonnage() && item.system.defaut_carac && item.system.xp) { if (item.isCompetencePersonnage() && item.system.defaut_carac && item.system.xp) {
@@ -3159,7 +3091,7 @@ export class RdDActor extends RdDBaseActorSang {
selected: { oeuvre: { key: oeuvre.id } }, selected: { oeuvre: { key: oeuvre.id } },
type: { allowed: [PART_OEUVRE], current: PART_OEUVRE, }, type: { allowed: [PART_OEUVRE], current: PART_OEUVRE, },
} }
await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose }) return await RollDialog.create(rollData)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -3264,8 +3196,7 @@ export class RdDActor extends RdDBaseActorSang {
cuisine: { key: recette.id } cuisine: { key: recette.id }
} }
} }
RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose }) return await RollDialog.create(rollData)
return
} }
const artData = { const artData = {
@@ -3315,8 +3246,7 @@ export class RdDActor extends RdDBaseActorSang {
cuisine: { key: item.id } cuisine: { key: item.id }
} }
} }
RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose }) return await RollDialog.create(rollData)
return
} }
if (item.getUtilisationCuisine() == 'brut') { if (item.getUtilisationCuisine() == 'brut') {

View File

@@ -1,4 +1,4 @@
import { renderTemplate, SHOW_DICE, SYSTEM_RDD } from "../constants.js"; import { RDD_CONFIG, renderTemplate, SHOW_DICE, SYSTEM_RDD } from "../constants.js";
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDResolutionTable } from "../rdd-resolution-table.js"; import { RdDResolutionTable } from "../rdd-resolution-table.js";
@@ -22,13 +22,16 @@ import { DialogValidationEncaissement } from "../dialog-validation-encaissement.
import { RdDCombat } from "../rdd-combat.js"; import { RdDCombat } from "../rdd-combat.js";
import { RdDEmpoignade } from "../rdd-empoignade.js"; import { RdDEmpoignade } from "../rdd-empoignade.js";
import { RdDPossession } from "../rdd-possession.js"; import { RdDPossession } from "../rdd-possession.js";
import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, POSSESSION_SANS_DRACONIC } from "../item/base-items.js"; import { BASE_CORPS_A_CORPS, BASE_ESQUIVE, CATEGORIES_COMPETENCES_CREATURES } from "../item/base-items.js";
import { RollDataAjustements } from "../rolldata-ajustements-v1.js"; import { RollDataAjustements } from "../rolldata-ajustements-v1.js";
import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs"; import { MappingCreatureArme } from "../item/mapping-creature-arme.mjs";
import RollDialog from "../roll/roll-dialog.mjs"; import RollDialog from "../roll/roll-dialog.mjs";
import { ATTAQUE_ROLL_TYPES, DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE, ROLL_TYPE_COMP, ROLL_TYPE_JEU, ROLL_TYPE_MEDITATION, ROLL_TYPE_OEUVRE, ROLL_TYPE_TACHE } from "../roll/roll-constants.mjs"; import { ATTAQUE_ROLL_TYPES, DEFAULT_ROLL_TYPES, DIFF, ROLL_TYPE_ATTAQUE } from "../roll/roll-constants.mjs";
import { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js"; import { OptionsAvancees, ROLL_DIALOG_V2 } from "../settings/options-avancees.js";
import { PART_COMP } from "../roll/roll-part-comp.mjs"; import { PART_COMP } from "../roll/roll-part-comp.mjs";
import { RdDInitiative } from "../initiative.mjs";
import { RdDItemCompetenceCreature } from "../item-competencecreature.js";
import { RdDPossessionV2 } from "../rdd-possession-v2.mjs";
/** /**
* Classe de base pour les acteurs disposant de rêve (donc, pas des objets) * Classe de base pour les acteurs disposant de rêve (donc, pas des objets)
@@ -45,39 +48,24 @@ export class RdDBaseActorReve extends RdDBaseActor {
} }
getCarac() { getCarac() {
return foundry.utils.mergeObject(this.system.carac, const carac = super.getCarac()
{ foundry.utils.mergeObject(carac, this.getCaracReveActuel())
'reve-actuel': this.getCaracReveActuel(), foundry.utils.mergeObject(carac, this.getCaracCompetenceCreature(), { overwrite: false })
'chance-actuelle': this.getCaracChanceActuelle() return carac
},
{ inplace: false })
}
getCaracChanceActuelle() {
return {
label: 'Chance actuelle',
value: this.getChanceActuel(),
type: "number"
};
}
getCaracReveActuel() {
return {
label: 'Rêve actuel',
value: this.getReveActuel(),
type: "number"
};
} }
getTaille() { return Misc.toInt(this.system.carac.taille?.value) } getTaille() { return Misc.toInt(this.system.carac.taille?.value) }
getConstitution() { return this.getReve() } getConstitution() { return this.getReve() }
getForce() { return this.getReve() } getForce() { return this.getReve() }
getAgilite() { return this.getForce() } getAgilite() { return this.getForce() }
getReve() { return Misc.toInt(this.system.carac.reve?.value) } getReve() { return Misc.toInt(this.system.carac.reve?.value) }
getChance() { return this.getReve() } getChance() { return this.getReve() }
getChanceActuel() { return this.getChance() }
getCaracChanceActuelle() { return { [CARACS.CHANCE_ACTUELLE]: { label: 'Chance actuelle', value: this.getChanceActuel(), type: "number" } } }
getReveActuel() { return this.getReve() } getReveActuel() { return this.getReve() }
getChanceActuel() { return this.getChance() } getCaracReveActuel() { return { [CARACS.REVE_ACTUEL]: { label: "Rêve Actuel", value: this.getReveActuel(), type: "number" } } }
getEnduranceMax() { return Math.max(1, this.getTaille() + this.getConstitution()) } getEnduranceMax() { return Math.max(1, this.getTaille() + this.getConstitution()) }
getEncombrementMax() { return (this.getForce() + this.getTaille()) / 2 } getEncombrementMax() { return (this.getForce() + this.getTaille()) / 2 }
@@ -114,11 +102,54 @@ export class RdDBaseActorReve extends RdDBaseActor {
return this.system.carac[competence.system.defaut_carac].value; return this.system.carac[competence.system.defaut_carac].value;
} }
getDraconics() { return [] }
getDraconicOuPossession() {
return [
...this.getDraconics(),
...this.itemTypes[ITEM_TYPES.competencecreature].filter(it => it.isCompetencePossession()),
this.getConjurationNaturelle()
].sort(Misc.descending(it => it.system.niveau));
}
getConjurations() {
return this.getDraconicOuPossession()
.map(it => this.toActionConjuration(it))
}
getConjurationNaturelle() {
return new RdDItemCompetenceCreature({
name: 'Sans compétence',
type: ITEM_TYPES.competencecreature,
img: RDD_CONFIG.icons.possession,
system: {
carac_value: this.getReveActuel(),
niveau: 0,
default_diffLibre: 0,
categorie: CATEGORIES_COMPETENCES_CREATURES.possession.key,
ispossession: true,
}
})
}
toActionConjuration(comp) {
const caracCode = this.isPersonnage() ? CARACS.REVE_ACTUEL : CARACS.REVE
const caracValue = this.getReveActuel()
const ajustement = this.getEtatGeneral()
return {
label: `Conjuration (${comp.name})`,
action: 'possession',
initOnly: false,
comp: comp,
carac: { key: caracCode, value: caracValue },
initiative: RdDInitiative.getRollInitiative(caracValue, comp.system.niveau, ajustement)
}
}
listActions({ isAttaque = false, isEquipe = false }) { listActions({ isAttaque = false, isEquipe = false }) {
return this.itemTypes[ITEM_TYPES.competencecreature] return this.itemTypes[ITEM_TYPES.competencecreature]
.filter(it => it.isAttaque()) .filter(it => it.isAttaque())
.map(it => it.attaqueCreature()) .map(it => it.attaqueCreature())
.filter(it => it != undefined); .filter(it => it != undefined)
} }
async computeArmure(dmg) { return this.getProtectionNaturelle() } async computeArmure(dmg) { return this.getProtectionNaturelle() }
@@ -130,13 +161,14 @@ export class RdDBaseActorReve extends RdDBaseActor {
async santeIncDec(name, inc, isCritique = false) { } async santeIncDec(name, inc, isCritique = false) { }
async finDeRound(options = { terminer: false }) { async finDeRound(options = { terminer: false }) {
await this.$finDeRoundSuppressionEffetsTermines(options); await this.finDeRoundSuppressionEffetsTermines(options)
await this.finDeRoundBlessures(); await this.finDeRoundBlessures()
await this.$finDeRoundSupprimerObsoletes(); await this.finDeRoundSupprimerObsoletes()
await this.$finDeRoundEmpoignade(); await this.finDeRoundEmpoignade()
await this.finDeRoundPossession()
} }
async $finDeRoundSuppressionEffetsTermines(options) { async finDeRoundSuppressionEffetsTermines(options) {
for (let effect of this.getEffects()) { for (let effect of this.getEffects()) {
if (effect.duration.type !== 'none' && (effect.duration.remaining <= 0 || options.terminer)) { if (effect.duration.type !== 'none' && (effect.duration.remaining <= 0 || options.terminer)) {
await effect.delete(); await effect.delete();
@@ -148,20 +180,22 @@ export class RdDBaseActorReve extends RdDBaseActor {
async finDeRoundBlessures() { async finDeRoundBlessures() {
} }
async $finDeRoundSupprimerObsoletes() { async finDeRoundSupprimerObsoletes() {
const obsoletes = [] const obsoletes = []
.concat(this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp <= 0)) .concat(this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp <= 0))
.concat(this.itemTypes[ITEM_TYPES.possession].filter(it => it.system.compteur < -2 || it.system.compteur > 2)) .map(it => it.id)
.map(it => it.id);
await this.deleteEmbeddedDocuments('Item', obsoletes); await this.deleteEmbeddedDocuments('Item', obsoletes);
} }
async $finDeRoundEmpoignade() { async finDeRoundEmpoignade() {
const immobilisations = this.itemTypes[ITEM_TYPES.empoignade].filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id); await Promise.all(this.itemTypes[ITEM_TYPES.empoignade]
immobilisations.forEach(emp => RdDEmpoignade.onImmobilisation(this, .filter(it => it.system.pointsemp >= 2 && it.system.empoigneurid == this.id)
game.actors.get(emp.system.empoigneid), .map(async it => await RdDEmpoignade.onImmobilisation(this, it)))
emp }
))
async finDeRoundPossession() {
await Promise.all(this.itemTypes[ITEM_TYPES.possession]
.map(async it => await RdDPossessionV2.onPossession(this, it)))
} }
async setSonne(sonne = true) { } async setSonne(sonne = true) { }
@@ -200,8 +234,6 @@ export class RdDBaseActorReve extends RdDBaseActor {
return false return false
} }
getDraconicOuPossession() { return POSSESSION_SANS_DRACONIC }
getPossession(possessionId) { getPossession(possessionId) {
return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId); return this.itemTypes[ITEM_TYPES.possession].find(it => it.system.possessionid == possessionId);
} }
@@ -210,6 +242,13 @@ export class RdDBaseActorReve extends RdDBaseActor {
return this.itemTypes[ITEM_TYPES.empoignade]; return this.itemTypes[ITEM_TYPES.empoignade];
} }
async updateCarac(caracName, to) {
const path = `system.carac.${caracName}.value`;
let updates = {};
updates[path] = Number.parseInt(to)
await this.update(updates, { noHook: true });
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async updateCreatureCompetence(idOrName, fieldName, value) { async updateCreatureCompetence(idOrName, fieldName, value) {
let competence = this.getCompetence(idOrName); let competence = this.getCompetence(idOrName);
@@ -284,8 +323,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
diff: { value: diff } diff: { value: diff }
} }
} }
RollDialog.create(rollData, options) return await RollDialog.create(rollData, options)
return
} }
const competence = this.getCompetence(compName); const competence = this.getCompetence(compName);
@@ -302,7 +340,10 @@ export class RdDBaseActorReve extends RdDBaseActor {
competence: competence, competence: competence,
show: { title: options?.title ?? '' } show: { title: options?.title ?? '' }
}, },
callbacks: [async r => this.$onRollCompetence(r, options)] callbacks: [
async r => this.$onRollCompetence(r, options),
...(options?.callbacks ?? [])
]
}); });
} }
/** /**
@@ -339,6 +380,19 @@ export class RdDBaseActorReve extends RdDBaseActor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async roll() { async roll() {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
type: {
allowed: DEFAULT_ROLL_TYPES,
current: PART_COMP,
},
selected: {
diff: { type: DIFF.DEFAUT }
}
}
return await RollDialog.create(rollData)
}
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
const carac = this.getCarac() const carac = this.getCarac()
@@ -359,6 +413,26 @@ export class RdDBaseActorReve extends RdDBaseActor {
}) })
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollReveActuel({ diff = 0, resistance = false }) {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = {
ids: { actorId: this.id },
type: {
allowed: [PART_COMP],
current: PART_COMP,
resistance: resistance
},
selected: {
carac: { key: CARACS.REVE_ACTUEL, forced: true },
comp: resistance ? { key: undefined, forced: true } : undefined,
diff: { type: DIFF.DEFAUT, value: diff }
}
}
return await RollDialog.create(rollData)
}
return this.rollCarac(CARACS.REVE_ACTUEL, { diff, resistance })
}
async rollCarac(caracName, options = {}) { async rollCarac(caracName, options = {}) {
if (Grammar.equalsInsensitive(caracName, CARACS.TAILLE)) { if (Grammar.equalsInsensitive(caracName, CARACS.TAILLE)) {
return return
@@ -366,14 +440,18 @@ export class RdDBaseActorReve extends RdDBaseActor {
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { allowed: DEFAULT_ROLL_TYPES, current: PART_COMP }, type: {
allowed: options.resistance ? [PART_COMP] : DEFAULT_ROLL_TYPES,
current: PART_COMP,
resistance: options.resistance
},
selected: { selected: {
carac: { key: caracName }, carac: { key: caracName },
comp: options.resistance ? { key: undefined, forced: true } : undefined comp: options.resistance ? { key: undefined, forced: true } : undefined,
diff: { type: DIFF.DEFAUT, value: options.diff ?? 0 }
} }
} }
RollDialog.create(rollData, options) return await RollDialog.create(rollData, options)
return
} }
foundry.utils.mergeObject(options, { resistance: false, diff: 0 }, { overwrite: false }) foundry.utils.mergeObject(options, { resistance: false, diff: 0 }, { overwrite: false })
@@ -404,17 +482,15 @@ export class RdDBaseActorReve extends RdDBaseActor {
async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) { async rollCompetence(idOrName, options = { tryTarget: true, arme: undefined }) {
RdDEmpoignade.checkEmpoignadeEnCours(this) RdDEmpoignade.checkEmpoignadeEnCours(this)
const competence = this.getCompetence(idOrName); const competence = this.getCompetence(idOrName);
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
const rollData = { const rollData = {
ids: { actorId: this.id }, ids: { actorId: this.id },
type: { allowed: options.arme ? ATTAQUE_ROLL_TYPES : DEFAULT_ROLL_TYPES }, type: { allowed: DEFAULT_ROLL_TYPES },
selected: { selected: {
carac: competence.type == ITEM_TYPES.competencecreature ? { key: competence.name } : undefined, carac: competence.type == ITEM_TYPES.competencecreature ? { key: competence.name } : undefined,
comp: { key: competence.name }, comp: { key: competence.name },
diff: { type: options.arme ? DIFF.ATTAQUE : DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 }, diff: { type: DIFF.LIBRE, value: competence.system.default_diffLibre ?? 0 },
attaque: options.arme ? { arme: { key: options.arme.id } } : undefined
} }
} }
return await RollDialog.create(rollData) return await RollDialog.create(rollData)
@@ -486,8 +562,8 @@ export class RdDBaseActorReve extends RdDBaseActor {
type: { type: {
allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE allowed: [ROLL_TYPE_ATTAQUE], current: ROLL_TYPE_ATTAQUE
} }
}; }
return await RollDialog.create(rollData) return await RollDialog.create(rollData, { onRollDone: RollDialog.onRollDoneClose })
} }
}) })
} }
@@ -495,16 +571,18 @@ export class RdDBaseActorReve extends RdDBaseActor {
/** -------------------------------------------- /** --------------------------------------------
* @param {*} arme item d'arme/compétence de créature * @param {*} arme item d'arme/compétence de créature
* @param {*} categorieArme catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession * @param {*} maniement catégorie d'attaque à utiliser: competence (== melee), lancer, tir; naturelle, possession
* @returns * @returns
*/ */
rollArme(arme, categorieArme = 'competence', token = undefined) { async rollArme(arme, maniement = 'competence', token = undefined) {
token = token ?? RdDUtility.getSelectedToken(this) token = token ?? RdDUtility.getSelectedToken(this)
const compToUse = RdDItemArme.getCompetenceArme(arme, categorieArme) const compToUse = RdDItemArme.getCompetenceArme(arme, maniement)
if (!RdDItemArme.isUtilisable(arme)) { if (!RdDItemArme.isUtilisable(arme)) {
ui.notifications.warn(`Arme inutilisable: ${arme.name} non équipée ou avec une résistance de 0 ou moins`) ui.notifications.warn(`Arme inutilisable: ${arme.name} non équipée ou avec une résistance de 0 ou moins`)
return return
} }
if (!Targets.hasTargets()) { if (!Targets.hasTargets()) {
RdDConfirm.confirmer({ RdDConfirm.confirmer({
settingConfirmer: "confirmer-combat-sans-cible", settingConfirmer: "confirmer-combat-sans-cible",
@@ -516,7 +594,7 @@ export class RdDBaseActorReve extends RdDBaseActor {
onAction: async () => { onAction: async () => {
this.rollCompetence(compToUse, { tryTarget: false, arme: arme }) this.rollCompetence(compToUse, { tryTarget: false, arme: arme })
} }
}); })
return return
} }
@@ -526,14 +604,19 @@ export class RdDBaseActorReve extends RdDBaseActor {
return return
} }
const competence = this.getCompetence(compToUse) const comp = this.getCompetence(compToUse)
if (competence.isCompetencePossession()) { if (comp.isCompetencePossession()) {
return RdDPossession.onAttaquePossession(target, this, competence); // TODO: vérifier si c'est possible, sinon simplifier
return RdDPossession.onAttaquePossession(target, this, comp);
} }
RdDCombat.rddCombatTarget(target, this, token).attaque(competence, arme); RdDCombat.rddCombatTarget(target, this, token).attaque(comp, arme, maniement)
}) })
} }
rollPossession() {
RdDPossessionV2.rollAttaquePossession(this)
}
verifierForceMin(item) { } verifierForceMin(item) { }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@@ -7,6 +7,8 @@ import { RdDDice } from "../rdd-dice.js";
import { RdDItemBlessure } from "../item/blessure.js"; import { RdDItemBlessure } from "../item/blessure.js";
import { ChatUtility } from "../chat-utility.js"; import { ChatUtility } from "../chat-utility.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDBaseActor } from "./base-actor.js";
import { CARACS } from "../rdd-carac.js";
/** /**
* Classe de base pour les acteurs qui peuvent subir des blessures * Classe de base pour les acteurs qui peuvent subir des blessures
@@ -22,10 +24,18 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
this.system.attributs.encombrement.value = this.getEncombrementMax() this.system.attributs.encombrement.value = this.getEncombrementMax()
} }
getCarac() {
const carac = super.getCarac()
foundry.utils.mergeObject(carac, this.getCaracChanceActuelle())
foundry.utils.mergeObject(carac, this.getCaracVie())
return carac
}
getForce() { return Misc.toInt(this.system.carac.force?.value) } getForce() { return Misc.toInt(this.system.carac.force?.value) }
getConstitution() { return Misc.toInt(this.system.carac.constitution?.value) } getConstitution() { return Misc.toInt(this.system.carac.constitution?.value) }
getVolonte() { return Misc.toInt(this.system.carac.volonte?.value) } getVolonte() { return Misc.toInt(this.system.carac.volonte?.value) }
getCaracVie() { return { [CARACS.VIE]: { label: "Vie", value: this.getVieMax(), type: "number" } } }
getVieMax() { return Misc.toInt(this.system.sante.vie?.max) } getVieMax() { return Misc.toInt(this.system.sante.vie?.max) }
getEnduranceMax() { return Math.max(1, this.getTaille() + this.getConstitution()) } getEnduranceMax() { return Math.max(1, this.getTaille() + this.getConstitution()) }
getFatigueMax() { return this.getEnduranceMax() * 2 } getFatigueMax() { return this.getEnduranceMax() * 2 }
@@ -120,17 +130,15 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
/* -------------------------------------------- */ /* -------------------------------------------- */
async santeIncDec(name, inc, isCritique = false) { async santeIncDec(name, inc, isCritique = false) {
if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) { if (name == 'fatigue' && !ReglesOptionnelles.isUsing("appliquer-fatigue")) {
return; return
}
if (!this.system.sante[name]) {
return
} }
const sante = foundry.utils.duplicate(this.system.sante) const sante = foundry.utils.duplicate(this.system.sante)
let compteur = sante[name]; const compteur = sante[name]
if (!compteur) { const result = { sonne: false }
return; let perteEndurance = 0
}
let result = {
sonne: false,
};
let minValue = name == "vie" ? -this.getSConst() - 1 : 0; let minValue = name == "vie" ? -this.getSConst() - 1 : 0;
result.newValue = Math.max(minValue, Math.min(compteur.value + inc, compteur.max)); result.newValue = Math.max(minValue, Math.min(compteur.value + inc, compteur.max));
@@ -145,16 +153,10 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
if (inc > 0) { // le max d'endurance s'applique seulement à la récupération if (inc > 0) { // le max d'endurance s'applique seulement à la récupération
result.newValue = Math.min(result.newValue, this._computeEnduranceMax()) result.newValue = Math.min(result.newValue, this._computeEnduranceMax())
} }
const perte = compteur.value - result.newValue; perteEndurance = compteur.value - result.newValue;
result.perte = perte; result.perte = perteEndurance
if (perte > 1) {
// Peut-être sonné si 2 points d'endurance perdus d'un coup
foundry.utils.mergeObject(result, await this.jetEndurance(result.newValue));
} else if (inc > 0) {
await this.setSonne(false);
}
if (sante.fatigue && inc < 0) { // Each endurance lost -> fatigue lost if (sante.fatigue && inc < 0) { // Each endurance lost -> fatigue lost
fatigue = perte; fatigue = perteEndurance;
} }
} }
compteur.value = result.newValue; compteur.value = result.newValue;
@@ -163,12 +165,81 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
sante.fatigue.value = Math.max(sante.fatigue.value + fatigue, this.getFatigueMin()); sante.fatigue.value = Math.max(sante.fatigue.value + fatigue, this.getFatigueMin());
} }
await this.update({ "system.sante": sante }, { render: true }) await this.update({ "system.sante": sante }, { render: true })
if (perteEndurance > 1) {
// Peut-être sonné si 2 points d'endurance perdus d'un coup
foundry.utils.mergeObject(result, await this.jetEndurance(result.newValue));
} else if (name == "endurance" && inc > 0) {
await this.setSonne(false);
}
if (this.isDead()) { if (this.isDead()) {
await this.setEffect(STATUSES.StatusComma, true); await this.setEffect(STATUSES.StatusComma, true);
} }
return result return result
} }
async onRollTachePremiersSoins(blessureId, rollData, soigneurId) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollTachePremiersSoins', args: [blessureId, rollData, soigneurId]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && !blessure.system.premierssoins.done) {
const tache = rollData.v2 ? rollData.current.tache.tache : rollData.tache
if (rollData.rolled.isETotal) {
await blessure.update({
'system.difficulte': blessure.system.difficulte - 1,
'system.premierssoins.tache': Math.max(0, tache.system.points_de_tache_courant)
})
}
else {
const bonus = tache.system.points_de_tache_courant - tache.system.points_de_tache
await blessure.update({
'system.premierssoins': {
done: (bonus >= 0),
bonus: Math.max(0, bonus),
tache: Math.max(0, tache.system.points_de_tache_courant)
}
})
if (bonus >= 0 && soigneurId) {
const soigneur = game.actors.get(soigneurId)
await soigneur.deleteEmbeddedDocuments('Item', [tache.id], { render: true })
}
}
}
}
async onRollSoinsComplets(blessureId, rollData) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
tokenId: this.token?.id,
actorId: this.id,
method: 'onRollSoinsComplets', args: [blessureId, rollData]
})
}
const blessure = this.getItem(blessureId, 'blessure')
if (blessure && blessure.system.premierssoins.done && !blessure.system.soinscomplets.done) {
// TODO: update de la blessure: passer par le MJ!
if (rollData.rolled.isETotal) {
await blessure.setSoinsBlessure({
difficulte: blessure.system.difficulte - 1,
premierssoins: { done: false, bonus: 0 }, soinscomplets: { done: false, bonus: 0 },
})
}
else {
// soins complets finis
await blessure.setSoinsBlessure({
soinscomplets: { done: true, bonus: Math.max(0, rollData.rolled.ptTache) },
})
}
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
_computeEnduranceMax() { _computeEnduranceMax() {
const diffVie = this.system.sante.vie.max - this.system.sante.vie.value; const diffVie = this.system.sante.vie.max - this.system.sante.vie.value;
@@ -180,29 +251,55 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
return Math.max(0, Math.min(maxEndVie, maxEndGraves, maxEndCritiques)); return Math.max(0, Math.min(maxEndVie, maxEndGraves, maxEndCritiques));
} }
async onCreateItem(item, options, id) { async onUpdateActor(update, options, actorId) {
switch (item.type) { const updatedEndurance = update?.system?.sante?.endurance
case ITEM_TYPES.blessure: if (updatedEndurance && options.diff) {
await this.changeBleedingState() await this.setEffect(STATUSES.StatusUnconscious, updatedEndurance.value == 0)
break
} }
await super.onUpdateActor(update, options, actorId)
}
async onCreateItem(item, options, id) {
await this.changeItemEffects(item)
await super.onCreateItem(item, options, id) await super.onCreateItem(item, options, id)
} }
async onUpdateItem(item, options, id) { async onUpdateItem(item, updates, options, id) {
switch (item.type) { await this.changeItemEffects(item);
case ITEM_TYPES.blessure: await super.onUpdateItem(item, updates, options, id)
await this.changeBleedingState()
break
}
await super.onUpdateItem(item, options, id)
} }
async changeBleedingState() { async onDeleteItem(item, options, id) {
await this.changeItemEffects(item);
await super.onDeleteItem(item, options, id)
}
async changeItemEffects(item) {
switch (item.type) {
case ITEM_TYPES.blessure:
await this.changeStateBleeding();
break;
case ITEM_TYPES.maladie:
case ITEM_TYPES.poison:
await this.changeStateMalade();
break;
}
}
async changeStateBleeding() {
const bleeding = this.itemTypes[ITEM_TYPES.blessure].find(it => it.isBleeding()) const bleeding = this.itemTypes[ITEM_TYPES.blessure].find(it => it.isBleeding())
await this.setEffect(STATUSES.StatusBleeding, bleeding ? true : false) await this.setEffect(STATUSES.StatusBleeding, bleeding ? true : false)
} }
async changeStateMalade() {
const maladiePoisons = this.getMaladiesPoisons()
await this.setEffect(STATUSES.StatusMalade, maladiePoisons.length > 0)
}
getMaladiesPoisons() {
return this.items.filter(it => [ITEM_TYPES.maladie, ITEM_TYPES.poison].includes(it.type))
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async ajouterBlessure(encaissement, attackerToken = undefined) { async ajouterBlessure(encaissement, attackerToken = undefined) {
if (encaissement.gravite < 0) return; if (encaissement.gravite < 0) return;

View File

@@ -11,6 +11,8 @@ import { RdDUtility } from "../rdd-utility.js";
import { SystemCompendiums } from "../settings/system-compendiums.js"; import { SystemCompendiums } from "../settings/system-compendiums.js";
import { RdDItem } from "../item.js"; import { RdDItem } from "../item.js";
import { StatusEffects, STATUSES } from "../settings/status-effects.js"; import { StatusEffects, STATUSES } from "../settings/status-effects.js";
import { Apprecier } from "../moral/apprecier.mjs";
import { CARACS } from "../rdd-carac.js";
export class RdDBaseActor extends Actor { export class RdDBaseActor extends Actor {
@@ -22,7 +24,7 @@ export class RdDBaseActor extends Actor {
} }
static $findCaracByName(carac, name) { static $findCaracByName(carac, name) {
const caracList = Object.entries(carac); const caracList = Object.entries(carac)
let entry = Misc.findFirstLike(name, caracList, { mapper: it => it[0], description: 'caractéristique', onMessage: m => { } }); let entry = Misc.findFirstLike(name, caracList, { mapper: it => it[0], description: 'caractéristique', onMessage: m => { } });
if (!entry || entry.length == 0) { if (!entry || entry.length == 0) {
entry = Misc.findFirstLike(name, caracList, { mapper: it => it[1].label, description: 'caractéristique' }); entry = Misc.findFirstLike(name, caracList, { mapper: it => it[1].label, description: 'caractéristique' });
@@ -49,7 +51,7 @@ export class RdDBaseActor extends Actor {
Handlebars.registerHelper('actor-isFeminin', actor => actor.isFeminin()) Handlebars.registerHelper('actor-isFeminin', actor => actor.isFeminin())
Hooks.on("preUpdateItem", (item, change, options, id) => Misc.documentIfResponsible(item.parent)?.onPreUpdateItem(item, change, options, id)) Hooks.on("preUpdateItem", (item, change, options, id) => Misc.documentIfResponsible(item.parent)?.onPreUpdateItem(item, change, options, id))
Hooks.on("createItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onCreateItem(item, options, id)) Hooks.on("createItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onCreateItem(item, options, id))
Hooks.on("updateItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onUpdateItem(item, options, id)) Hooks.on("updateItem", (item, updates, options, id) => Misc.documentIfResponsible(item.parent)?.onUpdateItem(item, updates, options, id))
Hooks.on("deleteItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onDeleteItem(item, options, id)) Hooks.on("deleteItem", (item, options, id) => Misc.documentIfResponsible(item.parent)?.onDeleteItem(item, options, id))
Hooks.on("updateActor", (actor, change, options, actorId) => Misc.documentIfResponsible(actor)?.onUpdateActor(change, options, actorId)) Hooks.on("updateActor", (actor, change, options, actorId) => Misc.documentIfResponsible(actor)?.onUpdateActor(change, options, actorId))
} }
@@ -61,25 +63,29 @@ export class RdDBaseActor extends Actor {
} }
} }
static remoteActorCall(callData) { static remoteActorCall(callData, userId = undefined) {
if (game.user.isGM) { if (game.user.isGM) {
RdDBaseActor.onRemoteActorCall(callData, game.user.id) RdDBaseActor.onRemoteActorCall(callData, game.user.id)
return false return false
} }
else { else {
game.socket.emit(SYSTEM_SOCKET_ID, { const gmUserId = Misc.firstConnectedGMId()
msg: "msg_remote_actor_call", if (gmUserId) {
data: callData, game.socket.emit(SYSTEM_SOCKET_ID, {
userId: Misc.firstConnectedGMId() msg: "msg_remote_actor_call",
}) data: callData,
return true userId: gmUserId
})
return true
}
return false
} }
} }
static onRemoteActorCall(callData, userId) { static onRemoteActorCall(callData, userId) {
const actor = RdDBaseActor.getRealActor(callData?.actorId, callData?.tokenId);
if (userId == game.user.id) { if (userId == game.user.id) {
// Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon // Seul le joueur choisi effectue l'appel: le joueur courant si propriétaire de l'actor, ou le MJ sinon
const actor = RdDBaseActor.getRealActor(callData?.actorId, callData?.tokenId);
const args = callData.args; const args = callData.args;
console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')'); console.info(`RdDBaseActor.onRemoteActorCall: pour l'Actor ${callData.actorId}, appel de RdDBaseActor.${callData.method}(`, ...args, ')');
actor[callData.method](...args); actor[callData.method](...args);
@@ -150,30 +156,47 @@ export class RdDBaseActor extends Actor {
super(docData, context); super(docData, context);
} }
getCarac() {
return foundry.utils.duplicate(this.system.carac)
}
findCaracByName(name) { findCaracByName(name) {
name = Grammar.toLowerCaseNoAccent(name) name = Grammar.toLowerCaseNoAccent(name)
switch (name) { switch (name) {
case 'reve-actuel': case 'reve actuel': case 'reve actuel':
return this.system.carac.reve name = CARACS.REVE_ACTUEL
case 'chance-actuelle': case 'chance actuelle': break
return this.system.carac.chance case 'chance actuelle':
case 'vie': name = CARACS.CHANCE_ACTUELLE
return this.system.sante.vie break
} }
const carac = this.getCarac()
const carac = this.system.carac;
return RdDBaseActor.$findCaracByName(carac, name); return RdDBaseActor.$findCaracByName(carac, name);
} }
getCaracCompetenceCreature() {
return this.isCreatureOuEntite()
? Object.fromEntries(this.itemTypes[ITEM_TYPES.competencecreature].map(it => [Grammar.toLowerCaseNoAccent(it.name), { label: it.name, value: it.system.carac_value }]))
: {}
}
mapCarac(caracCode) { return caracCode } mapCarac(caracCode) { return caracCode }
getCaracByName(name) { getCaracByName(name) {
name = this.mapCarac(Grammar.toLowerCaseNoAccent(name)) name = this.mapCarac(Grammar.toLowerCaseNoAccent(name)) ?? name
switch (name) { switch (name) {
case 'reve-actuel': case 'reve actuel': case 'reve actuel':
return this.getCaracReveActuel(); name = CARACS.REVE_ACTUEL
case 'chance-actuelle': case 'chance-actuelle': break
return this.getCaracChanceActuelle(); case 'chanceactuelle':
name = CARACS.CHANCE_ACTUELLE
break
}
switch (name) {
case CARACS.REVE_ACTUEL:
return this.getCaracReveActuel()[CARACS.REVE_ACTUEL]
case CARACS.CHANCE_ACTUELLE:
return this.getCaracChanceActuelle()[CARACS.CHANCE_ACTUELLE]
} }
return this.findCaracByName(name); return this.findCaracByName(name);
} }
@@ -220,6 +243,7 @@ export class RdDBaseActor extends Actor {
isEntite() { return false } isEntite() { return false }
isEntiteIncarnee() { return false } isEntiteIncarnee() { return false }
isEntiteNonIncarnee() { return false } isEntiteNonIncarnee() { return false }
isEntiteBlurette() { return false }
isHautRevant() { return false } isHautRevant() { return false }
isVehicule() { return false } isVehicule() { return false }
isPersonnage() { return false } isPersonnage() { return false }
@@ -279,11 +303,24 @@ export class RdDBaseActor extends Actor {
async removeEffects(filter = e => true) { async removeEffects(filter = e => true) {
if (game.user.isGM) { if (game.user.isGM) {
const effectsToRemove = this.getEffects(filter); const ids = this.getEffects(filter)
const ids = effectsToRemove.map(it => it.id); .filter(it => this.canRemoveEffects(it))
await this.deleteEmbeddedDocuments('ActiveEffect', ids); .map(it => it.id)
if (ids.length > 0) {
await this.deleteEmbeddedDocuments('ActiveEffect', ids)
}
} }
} }
canRemoveEffects(effect) {
if (effect.statuses.has(STATUSES.StatusSurEnc)) {
return !this.isSurenc()
}
if (effect.statuses.has(STATUSES.StatusDemiReve)) {
return !this.tmrApp
}
return true
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async updateCarac(caracName, to) { async updateCarac(caracName, to) {
@@ -303,7 +340,9 @@ export class RdDBaseActor extends Actor {
async onCreateItem(item, options, id) { async onCreateItem(item, options, id) {
} }
async onUpdateItem(item, options, id) { async onUpdateItem(item, updates, options, id) {
const conteneur = item.findConteneur()
conteneur?.render(options.render)
} }
async onDeleteItem(item, options, id) { async onDeleteItem(item, options, id) {
@@ -312,9 +351,8 @@ export class RdDBaseActor extends Actor {
} }
} }
async _removeItemFromConteneur(item) { async _removeItemFromConteneur(item) {
const updates = this.items.filter(it => it.isConteneur() && it.system.contenu.includes(item.id)) const updates = this.findConteneur(item)
.map(conteneur => { .map(conteneur => {
const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id) const nouveauContenu = conteneur.system.contenu.filter(id => id != item.id)
return { _id: conteneur.id, 'system.contenu': nouveauContenu } return { _id: conteneur.id, 'system.contenu': nouveauContenu }
@@ -344,7 +382,7 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async cleanupConteneurs() { async cleanupConteneurs() {
if (Misc.isOwnerPlayer(this)) { if (Misc.isOwnerPlayer(this)) {
let updates = this.itemTypes['conteneur'] let updates = this.itemTypes[ITEM_TYPES.conteneur]
.filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0) .filter(c => c.system.contenu.filter(id => this.getItem(id) == undefined).length > 0)
.map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } }); .map(c => { return { _id: c._id, 'system.contenu': c.system.contenu.filter(id => this.getItem(id) != undefined) } });
if (updates.length > 0) { if (updates.length > 0) {
@@ -355,7 +393,7 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
getFortune() { getFortune() {
return Monnaie.getFortune(this.itemTypes['monnaie']); return Monnaie.getFortune(this.itemTypes[ITEM_TYPES.monnaie]);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -398,6 +436,14 @@ export class RdDBaseActor extends Actor {
} }
async depenserSols(sols) { async depenserSols(sols) {
if (!this.isOwner) {
return RdDBaseActor.remoteActorCall({
userId: Misc.connectedGMOrUser(),
tokenId: this.token?.id,
actorId: this.id,
method: 'depenserSols', args: [sols]
})
}
let reste = this.getFortune() - Number(sols); let reste = this.getFortune() - Number(sols);
if (reste >= 0) { if (reste >= 0) {
await Monnaie.optimiserFortune(this, reste); await Monnaie.optimiserFortune(this, reste);
@@ -406,32 +452,31 @@ export class RdDBaseActor extends Actor {
} }
async ajouterSols(sols, fromActorId = undefined) { async ajouterSols(sols, fromActorId = undefined) {
sols = Number(sols); sols = Number(sols)
if (sols == 0) { if (sols == 0) {
return; return
} }
if (sols < 0) { if (sols < 0) {
ui.notifications.error(`Impossible d'ajouter un gain de ${sols} <0`); ui.notifications.error(`Impossible d'ajouter un gain de ${sols} <0`)
return; return
} }
if (fromActorId && !this.isOwner) { if (fromActorId && !this.isOwner) {
RdDBaseActor.remoteActorCall({ return RdDBaseActor.remoteActorCall({
userId: Misc.connectedGMOrUser(), userId: Misc.connectedGMOrUser(),
tokenId: this.token?.id, tokenId: this.token?.id,
actorId: this.id, actorId: this.id,
method: 'ajouterSols', args: [sols, fromActorId] method: 'ajouterSols', args: [sols, fromActorId]
}); })
} }
else {
const fromActor = game.actors.get(fromActorId)
await Monnaie.optimiserFortune(this, sols + this.getFortune());
RdDAudio.PlayContextAudio("argent"); // Petit son const fromActor = game.actors.get(fromActorId)
ChatMessage.create({ await Monnaie.optimiserFortune(this, sols + this.getFortune());
whisper: ChatUtility.getOwners(this),
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.` RdDAudio.PlayContextAudio("argent"); // Petit son
}); ChatMessage.create({
} whisper: ChatUtility.getOwners(this),
content: `Vous avez reçu <strong>${sols} Sols</strong> ${fromActor ? " de " + fromActor.name : ''}, qui ont été ajoutés à votre argent.`
})
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -443,24 +488,28 @@ export class RdDBaseActor extends Actor {
/* -------------------------------------------- */ /* -------------------------------------------- */
async achatVente(achat) { async achatVente(achat) {
if (achat.vendeurId == achat.acheteurId) { if (achat.vendeurId == achat.acheteurId) {
ui.notifications.info("Inutile de se vendre à soi-même"); ui.notifications.info("Inutile de se vendre à soi-même")
return; return
} }
if (!Misc.isFirstConnectedGM()) { const cout = Number(achat.prixTotal ?? 0)
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined
if (acheteur && !acheteur.isOwner) {
ui.notifications.warn(`${game.user.id} n'est pas propriétaire de ${this.name} et effectue un achat pour lui!`)
RdDBaseActor.remoteActorCall({ RdDBaseActor.remoteActorCall({
actorId: achat.vendeurId ?? achat.acheteurId, actorId: achat.acheteurId,
method: 'achatVente', args: [achat] method: 'achatVente', args: [achat]
}); });
return return
} }
const cout = Number(achat.prixTotal ?? 0);
const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined;
const acheteur = achat.acheteurId ? game.actors.get(achat.acheteurId) : undefined; const vendeur = achat.vendeurId ? game.actors.get(achat.vendeurId) : undefined
const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot); const quantite = (achat.choix.nombreLots ?? 1) * (achat.vente.tailleLot);
const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id); const itemVendu = vendeur?.getItem(achat.vente.item._id) ?? game.items.get(achat.vente.item._id);
if (!itemVendu) { if (!itemVendu) {
ChatUtility.notifyUser(achat.userId, 'warn', vendeur ? `Le vendeur n'a pas plus de ${achat.vente.item.name} !` : `Impossible de retrouver: ${achat.vente.item.name} !`); ChatUtility.notifyUser(achat.userId, 'warn', vendeur ? `Le vendeur n'a pas plus de ${achat.vente.item.name} !` : `Impossible de retrouver: ${achat.vente.item.name} !`);
return; return
} }
if (vendeur && !vendeur.verifierQuantite(itemVendu, quantite)) { if (vendeur && !vendeur.verifierQuantite(itemVendu, quantite)) {
ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`); ChatUtility.notifyUser(achat.userId, 'warn', `Le vendeur n'a pas assez de ${itemVendu.name} !`);
@@ -468,10 +517,10 @@ export class RdDBaseActor extends Actor {
} }
if (acheteur && !acheteur.verifierFortune(cout)) { if (acheteur && !acheteur.verifierFortune(cout)) {
ChatUtility.notifyUser(achat.userId, 'warn', `Vous n'avez pas assez d'argent pour payer ${Math.ceil(cout / 100)} sols !`); ChatUtility.notifyUser(achat.userId, 'warn', `Vous n'avez pas assez d'argent pour payer ${Math.ceil(cout / 100)} sols !`);
return; return
} }
await vendeur?.vendre(itemVendu, quantite, cout); await vendeur?.vendre(itemVendu, quantite, cout, acheteur);
await acheteur?.acheter(itemVendu, quantite, cout, achat) await acheteur?.acheter(itemVendu, quantite, cout, achat, vendeur)
if (cout > 0) { if (cout > 0) {
RdDAudio.PlayContextAudio("argent"); RdDAudio.PlayContextAudio("argent");
@@ -486,27 +535,40 @@ export class RdDBaseActor extends Actor {
}); });
if (!achat.vente.quantiteIllimite) { if (!achat.vente.quantiteIllimite) {
if (achat.vente.nbLots <= achat.choix.nombreLots) { await this.updateMessageVente(achat.chatMessageIdVente, achat.choix.nombreLots);
ChatUtility.removeChatMessageId(achat.chatMessageIdVente);
}
else if (achat.chatMessageIdVente) {
await ChatVente.diminuerQuantiteAchatVente(achat.chatMessageIdVente, achat.choix.nombreLots)
}
} }
} }
async vendre(item, quantite, cout) { async updateMessageVente(chatMessageIdVente, nombreLots) {
await this.ajouterSols(cout); const chatMessage = game.messages.get(chatMessageIdVente)
await this.decrementerQuantiteItem(item, quantite); if (!chatMessage.isOwner) {
return RdDBaseActor.remoteActorCall({
userId: Misc.firstConnectedGMId(),
actorId: this.id,
method: 'updateMessageVente', args: [chatMessageIdVente, nombreLots]
})
}
await ChatVente.diminuerQuantiteAchatVente(chatMessageIdVente, nombreLots);
}
async vendre(item, quantite, cout, acheteur) {
await this.ajouterSols(cout, acheteur?.id)
await this.decrementerQuantiteItem(item.id, quantite)
} }
async acheter(item, quantite, cout, achat) { async acheter(item, quantite, cout, achat) {
await this.depenserSols(cout) await this.depenserSols(cout)
if (!this.isOwner) {
ui.notifications.warn(`${game.user.id} n'est pas propriétaire de ${this.name} et effectue un achat!`)
}
const createdItemId = await this.creerQuantiteItem(item, quantite) const createdItemId = await this.creerQuantiteItem(item, quantite)
if (achat.choix.consommer && item.type == 'nourritureboisson' && createdItemId != undefined) { if (item.type == ITEM_TYPES.nourritureboisson && achat.choix.consommer && createdItemId != undefined) {
achat.choix.doses = achat.choix.nombreLots; achat.choix.doses = achat.choix.nombreLots;
await this.consommerNourritureboisson(createdItemId, achat.choix, achat.vente.actingUserId); await this.consommerNourritureboisson(createdItemId, achat.choix, achat.vente.actingUserId);
} }
if (item.type == ITEM_TYPES.service) {
new Apprecier(this, item.system.appreciation, item.system.qualite).apprecier()
}
} }
verifierFortune(cout) { verifierFortune(cout) {
@@ -520,43 +582,46 @@ export class RdDBaseActor extends Actor {
async consommerNourritureboisson(itemId, choix, userId) { } async consommerNourritureboisson(itemId, choix, userId) { }
async decrementerQuantiteItem(item, quantite, options = { supprimerSiZero: true }) { async decrementerQuantiteItem(itemId, quantite, options = { supprimerSiZero: true }) {
const item = this.items.get(itemId)
if (item.isService()) { if (item.isService()) {
return; return
} }
const itemId = item.id;
let resteQuantite = (item.system.quantite ?? 1) - quantite; if (!this.isOwner) {
if (resteQuantite <= 0) { return RdDBaseActor.remoteActorCall({
if (options.supprimerSiZero) { userId: Misc.connectedGMOrUser(),
await this.deleteEmbeddedDocuments("Item", [item.id]); tokenId: this.token?.id,
} actorId: this.id,
else { method: 'decrementerQuantiteItem', args: [itemId, quantite, options]
await this.updateEmbeddedDocuments("Item", [{ _id: itemId, 'system.quantite': 0 }]); })
}
if (resteQuantite < 0) {
ui.notifications.warn(`La quantité de ${item.name} était insuffisante, l'objet a donc été supprimé`)
}
} }
else if (resteQuantite > 0) {
const realItem = this.getItem(item.id) const resteQuantite = Math.max((item.system.quantite ?? 1) - quantite, 0)
realItem.update({ 'system.quantite': resteQuantite }); if (resteQuantite <= 0 && options.supprimerSiZero) {
await this.updateEmbeddedDocuments("Item", [{ _id: item.id, 'system.quantite': resteQuantite }]); await this.deleteEmbeddedDocuments("Item", [itemId]);
}
else {
await this.updateEmbeddedDocuments("Item", [{ _id: itemId, 'system.quantite': resteQuantite }])
} }
} }
async creerQuantiteItem(item, quantite) { async creerQuantiteItem(item, quantite) {
if (this.canReceive(item)) { if (!this.canReceive(item)) {
const isItemEmpilable = "quantite" in item.system; return
const baseItem = {
type: item.type,
img: item.img,
name: item.name,
system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }, { inplace: false })
};
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
const items = await this.createEmbeddedDocuments("Item", newItems);
return items.length > 0 ? items[0].id : undefined;
} }
const isItemEmpilable = "quantite" in item.system;
const baseItem = {
type: item.type,
img: item.img,
name: item.name,
system: foundry.utils.mergeObject(item.system, { quantite: isItemEmpilable ? quantite : undefined }, { inplace: false })
}
const newItems = isItemEmpilable ? [baseItem] : Array.from({ length: quantite }, (_, i) => baseItem);
const items = await this.createEmbeddedDocuments("Item", newItems);
return newItems.length > 0 ? items[0].id : undefined;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -576,7 +641,7 @@ export class RdDBaseActor extends Actor {
} }
getEncTotal() { getEncTotal() {
return Math.floor(this.encTotal ?? 0) return Number(this.encTotal?.toFixed(2) ?? 0.00)
} }
async createItem(type, name = undefined) { async createItem(type, name = undefined) {
@@ -609,7 +674,7 @@ export class RdDBaseActor extends Actor {
if (srcId != destId && itemId != destId) { // déplacement de l'objet if (srcId != destId && itemId != destId) { // déplacement de l'objet
const src = this.getItem(srcId); const src = this.getItem(srcId);
const dest = this.getItem(destId); const dest = this.getItem(destId);
const cible = this.getContenantOrParent(dest); const cible = this.findConteneurOrParent(dest);
const [empilable, message] = item.isInventaireEmpilable(dest); const [empilable, message] = item.isInventaireEmpilable(dest);
if (empilable) { if (empilable) {
await dest.empiler(item) await dest.empiler(item)
@@ -631,15 +696,15 @@ export class RdDBaseActor extends Actor {
return result; return result;
} }
getContenantOrParent(dest) { findConteneurOrParent(dest) {
if (!dest || dest.isConteneur()) { if (!dest || dest.isConteneur()) {
return dest; return dest;
} }
return this.getContenant(dest); return this.findConteneur(dest)
} }
getContenant(item) { findConteneur(item) {
return this.itemTypes['conteneur'].find(it => it.system.contenu.includes(item.id)); return this.itemTypes[ITEM_TYPES.conteneur].find(it => it.system.contenu.includes(item.id));
} }
@@ -835,6 +900,7 @@ export class RdDBaseActor extends Actor {
listActionsPossessions() { listActionsPossessions() {
return this.itemTypes[ITEM_TYPES.possession] return this.itemTypes[ITEM_TYPES.possession]
.filter(it => !it.system.possede)
.map(p => { .map(p => {
return { return {
label: p.name, label: p.name,
@@ -843,9 +909,5 @@ export class RdDBaseActor extends Actor {
} }
}) })
} }
listActionsCombat() {
const possessions = this.listActionsPossessions()
return possessions.length > 0 ? possessions : this.listActions({})
}
} }

View File

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

View File

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

View File

@@ -0,0 +1,288 @@
import { ACTOR_TYPES, ITEM_TYPES } from "../../constants.js"
import { Grammar } from "../../grammar.js"
import { RdDItemArme } from "../../item/arme.js"
import { CATEGORIES_COMPETENCE_COMBAT } from "../../item/base-items.js"
import { Misc } from "../../misc.js"
import { RdDTimestamp } from "../../time/rdd-timestamp.js"
import { PDFDocument } from "./pdf-lib/pdf-lib.esm.js"
const copyProperty = (actor, path) => foundry.utils.getProperty(actor, path)
// const findItem = (actor, itemType, itemName) => actor.itemTypes[itemType].find(it => Grammar.equalsInsensitive(formCompName(it.name), formCompName(itemName)))
// const findItemPos = (actor, itemType, pos) => actor.itemTypes[itemType].length <= pos ? actor.itemTypes[itemType][pos] : length
// const findProperty = (it, path) => it ? foundry.utils.getProperty(it, path) : undefined
// const findItemProperty = (actor, itemType, itemName, path) => findProperty(findItem(actor, itemType, itemName), path)
// const findItemPosProperty = (actor, itemType, pos, path) => findProperty(findItemPos(actor, itemType, pos), path)
// const findArmeProperty = (actor, pos, path) => findProperty(findItemPos(actor, ITEM_TYPES.arme, pos), path)
// const findSortProperty = (actor, pos, path) => findProperty(findItemPos(actor, ITEM_TYPES.sort, pos), path)
// const itemFormPath = (type, pos, property) => `${type}s.${pos}.${property}`
const ACTOR_TO_FORM_MAPPING = [
{ path: 'name' },
{ path: 'system.carac.taille.value' },
{ path: 'system.carac.apparence.value' },
{ path: 'system.carac.apparence.xp' },
{ path: 'system.carac.constitution.value' },
{ path: 'system.carac.constitution.xp' },
{ path: 'system.carac.force.value' },
{ path: 'system.carac.force.value' },
{ path: 'system.carac.force.xp' },
{ path: 'system.carac.agilite.value' },
{ path: 'system.carac.agilite.xp' },
{ path: 'system.carac.dexterite.value' },
{ path: 'system.carac.dexterite.xp' },
{ path: 'system.carac.vue.value' },
{ path: 'system.carac.vue.xp' },
{ path: 'system.carac.ouie.value' },
{ path: 'system.carac.ouie.xp' },
{ path: 'system.carac.odoratgout.value' },
{ path: 'system.carac.odoratgout.xp' },
{ path: 'system.carac.volonte.value' },
{ path: 'system.carac.volonte.xp' },
{ path: 'system.carac.empathie.value' },
{ path: 'system.carac.empathie.xp' },
{ path: 'system.carac.intellect.value' },
{ path: 'system.carac.intellect.xp' },
{ path: 'system.carac.reve.value' },
{ path: 'system.carac.reve.xp' },
{ path: 'system.carac.chance.value' },
{ path: 'system.carac.chance.xp' },
{ path: 'system.age' },
{ path: 'system.sexe' },
{ path: 'system.taille' },
{ path: 'system.poids' },
{ path: 'system.cheveux' },
{ path: 'system.yeux' },
{ path: 'system.beaute' },
{ path: 'system.main' },
{ path: 'system.heure' },
{ path: 'computed.hn.heure', getter: actor => (RdDTimestamp.definition(actor.system.heure)?.heure ?? 0) + 1 },
{ path: 'computed.hn.label', getter: actor => RdDTimestamp.definition(actor.system.heure)?.avecArticle },
{ path: 'system.carac.melee.value' },
{ path: 'system.carac.tir.value' },
{ path: 'system.carac.lancer.value' },
{ path: 'system.carac.derobee.value' },
{ path: 'system.sante.vie.value' },
{ path: 'system.sante.endurance.value' },
{ path: 'system.attributs.sust.value' },
{ path: 'system.attributs.sconst.value' },
{ path: 'system.attributs.encombrement.value' },
{ path: 'system.attributs.plusdom.value', getter: actor => Misc.toSignedString(actor.system.attributs.plusdom.value) },
// , getter: actor => actor.get
]
export default class ExportPdf {
static init() {
Hooks.on("getActorContextOptions", (actorDirectory, menus) => { ExportPdf.onActorDirectoryMenu(actorDirectory, menus) })
}
static onActorDirectoryMenu(actorDirectory, menus) {
menus.push({
name: 'Export PDF',
icon: '<i class="fa-regular fa-file-pdf"></i>',
condition: target => actorDirectory.id == 'actors' && ExportPdf.$isActorPersonnage(this.$getActor(target)),
callback: async target => await ExportPdf.exportActor(target)
})
}
static $getActor(target) {
const entryId = $(target).closest(".directory-item")?.data("entryId")
return game.actors.get(entryId)
}
static $isActorPersonnage(actor) {
return actor?.type == ACTOR_TYPES.personnage
}
static async exportActor(target) {
const actor = ExportPdf.$getActor(target)
if (!ExportPdf.$isActorPersonnage(actor)) {
ui.notifications.error("Pas de personnage sélectionné")
return
}
const templatePdf = '/systems/foundryvtt-reve-de-dragon/assets/feuille-personnage.pdf';
const pdfBytes = await fetch(templatePdf).then(res => res.arrayBuffer())
const pdfDoc = await PDFDocument.load(pdfBytes)
const exporter = new ExportPdf(actor, pdfDoc)
exporter.generateFeuillePersonnage()
}
constructor(actor, pdfDoc) {
this.pdfDoc = pdfDoc
this.form = this.pdfDoc.getForm()
this.actor = actor
this.allComps = this.actor.itemTypes[ITEM_TYPES.competence]
this.comps = this.allComps
.filter(it => !it.isNiveauBase())
.sort(Misc.ascending(it => it.name))
this.compsNonArmes = this.comps.filter(it => !ExportPdf.isCompCombat(it))
this.compsArmes = this.comps.filter(it => ExportPdf.isCompCombat(it))
this.addedComps = new Set([])
}
static isCompCombat(comp) {
return CATEGORIES_COMPETENCE_COMBAT.includes(comp.system.categorie) && !Grammar.includesLowerCaseNoAccent(comp.name, "corps à corps") && !Grammar.includesLowerCaseNoAccent(comp.name, "esquive")
}
async generateFeuillePersonnage() {
this.$exportActorFields()
this.$exportCompetences()
this.$exportArchetype()
this.$exportArmes()
this.$exportSorts()
const pdfBytes = await this.pdfDoc.save();
const filename = `rdd-${this.actor.name.slugify()}.pdf`;
foundry.utils.saveDataToFile(pdfBytes, "application/pdf", filename);
}
$exportActorFields() {
ACTOR_TO_FORM_MAPPING.forEach(async (mapping) => {
const path = mapping.path
const value = mapping.getter ? mapping.getter(this.actor) : copyProperty(this.actor, path)
this.$setFormValue(path, value)
})
}
$exportCompetences() {
this.compsNonArmes
.filter(it => !this.addedComps.has(it.id))
.forEach(comp => {
const formCompName = Grammar.toLowerCaseNoAccent(comp.name.replaceAll(/(\s|-|\')/g, '_'))
this.$setFormCompetence(formCompName, comp)
})
const musique = this.compsNonArmes.filter(it => Grammar.includesLowerCaseNoAccent(it.name, 'musique'))
.sort(Misc.descending(it => it.system.niveau))
.filter(it => !this.addedComps.has(it.id))
.find(it => true)
if (musique) {
this.$setFormCompetence('musique', musique)
}
}
$exportArchetype() {
this.allComps.sort(Misc.ascending(it => it.system.niveau_archetype))
.forEach(comp => {
let formCompName = Grammar.toLowerCaseNoAccent(comp.name.replaceAll(/(\s|-|\')/g, '_'))
if (formCompName.includes('musique')) {
formCompName = 'musique'
}
this.$setFormValue(`competences.${formCompName}.niveau_archetype`, comp.system.niveau_archetype)
})
}
$setFormCompetenceArchetype(formCompName, comp, baseFormName = 'competences') {
}
$exportArmes() {
const uniques = new Set([])
const armes = this.actor.itemTypes[ITEM_TYPES.arme].map(arme => arme.getTypeAttaques()
.map(main => {
const compName = arme.getCompetenceAction(main)
const dommages = RdDItemArme.valeurMain(arme.system.dommages, main)
const forceRequise = RdDItemArme.valeurMain(arme.system.force ?? 0, main)
const comp = this.compsArmes.find(it => Grammar.equalsInsensitive(it.name, compName)) ?? this.actor.findItemLike(compName, ITEM_TYPES.competence)
const unique = [comp.id, arme.name, dommages, forceRequise].join('|');
if (uniques.has(unique)) {
return undefined
}
uniques.add(unique)
return { arme: arme, comp: comp, main: main }
}))
.reduce((a, b) => a.concat(b))
.filter(it => it != undefined && !it.comp.isNiveauBase())
.sort(Misc.descending(it => it.comp.niveau))
for (let pos = 0; pos < armes.length; pos++) {
const it = armes[pos]
this.$setFormArmeCompetence(pos, it.comp, it.arme, it.main, it.main)
}
// TODO: list comps without weapons
// TODO: list other comps not in the standard list -- use an instance of ExportPdf to hold state/built list
const otherComps = this.comps.filter(it => !this.addedComps.has(it.id))
for (let pos = 0; pos < otherComps.length; pos++) {
const comp = otherComps[pos]
this.$setFormCompetence(pos, comp, 'competences')
this.$setFormValue(`competences.${pos}.name`, comp.name)
}
}
$setFormCompetence(formCompName, comp, baseFormName = 'competences') {
if (this.form.getFieldMaybe(`${baseFormName}.${formCompName}.niveau`)) {
this.addedComps.add(comp.id)
}
if (comp.system.niveau != comp.system.base) {
this.$setFormValue(`${baseFormName}.${formCompName}.niveau`, comp.system.niveau)
}
if (comp.system.xp > 0) {
this.$setFormValue(`${baseFormName}.${formCompName}.xp`, comp.system.xp)
}
if (comp.system.xp_sort > 0) {
this.$setFormValue(`${baseFormName}.${formCompName}.xp_sort`, comp.system.xp_sort)
}
if (CATEGORIES_COMPETENCE_COMBAT.includes(comp.system.categorie)) {
this.$setFormValue(`${baseFormName}.${formCompName}.init`, comp.getBaseInit())
}
}
$setFormArmeCompetence(pos, comp, arme, main) {
this.$setFormCompetence(pos, comp, 'armes')
this.$setFormValue(`armes.${pos}.name`, arme.name)
this.$setFormValue(`armes.${pos}.main`, main)
this.$setFormValue(`armes.${pos}.plusdom`, RdDItemArme.valeurMain(arme.system.dommages, main))
}
$exportSorts() {
const sorts = this.actor.itemTypes[ITEM_TYPES.sort].sort(Misc.ascending(s => ExportPdf.$orderDraconic(s) + s.name))
for (let pos = 0; pos < sorts.length; pos++) {
const sort = sorts[pos]
this.$setFormSort(pos, sort)
}
}
$setFormSort(pos, sort) {
this.$setFormValue(`sorts.${pos}.name`, sort.name)
this.$setFormValue(`sorts.${pos}.voie`, sort.system.draconic)
this.$setFormValue(`sorts.${pos}.tmr`, sort.system.caseTMRSpeciale ?? sort.system.caseTMR)
this.$setFormValue(`sorts.${pos}.diff`, sort.system.difficulte)
this.$setFormValue(`sorts.${pos}.reve`, sort.system.ptreve)
this.$setFormValue(`sorts.${pos}.bonuscase`, sort.system.bonuscase)
}
static $orderDraconic(s) {
switch (s.system.draconic.substring(0, 1)) {
case 'O': return 1
case 'H': return 2
case 'N': return 3
case 'T': return 4
}
return 5
}
$setFormValue(path, value) {
const hasField = this.form.getFieldMaybe(path)
if (hasField && value != undefined) {
const field = this.form.getTextField(path)
field.setText(value.toString())
}
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -5,7 +5,7 @@ import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
/** /**
* Class providing helper methods to get the list of users, and * Class providing helper methods around the Chat message
*/ */
export class ChatUtility { export class ChatUtility {
@@ -76,6 +76,15 @@ export class ChatUtility {
ChatUtility.removeMessages({ part: part }); ChatUtility.removeMessages({ part: part });
} }
static remover(chatMessage) {
const messageId = chatMessage.id;
if (messageId) {
return (..._) => ChatUtility.removeMessages({ messageId: messageId });
}
return (..._) => { }
}
static removeChatMessageId(messageId) { static removeChatMessageId(messageId) {
if (messageId) { if (messageId) {
ChatUtility.removeMessages({ messageId: messageId }); ChatUtility.removeMessages({ messageId: messageId });
@@ -206,11 +215,13 @@ export class ChatUtility {
static async onRenderChatMessage(chatMessage, html, data) { static async onRenderChatMessage(chatMessage, html, data) {
const rddTimestamp = chatMessage.getFlag(SYSTEM_RDD, 'rdd-timestamp') const rddTimestamp = chatMessage.getFlag(SYSTEM_RDD, 'rdd-timestamp')
if (rddTimestamp) { const heureRdD = $(html).find('header.message-header .heure-rdd')
if (rddTimestamp && heureRdD.length==0) {
const messageTimestamp = $(html).find('header.message-header .message-timestamp');
const timestamp = new RdDTimestamp(rddTimestamp); const timestamp = new RdDTimestamp(rddTimestamp);
const timestampData = timestamp.toCalendrier(); const timestampData = timestamp.toCalendrier();
const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData); const dateHeure = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/common/date-heure.hbs', timestampData);
$(html).find('header.message-header .message-timestamp').after(dateHeure) messageTimestamp.after(dateHeure)
} }
} }
@@ -224,4 +235,9 @@ export class ChatUtility {
static async setTimestamp(chatMessage) { static async setTimestamp(chatMessage) {
await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp()); await chatMessage.setFlag(SYSTEM_RDD, 'rdd-timestamp', game.system.rdd.calendrier.getTimestamp());
} }
static getISODate(chatMessage) {
const date = new Date(chatMessage.timestamp);
return date?.toISOString().substring(0, 10)
}
} }

View File

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

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -20,11 +20,11 @@ export class RdDInitiative {
return "1d6" + (base >= 0 ? "+" : "") + base return "1d6" + (base >= 0 ? "+" : "") + base
} }
static ajustementInitiative(caracValue, niveau, bonus) { static ajustementInitiative(caracValue, niveau, bonus = 0) {
return niveau + Math.floor(caracValue / 2) + bonus return niveau + Math.floor(caracValue / 2) + bonus
} }
static formule(phase, carac, niveau, bonusMalus) { static formule(phase, carac, niveau, bonusMalus = 0) {
const ajustement = RdDInitiative.ajustementInitiative(carac, niveau, bonusMalus) const ajustement = RdDInitiative.ajustementInitiative(carac, niveau, bonusMalus)
return { phase, ajustement } return { phase, ajustement }
} }

View File

@@ -1,5 +1,6 @@
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { RdDInitiative } from "./initiative.mjs";
import { RdDItem } from "./item.js"; import { RdDItem } from "./item.js";
import { CATEGORIES_COMPETENCES, SANS_COMPETENCE } from "./item/base-items.js"; import { CATEGORIES_COMPETENCES, SANS_COMPETENCE } from "./item/base-items.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
@@ -46,6 +47,30 @@ export class RdDItemCompetence extends RdDItem {
static get defaultIcon() { return "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp" } static get defaultIcon() { return "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp" }
isNiveauBase() {
return this.system.niveau == this.system.base && this.system.xp == 0
}
getBaseInit() {
const carac = this.getInitCarac()
if (carac == undefined) {
return undefined
}
return RdDInitiative.ajustementInitiative(carac.value, this.system.niveau)
}
getInitCarac() {
if (!this.actor) {
return undefined
}
switch (this.system.categorie) {
case CATEGORIES_COMPETENCES.melee.key: return this.actor.system.carac.melee
case CATEGORIES_COMPETENCES.tir.key: return this.actor.system.carac.tir
case CATEGORIES_COMPETENCES.lancer.key: return this.actor.system.carac.lancer
case CATEGORIES_COMPETENCES.draconic.key: return this.actor.system.carac.reve
}
return undefined
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static getLabelCategorie(category) { static getLabelCategorie(category) {
return CATEGORIES_COMPETENCES[category].label; return CATEGORIES_COMPETENCES[category].label;
@@ -111,7 +136,7 @@ export class RdDItemCompetence extends RdDItem {
return troncList; return troncList;
} }
} }
return []; return []
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

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

View File

@@ -14,6 +14,9 @@ import { RdDTimestamp } from "./time/rdd-timestamp.js";
import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js"; import { FLEUVE_COORD, TMRUtility } from "./tmr-utility.js";
import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js"; import { RdDTextEditor } from "./apps/rdd-text-roll-editor.js";
import { ItemAction } from "./item/item-actions.js"; import { ItemAction } from "./item/item-actions.js";
import { SANS_COMPETENCE } from "./item/base-items.js";
import { Apprecier } from "./moral/apprecier.mjs";
import { CARACS } from "./rdd-carac.js";
/** /**
* Extend the basic ItemSheet for RdD specific items * Extend the basic ItemSheet for RdD specific items
@@ -89,6 +92,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
const competences = (await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage))
let formData = { let formData = {
title: this.item.name, title: this.item.name,
id: this.item.id, id: this.item.id,
@@ -101,8 +105,9 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
descriptionmj: await RdDTextEditor.enrichHTML(this.item.system.descriptionmj, this.item), descriptionmj: await RdDTextEditor.enrichHTML(this.item.system.descriptionmj, this.item),
isComestible: this.item.getUtilisationCuisine(), isComestible: this.item.getUtilisationCuisine(),
options: RdDSheetUtility.mergeDocumentRights({}, this.item, this.isEditable), options: RdDSheetUtility.mergeDocumentRights({}, this.item, this.isEditable),
competences: await SystemCompendiums.getCompetences(ACTOR_TYPES.personnage), competences: [new RdDItemCompetence(SANS_COMPETENCE), ...competences],
categories: RdDItem.getCategories(this.item.type), categories: RdDItem.getCategories(this.item.type),
isAppreciable: Apprecier.isAppreciable(this.item)
} }
if (this.item.type == ITEM_TYPES.competencecreature) { if (this.item.type == ITEM_TYPES.competencecreature) {
@@ -114,7 +119,7 @@ export class RdDItemSheetV1 extends foundry.appv1.sheets.ItemSheet {
this.item.type == ITEM_TYPES.meditation || this.item.type == ITEM_TYPES.meditation ||
this.item.type == ITEM_TYPES.oeuvre) { this.item.type == ITEM_TYPES.oeuvre) {
formData.caracList = foundry.utils.duplicate(game.model.Actor.personnage.carac) formData.caracList = foundry.utils.duplicate(game.model.Actor.personnage.carac)
formData.caracList["reve-actuel"] = foundry.utils.duplicate(game.model.Actor.personnage.reve.reve) formData.caracList[CARACS.REVE_ACTUEL] = foundry.utils.duplicate(game.model.Actor.personnage.reve.reve)
} }
if (this.item.type == ITEM_TYPES.arme) { if (this.item.type == ITEM_TYPES.arme) {
formData.competences = formData.competences.filter(it => it.isCompetenceArme()) formData.competences = formData.competences.filter(it => it.isCompetenceArme())

View File

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

View File

@@ -28,7 +28,7 @@ const typesInventaireMateriel = [
] ]
const typesInventaire = { const typesInventaire = {
materiel: typesInventaireMateriel, materiel: typesInventaireMateriel,
all: ['service'].concat(typesInventaireMateriel), all: [ITEM_TYPES.service].concat(typesInventaireMateriel),
} }
const typesObjetsOeuvres = [ITEM_TYPES.oeuvre, ITEM_TYPES.recettecuisine, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.jeu] const typesObjetsOeuvres = [ITEM_TYPES.oeuvre, ITEM_TYPES.recettecuisine, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.jeu]
@@ -36,6 +36,10 @@ const typesObjetsDraconiques = [ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.s
const typesObjetsConnaissance = [ITEM_TYPES.meditation, ITEM_TYPES.recettealchimique, ITEM_TYPES.sort] const typesObjetsConnaissance = [ITEM_TYPES.meditation, ITEM_TYPES.recettealchimique, ITEM_TYPES.sort]
const typesObjetsEffet = [ITEM_TYPES.possession, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.blessure] const typesObjetsEffet = [ITEM_TYPES.possession, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.blessure]
const typesObjetsCompetence = [ITEM_TYPES.competence, ITEM_TYPES.competencecreature] const typesObjetsCompetence = [ITEM_TYPES.competence, ITEM_TYPES.competencecreature]
const typesAppreciable = [
ITEM_TYPES.oeuvre, ITEM_TYPES.musique, ITEM_TYPES.chant, ITEM_TYPES.danse, ITEM_TYPES.nourritureboisson,
ITEM_TYPES.jeu, ITEM_TYPES.service
]
const typesObjetsTemporels = [ITEM_TYPES.blessure, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.signedraconique, ITEM_TYPES.rencontre] const typesObjetsTemporels = [ITEM_TYPES.blessure, ITEM_TYPES.poison, ITEM_TYPES.maladie, ITEM_TYPES.queue, ITEM_TYPES.ombre, ITEM_TYPES.souffle, ITEM_TYPES.signedraconique, ITEM_TYPES.rencontre]
const typesObjetsEquipable = [ITEM_TYPES.arme, ITEM_TYPES.armure, ITEM_TYPES.objet]; const typesObjetsEquipable = [ITEM_TYPES.arme, ITEM_TYPES.armure, ITEM_TYPES.objet];
const typesEnvironnement = typesInventaireMateriel; const typesEnvironnement = typesInventaireMateriel;
@@ -77,13 +81,13 @@ export const defaultItemImg = {
souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp", souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp",
tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp", tarot: "systems/foundryvtt-reve-de-dragon/icons/tarots/dos-tarot.webp",
tete: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp", tete: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp",
monnaie:"systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp", monnaie: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
munition: "systems/foundryvtt-reve-de-dragon/icons/objets/fleche.webp" munition: "systems/foundryvtt-reve-de-dragon/icons/objets/fleche.webp"
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDItem extends Item { export class RdDItem extends Item {
static get defaultIcon() { static get defaultIcon() {
return undefined; return undefined;
} }
@@ -96,14 +100,14 @@ export class RdDItem extends Item {
switch (field) { switch (field) {
case 'quantite': case 'quantite':
if (ITEM_TYPES.conteneur == type) { if (ITEM_TYPES.conteneur == type) {
return false; return false
} }
break; break;
case 'cout': case 'cout':
if (ITEM_TYPES.monnaie == type) { if (ITEM_TYPES.monnaie == type) {
return game.user.isGM; return game.user.isGM;
} }
break; break
} }
return true; return true;
} }
@@ -180,10 +184,17 @@ export class RdDItem extends Item {
isCompetencePersonnage() { return this.type == ITEM_TYPES.competence } isCompetencePersonnage() { return this.type == ITEM_TYPES.competence }
isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature } isCompetenceCreature() { return this.type == ITEM_TYPES.competencecreature }
isConteneur() { return this.type == ITEM_TYPES.conteneur; } isConteneur() { return this.type == ITEM_TYPES.conteneur }
isMonnaie() { return this.type == ITEM_TYPES.monnaie; } findConteneur() {
if (this.isInventaire('all') && this.parent) {
return this.parent.findConteneur(this)
}
return undefined
}
isMonnaie() { return this.type == ITEM_TYPES.monnaie }
isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; } isNourritureBoisson() { return this.type == ITEM_TYPES.nourritureboisson; }
isService() { return this.type == ITEM_TYPES.service; } isService() { return this.type == ITEM_TYPES.service }
isAttaque() { return false } isAttaque() { return false }
isParade() { return false } isParade() { return false }
isBouclier() { return false } isBouclier() { return false }
@@ -205,7 +216,7 @@ export class RdDItem extends Item {
return this.isCompetence() && ['melee', 'tir', 'lancer'].includes(this.system.categorie) return this.isCompetence() && ['melee', 'tir', 'lancer'].includes(this.system.categorie)
} }
isCompetencePossession() { return ITEM_TYPES.competencecreature == this.type && this.system.categorie == "possession" } isCompetencePossession() { return ITEM_TYPES.competencecreature == this.type && this.system.categorie == CATEGORIES_COMPETENCES_CREATURES.possession.key }
isTemporel() { return typesObjetsTemporels.includes(this.type) } isTemporel() { return typesObjetsTemporels.includes(this.type) }
isOeuvre() { return typesObjetsOeuvres.includes(this.type) } isOeuvre() { return typesObjetsOeuvres.includes(this.type) }
isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) } isDraconique() { return RdDItem.getItemTypesDraconiques().includes(this.type) }
@@ -214,6 +225,7 @@ export class RdDItem extends Item {
isConnaissance() { return typesObjetsConnaissance.includes(this.type) } isConnaissance() { return typesObjetsConnaissance.includes(this.type) }
isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); } isInventaire(mode = 'materiel') { return RdDItem.getItemTypesInventaire(mode).includes(this.type); }
isAppreciable() { return typesAppreciable.includes(this.type) }
isBoisson() { return this.isNourritureBoisson() && this.system.boisson; } isBoisson() { return this.isNourritureBoisson() && this.system.boisson; }
isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; } isAlcool() { return this.isNourritureBoisson() && this.system.boisson && this.system.alcoolise; }
isHerbeAPotion() { return this.type == ITEM_TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); } isHerbeAPotion() { return this.type == ITEM_TYPES.herbe && (this.system.categorie == 'Soin' || this.system.categorie == 'Repos'); }
@@ -364,11 +376,11 @@ export class RdDItem extends Item {
getEnc() { getEnc() {
switch (this.type) { switch (this.type) {
case ITEM_TYPES.service: case ITEM_TYPES.service:
return 0; return 0
case ITEM_TYPES.herbe: case ITEM_TYPES.herbe:
return this.getEncHerbe(); return this.getEncHerbe()
} }
return Math.max(this.system.encombrement ?? 0, 0); return Math.max(this.system.encombrement ?? 0.0, 0.0);
} }
getEncContenu() { getEncContenu() {
@@ -384,9 +396,9 @@ export class RdDItem extends Item {
getEncHerbe() { getEncHerbe() {
switch (this.system.categorie) { switch (this.system.categorie) {
case 'Repos': case 'Soin': case 'Alchimie': case 'Repos': case 'Soin': case 'Alchimie':
return encBrin; return encBrin
} }
return this.system.encombrement; return this.system.encombrement
} }

View File

@@ -45,6 +45,16 @@ export class RdDItemArme extends RdDItem {
isParade() { return this.system.resistance > 0 && this.system.categorie_parade } isParade() { return this.system.resistance > 0 && this.system.categorie_parade }
isBouclier() { return RdDItemArme.getCategorieParade(this).includes('bouclier') } isBouclier() { return RdDItemArme.getCategorieParade(this).includes('bouclier') }
getCompetenceAction(main) {
switch (main) {
case ATTAQUE_TYPE.UNE_MAIN: return this.competence1Mains()
case ATTAQUE_TYPE.DEUX_MAINS: return this.competence2Mains()
case ATTAQUE_TYPE.LANCER: return this.system.lancer
case ATTAQUE_TYPE.TIR: return this.system.tir
default: return this.system.competence
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static valeurMain(valeurs, main) { static valeurMain(valeurs, main) {
valeurs = valeurs?.toString() ?? "" valeurs = valeurs?.toString() ?? ""
@@ -78,17 +88,26 @@ export class RdDItemArme extends RdDItem {
return arme.name return arme.name
case ITEM_TYPES.arme: case ITEM_TYPES.arme:
switch (maniement) { switch (maniement) {
case ATTAQUE_TYPE.COMPETENCE: return arme.system.competence; case ATTAQUE_TYPE.COMPETENCE: return arme.system.competence
case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains() case ATTAQUE_TYPE.UNE_MAIN: return arme.competence1Mains()
case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains() case ATTAQUE_TYPE.DEUX_MAINS: return arme.competence2Mains()
case ATTAQUE_TYPE.TIR: case 'tir': return arme.system.tir case ATTAQUE_TYPE.TIR: case 'tir': return arme.system.tir
case ATTAQUE_TYPE.LANCER: case 'lancer': return arme.system.lancer; case ATTAQUE_TYPE.LANCER: case 'lancer': return arme.system.lancer
case ATTAQUE_TYPE.CORPS_A_CORPS: return CORPS_A_CORPS case ATTAQUE_TYPE.CORPS_A_CORPS: return CORPS_A_CORPS
} }
} }
return undefined return undefined
} }
getTypeAttaques() {
return [
...(this.system.unemain && this.system.competence && this.system.resistance > 0) ? [ATTAQUE_TYPE.UNE_MAIN] : [],
...(this.system.deuxmains && this.system.competence && this.system.resistance > 0) ? [ATTAQUE_TYPE.DEUX_MAINS] : [],
...(this.system.lancer && this.system.resistance > 0) ? [ATTAQUE_TYPE.LANCER] : [],
...(this.system.tir) ? [ATTAQUE_TYPE.TIR] : [],
]
}
static computeNiveauArmes(armes, competences) { static computeNiveauArmes(armes, competences) {
for (const arme of armes) { for (const arme of armes) {
arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences); arme.system.niveau = RdDItemArme.niveauCompetenceArme(arme, competences);
@@ -155,24 +174,30 @@ export class RdDItemArme extends RdDItem {
static defenseArmeParade(armeAttaque, armeParade) { static defenseArmeParade(armeAttaque, armeParade) {
const defCategory = RdDItemArme.getCategorieParade(armeParade) const defCategory = RdDItemArme.getCategorieParade(armeParade)
if (defCategory == 'boucliers') { switch (defCategory) {
return 'norm' case 'boucliers':
return 'norm'
case '':
return 'impossible'
} }
if (armeAttaque?.system?.competence?.toLowerCase().match(/(fléau)/)) { if (RdDItemArme.$isFleau(armeAttaque)) {
return '' return 'impossible'
}
if (armeParade.system?.tir) {
return ''
} }
const attCategory = RdDItemArme.getCategorieParade(armeAttaque) const attCategory = RdDItemArme.getCategorieParade(armeAttaque)
switch (attCategory) { switch (attCategory) {
case 'armes-naturelles': case 'sans-armes': case 'sans-armes':
return defCategory == 'sans-armes' ? 'norm' : '' case 'armes-naturelles':
return defCategory == attCategory ? 'norm' : 'impossible'
default: default:
return RdDItemArme.needParadeSignificative(armeAttaque, armeParade) ? 'sign' : 'norm' return RdDItemArme.needParadeSignificative(armeAttaque, armeParade) ? 'sign' : 'norm'
} }
} }
static $isFleau(armeAttaque) {
return armeAttaque?.system?.competence?.toLowerCase().match(/(fléau)/);
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static needParadeSignificative(armeAttaque, armeParade) { static needParadeSignificative(armeAttaque, armeParade) {
if (!armeAttaque || !armeParade) { if (!armeAttaque || !armeParade) {
@@ -259,6 +284,10 @@ export class RdDItemArme extends RdDItem {
return this.system.mortalite == RDD_CONFIG.encaissement.empoignade return this.system.mortalite == RDD_CONFIG.encaissement.empoignade
} }
isPossession() {
return this.system.mortalite == RDD_CONFIG.encaissement.possession
}
isUtilisableEmpoigne() { isUtilisableEmpoigne() {
return this.system.baseInit == 3 || this.system.baseInit == 4 || this.system.competence == "Dague" return this.system.baseInit == 3 || this.system.baseInit == 4 || this.system.competence == "Dague"
} }

View File

@@ -1,40 +1,46 @@
export const POSSESSION_SANS_DRACONIC = { name: 'Sans draconic', type: 'competence', system: { niveau: 0, defaut_carac: "reve-actuel", }, img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp' } import { ITEM_TYPES, RDD_CONFIG } from "../constants.js"
import { CARACS } from "../rdd-carac.js"
export const CATEGORIES_COMPETENCES = {
generale: { key: 'generale', base: -4, label: "Générales" },
particuliere: { key: 'particuliere', base: -8, label: "Particulières" },
specialisee: { key: 'specialisee', base: -11, label: "Spécialisées" },
connaissance: { key: 'connaissance', base: -11, label: "Connaissances" },
draconic: { key: 'draconic', base: -11, label: "Draconic" },
melee: { key: 'melee', base: -6, label: "Mêlée" },
tir: { key: 'tir', base: -8, label: "Tir" },
lancer: { key: 'lancer', base: -8, label: "Lancer" }
}
export const CATEGORIES_COMPETENCE_COMBAT = [CATEGORIES_COMPETENCES.melee, CATEGORIES_COMPETENCES.tir, CATEGORIES_COMPETENCES.lancer].map(it => it.key)
export const CATEGORIES_COMPETENCES_CREATURES = {
generale: { key: 'generale', base: 0, label: "Générale" },
naturelle: { key: 'naturelle', base: 0, label: "Arme naturelle" },
melee: { key: 'melee', base: 0, label: "Mêlée" },
parade: { key: 'parade', base: 0, label: "Parade" },
tir: { key: 'tir', base: 0, label: "Tir" },
lancer: { key: 'lancer', base: 0, label: "Lancer" },
possession: { key: 'possession', base: 0, label: "Possession" },
}
export const POSSESSION_SANS_DRACONIC = {
name: 'Sans draconic',
type: ITEM_TYPES.competence,
img: RDD_CONFIG.icons.possession,
system: { niveau: 0, defaut_carac: CARACS.REVE_ACTUEL, categorie: CATEGORIES_COMPETENCES.draconic.key }
}
export const PAS_DE_DRACONIC = { name: 'Pas de draconic', type: 'competence', system: { niveau: -11, defaut_carac: "reve" }, img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp' } export const PAS_DE_DRACONIC = { name: 'Pas de draconic', type: 'competence', system: { niveau: -11, defaut_carac: "reve" }, img: 'systems/foundryvtt-reve-de-dragon/icons/entites/possession.webp' }
export const BASE_CORPS_A_CORPS = { name: 'Corps à Corps', type: 'competence', system: { niveau: -6, defaut_carac: "melee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' } export const BASE_CORPS_A_CORPS = { name: 'Corps à Corps', type: 'competence', system: { niveau: -6, defaut_carac: "melee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_corps_a_corps.webp' }
export const BASE_ESQUIVE = { name: 'Esquive', type: 'competence', system: { niveau: -6, defaut_carac: "derobee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp' } export const BASE_ESQUIVE = { name: 'Esquive', type: 'competence', system: { niveau: -6, defaut_carac: "derobee" }, img: 'systems/foundryvtt-reve-de-dragon/icons/competence_esquive.webp' }
export const SANS_COMPETENCE = { export const SANS_COMPETENCE = {
name: "Sans compétence", name: "Sans compétence",
type: 'competence', type: ITEM_TYPES.competence,
img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp",
system: { system: {
niveau: 0, niveau: 0,
default_diffLibre: 0, default_diffLibre: 0,
base: 0, categorie: CATEGORIES_COMPETENCES.generale.key,
categorie: "Aucune", }
description: "",
descriptionmj: "",
defaut_carac: "",
},
img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.webp"
}
export const CATEGORIES_COMPETENCES = {
"generale": { base: -4, label: "Générales" },
"particuliere": { base: -8, label: "Particulières" },
"specialisee": { base: -11, label: "Spécialisées" },
"connaissance": { base: -11, label: "Connaissances" },
"draconic": { base: -11, label: "Draconic" },
"melee": { base: -6, label: "Mêlée" },
"tir": { base: -8, label: "Tir" },
"lancer": { base: -8, label: "Lancer" }
}
export const CATEGORIES_COMPETENCES_CREATURES = {
"generale": { base: 0, label: "Générale" },
"naturelle": { base: 0, label: "Arme naturelle" },
"melee": { base: 0, label: "Mêlée" },
"parade": { base: 0, label: "Parade" },
"tir": { base: 0, label: "Tir" },
"lancer": { base: 0, label: "Lancer" },
"possession": { base: 0, label: "Possession" },
} }

View File

@@ -1,4 +1,4 @@
import { ACTOR_TYPES } from "../constants.js" import { ACTOR_TYPES, ITEM_TYPES } from "../constants.js"
import { Misc } from "../misc.js" import { Misc } from "../misc.js"
import { RdDSheetUtility } from "../rdd-sheet-utility.js" import { RdDSheetUtility } from "../rdd-sheet-utility.js"
import { RdDUtility } from "../rdd-utility.js" import { RdDUtility } from "../rdd-utility.js"
@@ -11,33 +11,35 @@ import { RdDUtility } from "../rdd-utility.js"
const _SPACEHOLDER = { placeholder: true } const _SPACEHOLDER = { placeholder: true }
const _VENDRE = { const _VENDRE = {
code: 'item-vendre', label: 'Vendre ou donner', icon: it => 'fa-solid fa-comments-dollar', code: 'item-vendre', label: 'Vendre ou donner', icon: 'fa-solid fa-comments-dollar',
filter: it => Misc.toInt(it.system.quantite) > 0 || it.parent?.type == ACTOR_TYPES.commerce, filter: it => Misc.toInt(it.system.quantite) > 0 || it.parent?.type == ACTOR_TYPES.commerce,
action: (item, actor) => item.proposerVente() action: (item, actor) => item.proposerVente()
} }
const _ACHETER = { const _ACHETER = {
code: 'item-acheter', label: 'Acheter', icon: it => 'fa-regular fa-coins', code: 'item-acheter', label: 'Acheter', icon: 'fa-regular fa-coins',
filter: it => it.parent?.type == ACTOR_TYPES.commerce, filter: it => it.parent?.type == ACTOR_TYPES.commerce,
allowLimited: true, allowLimited: true,
action: (item, actor) => actor.vente(item) action: (item, actor) => actor.vente(item)
} }
const _MONTRER = { const _MONTRER = {
code: 'item-montrer', label: 'Montrer', icon: it => 'fa-solid fa-comment', code: 'item-montrer', label: 'Montrer', icon: 'fa-solid fa-comment',
allowLimited: true, allowLimited: true,
action: (item, actor) => item.postItemToChat() action: (item, actor) => item.postItemToChat()
} }
const _SPLIT = { const _SPLIT = {
code: 'item-split', label: 'Séparer le goupe', icon: it => 'fa-solid fa-unlink', code: 'item-split', label: 'Séparer le goupe', icon: 'fa-solid fa-unlink',
filter: it => Misc.toInt(it.system.quantite) > 1 && it.parent?.type != ACTOR_TYPES.commerce, filter: it => Misc.toInt(it.system.quantite) > 1 && it.parent?.type != ACTOR_TYPES.commerce,
action: (item, actor) => RdDSheetUtility.splitItem(item, actor) action: (item, actor) => RdDSheetUtility.splitItem(item, actor)
} }
const _EDIT = { const _EDIT = {
code: 'item-edit', label: 'Editer', icon: it => 'fa-solid fa-edit', code: 'item-edit', label: it => it.type == ITEM_TYPES.conteneur ? 'Ouvrir' : 'Editer',
icon: 'fa-solid fa-edit',
action: (item, actor) => item.sheet.render(true) action: (item, actor) => item.sheet.render(true)
} }
const _DELETE = { const _DELETE = {
code: 'item-delete', label: 'Supprimer', icon: it => 'fa-solid fa-trash', code: 'item-delete', label: 'Supprimer', icon: 'fa-solid fa-trash',
optionsFilter: options => options.isOwner, optionsFilter: options => options.isOwner,
action: (item, actor) => RdDUtility.confirmActorItemDelete(item, actor) action: (item, actor) => RdDUtility.confirmActorItemDelete(item, actor)
} }
@@ -48,53 +50,55 @@ const _EQUIPER = {
} }
const _CUISINER = { const _CUISINER = {
code: 'item-cuisiner', label: 'Cuisiner', icon: it => 'fa-solid fa-utensils', code: 'item-cuisiner', label: 'Cuisiner',
img: 'systems/foundryvtt-reve-de-dragon/assets/actions/cuisine.svg',
filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0, filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0,
action: (item, actor) => actor.preparerNourriture(item) action: (item, actor) => actor.preparerNourriture(item)
} }
const _MANGER_CRU = { const _MANGER_CRU = {
code: 'item-manger-cru', label: 'Manger cru', icon: it => 'fa-solid fa-drumstick-bite', code: 'item-manger-cru', label: 'Manger cru', icon: 'fa-solid fa-drumstick-bite',
filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0, filter: it => it.getUtilisation() == 'cuisine' && it.system.sust > 0,
action: (item, actor) => actor.mangerNourriture(item) action: (item, actor) => actor.mangerNourriture(item)
} }
const _MANGER = { const _MANGER = {
code: 'item-manger', label: 'Manger', icon: it => 'fa-solid fa-utensils', code: 'item-manger', label: 'Manger', icon: 'fa-solid fa-utensils',
filter: it => !(it.system.boisson), filter: it => !(it.system.boisson),
action: (item, actor) => actor.mangerNourriture(item) action: (item, actor) => actor.mangerNourriture(item)
} }
const _BOIRE = { const _BOIRE = {
code: 'item-boire', label: 'Boire', icon: it => 'fa-solid fa-glass-water', code: 'item-boire', label: 'Boire', icon: 'fa-solid fa-glass-water',
filter: it => it.system.boisson, filter: it => it.system.boisson,
action: (item, actor) => actor.mangerNourriture(item) action: (item, actor) => actor.mangerNourriture(item)
} }
const _DECOCTION = { const _DECOCTION = {
code: 'item-decoction', label: 'Décoction', icon: it => 'fa-solid fa-flask-vial', code: 'item-decoction', label: 'Décoction', icon: 'fa-solid fa-flask-vial',
action: (item, actor) => actor.fabriquerDecoctionHerbe(item) action: (item, actor) => actor.fabriquerDecoctionHerbe(item)
} }
const _OUVRIR = { const _OUVRIR = {
code: 'item-edit', label: 'Ouvrir', icon: it => 'fa-solid fa-eye', code: 'item-edit', label: 'Ouvrir',
img: 'systems/foundryvtt-reve-de-dragon/assets/actions/ouvrir.svg',
action: (item, actor) => item.sheet.render(true) action: (item, actor) => item.sheet.render(true)
} }
const _LIRE = { const _LIRE = {
code: 'item-lire', label: 'Lire', icon: it => 'fa-solid fa-book-open', code: 'item-lire', label: 'Lire', icon: 'fa-solid fa-book-open',
action: (item, actor) => actor.actionLire(item) action: (item, actor) => actor.actionLire(item)
} }
const _REFOULER = { const _REFOULER = {
code: 'item-refouler', label: 'Refouler', icon: it => 'fa-solid fa-burst', code: 'item-refouler', label: 'Refouler', icon: 'fa-solid fa-burst',
filter: it => it.system.refoulement > 0, filter: it => it.system.refoulement > 0,
action: (item, actor) => actor.actionRefoulement(item) action: (item, actor) => actor.actionRefoulement(item)
} }
const _SORT_RESERVE = { const _SORT_RESERVE = {
code: 'item-sortreserve-add', label: 'Ajouter en réserve', icon: it => 'fa-solid fa-sparkles', code: 'item-sortreserve-add', label: 'Ajouter en réserve', icon: 'fa-solid fa-sparkles',
filter: it => game.user.isGM && !it.system.isrituel, filter: it => game.user.isGM && !it.system.isrituel,
action: (item, actor) => actor.addSortReserve(item) action: (item, actor) => actor.addSortReserve(item)
} }
export const COMMON_ACTIONS = [_EQUIPER] export const COMMON_ACTIONS = [_EQUIPER]
export const DEFAULT_ACTIONS = [_ACHETER, _SPACEHOLDER, _SPLIT, _VENDRE, _MONTRER, _EDIT, _DELETE] export const DEFAULT_ACTIONS = [_ACHETER, _SPLIT, _SPACEHOLDER, _VENDRE, _MONTRER, _EDIT, _DELETE]
export const ITEM_ACTIONS = { export const ITEM_ACTIONS = {
faune: [_CUISINER, _MANGER_CRU], faune: [_CUISINER, _MANGER_CRU],
@@ -119,11 +123,31 @@ export class ItemAction {
&& (!action.optionsFilter || action.optionsFilter(options)) && (!action.optionsFilter || action.optionsFilter(options))
} }
static icon(action, item) { static label(action, item) {
if (action && action.icon) { if (action.placeholder) {
return action.icon(item) return ""
} }
return undefined return ItemAction.getParam(action.label, item)
}
static img(action, item) {
if (action.placeholder) {
return ""
}
const img = ItemAction.getParam(action.img, item)
if (img) {
return `<img src="${img}" />`
}
const icon = ItemAction.getParam(action.icon, item)
if (icon) {
return `<i class="${icon}"></i>`
}
return action.label
}
static getParam(p, item) {
return typeof (p) == 'function' ? p(item) : p
} }
static async onActionItem(event, actor, options) { static async onActionItem(event, actor, options) {

View File

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

View File

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

View File

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

View File

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

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

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

View File

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

View File

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

View File

@@ -19,6 +19,7 @@ import { ROLL_TYPE_ATTAQUE, ROLL_TYPE_DEFENSE } from "./roll/roll-constants.mjs"
import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js"; import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs"; import { MappingCreatureArme } from "./item/mapping-creature-arme.mjs";
import { RollBasicParts } from "./roll/roll-basic-parts.mjs"; import { RollBasicParts } from "./roll/roll-basic-parts.mjs";
import { Distance } from "./combat/distance.mjs";
/* -------------------------------------------- */ /* -------------------------------------------- */
const premierRoundInit = [ const premierRoundInit = [
@@ -58,9 +59,13 @@ export class RdDCombatManager extends Combat {
static getCombatant(actorId, tokenId) { static getCombatant(actorId, tokenId) {
return game.combat.combatants.find(it => it.actor.id == actorId && return game.combat?.combatants.find(it => it.actor.id == actorId &&
it.token.id == tokenId it.token.id == tokenId
); )
}
static getRangInitiativeCombatant(actorId, tokenId) {
const combatant = RdDCombatManager.getCombatant(actorId, tokenId)
return combatant?.system.init?.rang
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async nextRound() { async nextRound() {
@@ -105,7 +110,7 @@ export class RdDCombatManager extends Combat {
} }
else if (!combatant.actor.isActorCombat()) { else if (!combatant.actor.isActorCombat()) {
if (options.warning) { if (options.warning) {
ui.notifications.warn(`${combatant.name} ne peut pas combattre!`) ui.notifications.warn(`L'acteur ${combatant.name} ne peut pas combattre!`)
} }
return undefined return undefined
} }
@@ -153,7 +158,7 @@ export class RdDCombatManager extends Combat {
alias: combatant.token?.name, alias: combatant.token?.name,
sound: CONFIG.sounds.dice, sound: CONFIG.sounds.dice,
}, },
flavor: `${combatant.token?.name} a une initiatyive de ${init.value} : ${messageOptions.info}<br>` flavor: `${combatant.token?.name} a une initiative de ${init.value} : ${messageOptions.info}<br>`
}, },
messageOptions); messageOptions);
init.roll.toMessage(messageData, { rollMode, create: true }); init.roll.toMessage(messageData, { rollMode, create: true });
@@ -315,6 +320,7 @@ export class RdDCombat {
switch (sockmsg.msg) { switch (sockmsg.msg) {
case "msg_encaisser": return RdDCombat.onMsgEncaisser(sockmsg.data); case "msg_encaisser": return RdDCombat.onMsgEncaisser(sockmsg.data);
case "msg_defense": return RdDCombat.onMsgDefense(sockmsg.data); case "msg_defense": return RdDCombat.onMsgDefense(sockmsg.data);
case "msg_defense_v2": return RdDCombat.onMsgDefenseV2(sockmsg.data);
} }
} }
@@ -367,6 +373,18 @@ export class RdDCombat {
return new RdDCombat(attacker, attackerTokenId, defender, defenderTokenId, target) return new RdDCombat(attacker, attackerTokenId, defender, defenderTokenId, target)
} }
static rddCombatForAttackV2(attackerRoll) {
return RdDCombat.rddCombatForDefenseV2(RollBasicParts.prepareDefense(attackerRoll))
}
static rddCombatForDefenseV2(defenderRoll) {
let defenderToken = canvas.tokens.get(defenderRoll.active.tokenId)
if (defenderToken) {
return RdDCombat.rddCombatForAttackerAndDefender(defenderRoll.opponent.id, defenderRoll.opponent.tokenId, defenderRoll.active.tokenId)
}
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static onMsgEncaisser(msg) { static onMsgEncaisser(msg) {
let defender = canvas.tokens.get(msg.defenderToken.id).actor; let defender = canvas.tokens.get(msg.defenderToken.id).actor;
@@ -500,8 +518,8 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
attaqueChanceuse(attackerRoll) { attaqueChanceuse(attackerRoll) {
ui.notifications.info("L'attaque est rejouée grâce à la chance") ui.notifications.info("L'attaque est rejouée grâce à la chance")
attackerRoll.essais.attaqueChance = true; attackerRoll.essais.attaqueChance = true
this.attaque(attackerRoll, attackerRoll.arme); this.attaque(attackerRoll, attackerRoll.arme)
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@@ -612,68 +630,27 @@ export class RdDCombat {
} }
else { else {
const defenderToken = canvas.tokens.get(this.defenderTokenId) const defenderToken = canvas.tokens.get(this.defenderTokenId)
const dist = this.distance(_token, defenderToken) const info = foundry.utils.mergeObject(
const isVisible = this.isVisible(_token, defenderToken) {
const portee = this._ajustementPortee(dist, rollData.arme)
const taille = this._ajustementTaille(this.defender)
const activite = this._ajustementMouvement(this.defender)
const total = [portee, taille, activite].map(it => it.diff).filter(d => !Number.isNaN(d)).reduce(Misc.sum(), 0)
ChatMessage.create({
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.hbs', {
rollData: rollData, rollData: rollData,
attacker: _token, attacker: _token,
isVisible: isVisible,
defender: defenderToken, defender: defenderToken,
distance: dist, },
portee: portee, Distance.ajustements(_token, defenderToken, { arme: rollData.arme, main: rollData.competence.system.categorie })
taille: taille, )
activite: activite, ChatMessage.create({
total: total content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-info-distance.hbs', info),
}),
whisper: ChatUtility.getGMs() whisper: ChatUtility.getGMs()
}) })
} }
} }
} }
isVisible(token, defenderToken) { async attaqueV2(options = undefined) {
return canvas.effects.visibility.testVisibility(defenderToken.center, { object: token })
}
distance(token, defenderToken) {
return Number(canvas.grid.measureDistances([{ ray: new Ray(token.center, defenderToken.center) }], { gridSpaces: false })).toFixed(1);
}
_ajustementPortee(dist, arme) {
if (dist <= arme.system.portee_courte) return { msg: "courte", diff: 0 };
if (dist <= arme.system.portee_moyenne) return { msg: "moyenne", diff: -3 };
if (dist <= arme.system.portee_extreme) return { msg: "extrême", diff: -5 };
return { msg: "inatteignable", diff: -10 };
}
_ajustementTaille(actor) {
if (actor.isVehicule()) return { msg: "véhicule", diff: 0 }
const taille = actor.getCaracByName('TAILLE')?.value ?? 1;
if (taille <= 1) return { msg: "souris", diff: -8 };
if (taille <= 3) return { msg: "chat", diff: -4 };
if (taille <= 5) return { msg: "chien", diff: -2 };
if (taille <= 15) return { msg: "humanoïde", diff: 0 };
if (taille <= 20) return { msg: "ogre", diff: 2 };
return { msg: "gigantesque", diff: 4 };
}
_ajustementMouvement(defender) {
if (defender.getSurprise(true) != '') return { msg: "immobile (surprise)", diff: 0 };
if (game.combat?.combatants.find(it => it.actorId == defender.id)) return { msg: "en mouvement (combat)", diff: -4 };
return { msg: "à déterminer (0 immobile, -3 actif, -4 en mouvement, -5 en zig-zag)", diff: -3 };
}
async attaqueV2() {
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) { if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
return return
} }
await this.doRollAttaque({ const rollData = {
ids: { ids: {
actorId: this.attackerId, actorId: this.attackerId,
actorTokenId: this.attackerTokenId, actorTokenId: this.attackerTokenId,
@@ -681,13 +658,23 @@ export class RdDCombat {
opponentTokenId: this.defenderTokenId, opponentTokenId: this.defenderTokenId,
}, },
type: { allowed: ['attaque'], current: 'attaque' }, type: { allowed: ['attaque'], current: 'attaque' },
selected: {},
passeArme: foundry.utils.randomID(16), passeArme: foundry.utils.randomID(16),
}) }
if (options) {
rollData.selected = {
attaque: {
comp: { id: options.comp.id },
arme: { id: options.arme.id },
main: options.main
}
}
}
await this.doRollAttaque(rollData)
} }
async doRollAttaque(rollData, callbacks = []) { async doRollAttaque(rollData, callbacks = []) {
// TODO V2 await this.proposerAjustementTirLancer(rollData) return await RollDialog.create(rollData, {
await RollDialog.create(rollData, {
onRollDone: RollDialog.onRollDoneClose, onRollDone: RollDialog.onRollDoneClose,
callbacks: [ callbacks: [
async (roll) => await this.onAttaqueV2(roll), async (roll) => await this.onAttaqueV2(roll),
@@ -722,11 +709,26 @@ export class RdDCombat {
await this._chatMessageDefenseV2(paramChatDefense); await this._chatMessageDefenseV2(paramChatDefense);
} }
else { else {
this._socketSendMessageDefense(paramChatDefense, {}); this._socketSendMessageDefenseV2(paramChatDefense);
} }
} }
_socketSendMessageDefenseV2(paramChatDefense) {
game.socket.emit(SYSTEM_SOCKET_ID, { msg: "msg_defense_v2", data: { paramChatDefense } })
}
static async onMsgDefenseV2(msg) {
if (Misc.isFirstConnectedGM()) {
const paramChatDefense = msg.paramChatDefense
RollBasicParts.restore(paramChatDefense.attackerRoll)
const rddCombat = RdDCombat.rddCombatForAttackV2(paramChatDefense.attackerRoll)
rddCombat?.removeChatMessageActionsPasseArme(paramChatDefense.attackerRoll.passeArme)
await rddCombat?._chatMessageDefenseV2(paramChatDefense)
}
}
async _chatMessageDefenseV2(paramDemandeDefense) { async _chatMessageDefenseV2(paramDemandeDefense) {
const attackerRoll = paramDemandeDefense.attackerRoll; const attackerRoll = paramDemandeDefense.attackerRoll
RollBasicParts.loadSurprises(attackerRoll) RollBasicParts.loadSurprises(attackerRoll)
attackerRoll.dmg = RdDBonus.dmgRollV2(attackerRoll, attackerRoll.current.attaque) attackerRoll.dmg = RdDBonus.dmgRollV2(attackerRoll, attackerRoll.current.attaque)
@@ -749,12 +751,14 @@ export class RdDCombat {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async attaque(competence, arme) { async attaque(competence, arme, main) {
if (!await this.attacker.accorder(this.defender, 'avant-attaque')) { if (!await this.attacker.accorder(this.defender, 'avant-attaque')) {
return return
} }
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) { if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
return this.attacker.rollCompetence(competence.name, { arme: arme }) return this.attaqueV2(
{ comp: competence, arme: arme, main: main }
)
} }
if (arme.system.cac == EMPOIGNADE) { if (arme.system.cac == EMPOIGNADE) {
RdDEmpoignade.onAttaqueEmpoignade(this.attacker, this.defender) RdDEmpoignade.onAttaqueEmpoignade(this.attacker, this.defender)
@@ -763,7 +767,7 @@ export class RdDCombat {
RdDEmpoignade.checkEmpoignadeEnCours(this.attacker) RdDEmpoignade.checkEmpoignadeEnCours(this.attacker)
let rollData = this._prepareAttaque(competence, arme) let rollData = this._prepareAttaque(competence, arme)
console.log("RdDCombat.attaque >>>", rollData); console.log("RdDCombat.attaque >>>", rollData)
if (arme) { if (arme) {
this.attacker.verifierForceMin(arme); this.attacker.verifierForceMin(arme);
} }
@@ -788,7 +792,7 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
_prepareAttaque(competence, arme) { _prepareAttaque(competence, arme) {
let rollData = { let rollData = {
mode: ROLL_TYPE_ATTAQUE, mode: 'attaque',
alias: this.attacker?.getAlias(), alias: this.attacker?.getAlias(),
passeArme: foundry.utils.randomID(16), passeArme: foundry.utils.randomID(16),
mortalite: arme?.system.mortalite, mortalite: arme?.system.mortalite,
@@ -1056,8 +1060,7 @@ export class RdDCombat {
} }
async defenseV2(attackerRoll, callbacks = []) { async defenseV2(attackerRoll, callbacks = []) {
// this._prepareParade(attackerRoll, arme, competence);
RollDialog.loadRollData(attackerRoll)
await this.doRollDefense({ await this.doRollDefense({
ids: { ids: {
actorId: this.defender.id, actorId: this.defender.id,
@@ -1072,7 +1075,7 @@ export class RdDCombat {
} }
async doRollDefense(rollData, callbacks = []) { async doRollDefense(rollData, callbacks = []) {
await RollDialog.create(rollData, { return await RollDialog.create(rollData, {
onRollDone: RollDialog.onRollDoneClose, onRollDone: RollDialog.onRollDoneClose,
callbacks: [ callbacks: [
async (roll) => { async (roll) => {
@@ -1392,6 +1395,7 @@ export class RdDCombat {
return return
} }
const alias = token?.name ?? actor.getAlias(); const alias = token?.name ?? actor.getAlias();
const blessuresGraves = actor.countBlessures(it => it.isGrave());
const formData = { const formData = {
combatId: combat._id, combatId: combat._id,
alias: alias, alias: alias,
@@ -1402,7 +1406,7 @@ export class RdDCombat {
actorId: actor.id, actorId: actor.id,
actor: actor, actor: actor,
tokenId: token.id, tokenId: token.id,
isGrave: actor.countBlessures(it => it.isGrave()) > 0, blessuresGraves: blessuresGraves,
isCritique: actor.countBlessures(it => it.isCritique()) > 0 isCritique: actor.countBlessures(it => it.isCritique()) > 0
} }
await ChatMessage.create({ await ChatMessage.create({

View File

@@ -116,6 +116,7 @@ export class RdDCommands {
this.registerCommand({ this.registerCommand({
path: ["/xp", "carac"], func: (content, msg, params) => this.getCoutXpCarac(msg, params), path: ["/xp", "carac"], func: (content, msg, params) => this.getCoutXpCarac(msg, params),
descr: `Détermine le coût d'expérience pour augmenter une caractéristique. Exemples: descr: `Détermine le coût d'expérience pour augmenter une caractéristique. Exemples:
<br>/xp carac 12 15: coût pour passer de 12 15
<br>/xp carac 15: coût pour atteindre 15 (depuis 14)` <br>/xp carac 15: coût pour atteindre 15 (depuis 14)`
}); });
@@ -127,7 +128,7 @@ export class RdDCommands {
<br><strong>/rdd 15 -2</strong> effectue un jet 15 à -2 <br><strong>/rdd 15 -2</strong> effectue un jet 15 à -2
<br><strong>/rdd 15 0 s</strong> effectue un jet 15 à 0, avec significative requise <br><strong>/rdd 15 0 s</strong> effectue un jet 15 à 0, avec significative requise
<br><strong>/rdd Vue Vigilance -2</strong> effectue un jet de Vue/Vigilance à -2 pour les tokens sélectionnés <br><strong>/rdd Vue Vigilance -2</strong> effectue un jet de Vue/Vigilance à -2 pour les tokens sélectionnés
<br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés <br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en Désert à +2 pour les tokens sélectionnés
` `
}); });
this.registerCommand({ this.registerCommand({
@@ -137,7 +138,7 @@ export class RdDCommands {
<br><strong>/jet Vue</strong> poste une demande de jet de VUE à 0 <br><strong>/jet Vue</strong> poste une demande de jet de VUE à 0
<br><strong>/jet Vue -2</strong> poste une demande de jet de VUE à -2 <br><strong>/jet Vue -2</strong> poste une demande de jet de VUE à -2
<br><strong>/jet Vue Vigilance -2</strong> poste une demande de jet de VUE / Vigilance à -2 <br><strong>/jet Vue Vigilance -2</strong> poste une demande de jet de VUE / Vigilance à -2
<br><strong>/jet vol déser +2</strong> poste une demande de jet de VOLONTÉ / Survie en désert à +2 <br><strong>/jet vol déser +2</strong> poste une demande de jet de VOLONTÉ / Survie en Désert à +2
` `
}); });
this.registerCommand({ path: ["/ddr"], func: (content, msg, params) => this.rollDeDraconique(msg), descr: "Lance un Dé Draconique" }); this.registerCommand({ path: ["/ddr"], func: (content, msg, params) => this.rollDeDraconique(msg), descr: "Lance un Dé Draconique" });
@@ -440,13 +441,18 @@ export class RdDCommands {
/* -------------------------------------------- */ /* -------------------------------------------- */
getCoutXpCarac(msg, params) { getCoutXpCarac(msg, params) {
if (params && params.length == 1) { if (params) {
let to = Number(params[0]); if (params.length == 1) {
return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to)}`); const to = Number(params[0])
} return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${to - 1} à ${to}: ${RdDCarac.getCaracXp(to - 1, to)}`);
else { }
return false; if (params.length == 2) {
const from = Number(params[0]);
const to = Number(params[1]);
return RdDCommands._chatAnswer(msg, `Coût pour passer une caractéristique de ${from} à ${to}: ${RdDCarac.getCaracXp(from, to)}`);
}
} }
return false
} }
async creerSignesDraconiques() { async creerSignesDraconiques() {

View File

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

View File

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

View File

@@ -1,5 +1,7 @@
import { SYSTEM_RDD, SYSTEM_SOCKET_ID, RDD_CONFIG, ITEM_TYPES } from "./constants.js" import { SYSTEM_RDD, SYSTEM_SOCKET_ID, RDD_CONFIG, ITEM_TYPES } from "./constants.js"
const RDD_INFO_MESSAGE_URL = "https://gitea.scriptarium.org/Scriptarium/foundryvtt-reve-de-dragon/raw/branch/v13/info-message.html"
import { RdDUtility } from "./rdd-utility.js" import { RdDUtility } from "./rdd-utility.js"
import { TMRUtility } from "./tmr-utility.js" import { TMRUtility } from "./tmr-utility.js"
import { TMRRencontres } from "./tmr-rencontres.js" import { TMRRencontres } from "./tmr-rencontres.js"
@@ -89,6 +91,9 @@ import { Migrations } from './migrations.js'
import RollDialog from "./roll/roll-dialog.mjs" import RollDialog from "./roll/roll-dialog.mjs"
import ChatRollResult from "./roll/chat-roll-result.mjs" import ChatRollResult from "./roll/chat-roll-result.mjs"
import ExportPdf from "./actor/export-pdf/export-pdf.mjs"
import { DialogFlushByDate } from "./chat/dialog-flush-by-date.mjs"
import { Remote } from "./remote.mjs"
/** /**
* RdD system * RdD system
@@ -180,6 +185,7 @@ export class SystemReveDeDragon {
game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => { game.socket.on(SYSTEM_SOCKET_ID, async (sockmsg) => {
console.log(">>>>> MSG RECV", sockmsg) console.log(">>>>> MSG RECV", sockmsg)
try { try {
Remote.onSocketMessage(sockmsg)
RdDUtility.onSocketMessage(sockmsg) RdDUtility.onSocketMessage(sockmsg)
RdDCombat.onSocketMessage(sockmsg) RdDCombat.onSocketMessage(sockmsg)
ChatUtility.onSocketMessage(sockmsg) ChatUtility.onSocketMessage(sockmsg)
@@ -246,11 +252,11 @@ export class SystemReveDeDragon {
ITEM_TYPES.jeu, ITEM_TYPES.jeu,
ITEM_TYPES.race, ITEM_TYPES.race,
ITEM_TYPES.recettecuisine, ITEM_TYPES.recettecuisine,
ITEM_TYPES.oeuvre, ITEM_TYPES.oeuvre,
ITEM_TYPES.meditation, ITEM_TYPES.meditation,
ITEM_TYPES.queue, ITEM_TYPES.queue,
ITEM_TYPES.ombre, ITEM_TYPES.ombre,
ITEM_TYPES.souffle, ITEM_TYPES.souffle,
ITEM_TYPES.tete, ITEM_TYPES.tete,
ITEM_TYPES.casetmr, ITEM_TYPES.casetmr,
ITEM_TYPES.sort, ITEM_TYPES.sort,
@@ -296,8 +302,10 @@ export class SystemReveDeDragon {
RdDPossession.init() RdDPossession.init()
TMRRencontres.init() TMRRencontres.init()
ExportScriptarium.init() ExportScriptarium.init()
ExportPdf.init()
RollDialog.init() RollDialog.init()
ChatRollResult.init() ChatRollResult.init()
DialogFlushByDate.init()
} }
initSettings() { initSettings() {
@@ -350,6 +358,15 @@ export class SystemReveDeDragon {
}, },
default: "aucun" default: "aucun"
}) })
/* -------------------------------------------- */
game.settings.register(SYSTEM_RDD, "info-msg-timeout", {
name: "Gestion du timeout d'affichage du message d'information",
scope: "world",
config: false,
type: Number,
default: 0
})
} }
async onReady() { async onReady() {
@@ -408,10 +425,33 @@ export class SystemReveDeDragon {
<br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs} <br>Vous trouverez quelques informations pour démarrer dans ce document : @Compendium[foundryvtt-reve-de-dragon.rappel-des-regles.7uGrUHGdPu0EmIu2]{Documentation MJ/Joueurs}
<br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div> <br>La commande <code>/aide</code> dans le chat permet de voir les commandes spécifiques à Rêve de Dragon.</div>
` }) ` })
// Get last message display time
const lastDisplay = game.settings.get(SYSTEM_RDD, "info-msg-timeout") || 0
const now = Date.now()
const oneDayMs = 24 * 60 * 60 * 1000
if (now - lastDisplay < oneDayMs) {
return // Already displayed in the last 24 hours
}
// Update last display time
game.settings.set(SYSTEM_RDD, "info-msg-timeout", now)
// Try to fetch the welcome message from the github repo RDD_INFO_MESSAGE_URL
fetch(RDD_INFO_MESSAGE_URL)
.then(response => response.text())
.then(html => {
console.log("Fetched welcome message:", html);
ChatMessage.create({
user: game.user.id,
whisper: [game.user.id],
content: html
});
})
.catch(error => {
console.error("Error fetching welcome message:", error);
});
} }
} }
roll(rollData, actors, options){ roll(rollData, actors, options) {
RollDialog.create(rollData, actors, options) RollDialog.create(rollData, actors, options)
} }
} }

View File

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

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