Compare commits

..

116 Commits
v1.4 ... master

Author SHA1 Message Date
c515e9bc66 Merge branch 'tyrcho-master-patch-22717' into 'master'
typos

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!269
2021-06-07 22:01:32 +00:00
b2e7a8a6e1 typos 2021-06-07 21:41:04 +00:00
09045c0d53 Blocage astro #198, Synchro horloge #197, gérer pièces #196 2021-06-01 21:05:45 +02:00
4c4e1e8419 Fix combat et messages 2021-06-01 07:52:47 +02:00
66bcc51102 Merge branch 'master-fix-combat' into 'master'
Fix: regression combat

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!262
2021-06-01 04:34:22 +00:00
32844bbf3c increment version 1.3.62 2021-06-01 00:20:24 +02:00
21d6f14b68 Fix: regression combat
Notifier tous les postes clients des données de passe d'arme
2021-06-01 00:18:41 +02:00
87a0bece5e Cosmetic changes 2021-05-26 17:45:52 +02:00
e0f83e9be2 Fix TMR 2021-05-26 16:41:18 +02:00
01c1978ccd Fix pour montée TMR en double 2021-05-24 09:36:09 +02:00
47ae157781 Fix pour montée TMR en double 2021-05-24 09:35:49 +02:00
0c092b9099 Fix for Misc.js 2021-05-22 17:51:30 +02:00
a6d1a84b13 Fix combat avec MJ 2021-05-22 08:40:00 +02:00
82e8954d5c Merge branch 'master-fix-defense-193' into 'master'
#193: utiliser isElectedUser pour les défenses

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!249
2021-05-22 06:39:14 +00:00
249850558b #193: utiliser isElectedUser pour les défenses
Misc.isElectedUser renvoit true pour un seul MJ connecté,
ou le joueur connecté s'il n'y a pas de MJ.

Ca veut dire que sans MJ, les messages de combat ne marcheront
peut-être pas, mais pour tous les autres cas, ça marchera correctement,
vu que ce sera toujours un MJ qui postera le message de défense au
joueur (connecté ou pas) et au MJ
2021-05-22 02:04:25 +02:00
45b10f2c6b Fix sur defense 2021-05-18 10:14:57 +02:00
d39dac3bf9 Merge branch 'master-fix' into 'master'
Fix: pas de messages de défense

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!240
2021-05-18 08:14:18 +00:00
1f5e8c084b Fix +dom Bandersnatch 2021-05-18 00:36:07 +02:00
0864721bc5 Fix: pas de messages de défense
Dans certains cas, il n'y avait plus de message pour que le personnage
attaqué se défense
2021-05-17 23:18:03 +02:00
4c5685c20b Update release 2021-05-14 08:46:38 +02:00
a618200417 Merge branch 'master-fix' into 'master'
Fix rencontre Rêve de Dragon

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!237
2021-05-12 04:45:17 +00:00
62eb6482d0 Fix rencontre Rêve de Dragon
Le minimum était devenu 14
2021-05-12 00:06:53 +02:00
9b8ea03067 Merge branch 'master-fix' into 'master'
Fix jet récupération

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!229
2021-05-08 05:41:14 +00:00
8090d0280d Fix jet récupération
le +7 n'est pas justifié, sinon on ne fait que des rêves
de dragon
2021-05-08 00:27:50 +02:00
c31202fbd3 Merge branch 'master-misc' into 'master'
Utiliser des polices pour les dés

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!223
2021-05-01 21:50:58 +00:00
146c8d184c Utiliser des polices pour les dés
Afin de ne pas avoir de soucis de couleurs
2021-05-01 15:53:26 +02:00
c251727dea Aide tchat dans un dialogue 2021-05-01 13:00:49 +02:00
19f5e2af59 Fix jet éthylisme sur vie 2021-05-01 13:00:42 +02:00
8b2f02d4b0 Sync versions 2021-04-30 23:11:06 +02:00
03b88a269a Merge branch 'master-des' into 'master'
Un dé pour les heures draconiques

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!219
2021-04-30 06:13:46 +00:00
32d016b9ad Dé des heures
inutile, donc indispensable

 /roll 1dh
2021-04-30 00:51:38 +02:00
a0c1d063f1 Fix dé dragon sans bords pour tous
Pas uniquement pour le système rdd
2021-04-30 00:51:38 +02:00
1e5446fcde Merge branch 'master-des' into 'master'
Jolis dés draconiques

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!218
2021-04-29 06:25:38 +00:00
f76e0db046 Jolis dés draconiques 2021-04-29 03:59:16 +02:00
b7c816129b Merge branch 'master-blessures' into 'master'
Amélioration des blessures #173

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!216
2021-04-28 07:42:18 +00:00
c786757db0 Fix: oubli correction tmr multiples 2021-04-28 00:43:06 +02:00
78d4b48aae Amélioration des blessures #173
# Conflicts:
#	templates/chat-resultat-encaissement.html
2021-04-28 00:33:44 +02:00
0a9e8e0ac6 Amélioration présentation blessures #173 2021-04-28 00:33:44 +02:00
5443cb52bb Merge branch 'master-rappel-regles' into 'master'
Amélioration, rappel-des-regles

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!215
2021-04-27 07:34:02 +00:00
b232a8fa0c typofix 2021-04-27 00:36:01 +02:00
a68aa29b53 Extraction calcul chances 2021-04-26 23:45:43 +02:00
ccb9cd73f4 Amélioration, rappel-des-regles 2021-04-26 23:44:39 +02:00
723d1e6b99 Fix #187 2021-04-26 00:07:36 +02:00
40f99da8ac Merge branch 'master-fix-187' into 'master'
Fix: recul sur encaissement créature #187

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!213
2021-04-25 22:06:21 +00:00
76865d24d2 Fix: recul sur encaissement créature #187 2021-04-25 14:50:44 +02:00
020824af7e Reset des nombre astraux 2021-04-25 09:43:26 +02:00
cc8f432746 Merge branch 'master' of gitlab.com:LeRatierBretonnien/foundryvtt-reve-de-dragon 2021-04-24 09:31:41 +02:00
6435ce70da Fix sauvegarde TMR 2021-04-24 09:31:29 +02:00
db9cbc693a Merge branch 'master-fix' into 'master'
Fix: après dérobade, impossible ouvrir fiche

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!208
2021-04-18 06:39:12 +00:00
b202352979 Fix: après dérobade, impossible ouvrir fiche 2021-04-17 21:03:59 +02:00
7ddedea204 Updat release 2021-04-17 09:19:15 +02:00
2bca036d53 Merge branch 'master-fix' into 'master'
Empêcher doublons sur tête/souffle #175

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!206
2021-04-17 07:18:31 +00:00
8f08f95dbf Updat release 2021-04-17 09:08:09 +02:00
b5581ff9fb Ajout de tokens de créatures 2021-04-17 00:04:25 +02:00
e06ae1937a Empêcher doublons sur tête/souffle #175
Lors de l'ajout de la tête présents des cités, le présent de chaque
cité était ajouté par tous les joueurs connectés qui traitaient le hook
2021-04-16 23:33:09 +02:00
0f7e1ef553 Merge branch 'master-fix-compendium' into 'master'
Fix compendium voyageurs

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!201
2021-04-16 07:14:57 +00:00
51afd9020c Fix compendium voyageurs
- nom de token Coureur des Rues
- don de haut rêve pour le Cuisinier Haut-Rêvant
- tokens maintenant neutres
2021-04-15 20:00:14 +02:00
1bc5e06147 Merge branch 'master-fix-comp-base' into 'master'
Fix categorieCompetences.base

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!196
2021-04-09 08:29:51 +00:00
7f3a575349 Fix categorieCompetences.base
au lieu de niveau/level
2021-04-09 09:41:57 +02:00
c26ba66722 #182 - Décompte XP 2021-04-09 08:46:46 +02:00
cb105dd311 Merge branch 'master' of gitlab.com:LeRatierBretonnien/foundryvtt-reve-de-dragon 2021-04-09 08:09:20 +02:00
76c88e530e #182 - Décompte XP 2021-04-09 08:09:04 +02:00
03839397ce Merge branch 'master-fix-182' into 'master'
Fix xp des compétences tronc #182

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!195
2021-04-09 06:05:05 +00:00
74ddc8893a Fix xp des compétences tronc #182
La méthode splice retourne les éléments supprimées, et non pas
le tableau après suppression

# Conflicts:
#	module/item-competence.js
#	module/misc.js
2021-04-09 01:12:02 +02:00
790aa950c3 Message explicite HR 2021-04-04 09:03:28 +02:00
4672a3a7d6 Message explicite HR 2021-04-04 08:58:23 +02:00
2a8ab5e1ce Merge branch 'master-demi-surprise' into 'master'
Demi-surprise: Réussite normale => échec #181

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!190
2021-04-04 06:50:37 +00:00
4aaa72ed1a Erreur si draconic sans être haut-rêvant 2021-04-04 00:16:49 +02:00
f087b61c27 Demi-surprise: Réussite normale => échec #181
En demi-surprise, les résultats "réussite normaux" sont
maintenant présenté comme des réussite insuffisantes
2021-04-03 23:59:47 +02:00
96c6936c3e Fix: message pour non haut-rêvant 2021-04-03 23:59:47 +02:00
7d27d7d9f9 Fix sur commande astro 2021-04-03 23:01:04 +02:00
0d7ba3be69 Merge branch 'master' of gitlab.com:LeRatierBretonnien/foundryvtt-reve-de-dragon 2021-04-03 18:53:21 +02:00
8670456d9a Increment version 2021-04-03 18:53:09 +02:00
b2c7ff4927 Merge branch 'master-177' into 'master'
Fix: #177 arme creature incorrecte

Closes #177

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!189
2021-04-03 16:52:42 +00:00
680fbee090 Fix: #177 arme creature incorrecte 2021-04-03 13:05:10 +02:00
5c6a01b9f4 Push pour mini-fixes 2021-04-03 08:39:31 +02:00
d45f5d625a #179 - Fix reve-actuel 2021-04-03 08:32:27 +02:00
2b1a9151d7 Gestion état sonné correct 2021-04-03 08:18:08 +02:00
3335c41c27 Merge branch 'master-improve' into 'master'
Draconic pour les haut-rêvants - HUD

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!188
2021-04-03 06:16:18 +00:00
329ae475d9 Correction message échec total 2021-04-03 03:05:44 +02:00
72f8c83caf Draconic que pour les Haut rêvant #174 2021-04-03 03:04:48 +02:00
d353b6ccaf Fix regression liste tâches 2021-04-02 22:06:58 +02:00
a122a2e421 Merge branch 'master-hautrevant' into 'master'
Limiter le draconic aux Haut rêvant - #174

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!185
2021-04-02 06:45:10 +00:00
2465af4413 réparation icones 2021-04-01 23:02:03 +02:00
817c5d30ad Les haut-rêvants ont le don de haut rêve 2021-04-01 23:02:02 +02:00
87440cf7f9 Limiter le draconic aux Haut rêvant - #174 2021-04-01 23:02:02 +02:00
965e45cead Merge branch 'master-fixes' into 'master'
Fix détermination nombre astral

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!184
2021-04-01 05:41:36 +00:00
ac8610cd6c Fix détermination nombre astral
fixé, déplacé dans les savoirs

# Conflicts:
#	module/rdd-calendrier.js
#	templates/actor-sheet.html
2021-04-01 01:12:16 +02:00
08cf1f49e1 Fix Chanter la chanson 2021-04-01 01:12:15 +02:00
4925cee756 Fix changement jour 2021-04-01 01:12:15 +02:00
43acbfb443 Simplification calcul de difficulté alchimie 2021-04-01 01:12:15 +02:00
9a6fb1a850 Fix reférence de recette de cuisine 2021-04-01 01:12:15 +02:00
42fb0c0b5e Merge branch 'master-fixes' into 'master'
Création d'oeuvres

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!182
2021-03-31 06:40:56 +00:00
fa2b125459 Création d'oeuvres
# Conflicts:
#	module/actor-sheet.js
2021-03-31 01:34:52 +02:00
e8d0748688 Fix tooltip périple 2021-03-29 23:57:37 +02:00
2972504640 Fix caracXP, chance, /payer 2021-03-27 14:55:32 +01:00
3582fa9c8a Merge branch 'master-fixes' into 'master'
Fix expérience carac

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!179
2021-03-27 13:54:53 +00:00
d5277137dd Fix dépense chance sur appel à la chance 2021-03-27 14:41:12 +01:00
dae852a1e0 Fix expérience carac
=> await manquant
=> plusieurs whisper recipients: pas supporté
=> manque lowercase sur recherche de carac par nom
2021-03-27 14:41:12 +01:00
1ea6b66483 Fix chance 2021-03-26 07:42:58 +01:00
d35f3ce5a2 Merge branch 'master-improve' into 'master'
Fix jet de moral/chance

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!178
2021-03-26 06:42:14 +00:00
bf9e74ef7c Ne pas afficher la description d'un sort manqué
Pas d'affichage pour un sort mis en réserve non plus
2021-03-26 01:16:53 +01:00
fd73b2c7af Fix récupération chance 2021-03-26 01:16:52 +01:00
3aa13511cd Fix jet de moral
L'affichage du message ne fonctionnait plus
2021-03-26 01:16:52 +01:00
94cebbb9e5 Ajout edition nombre astral 2021-03-25 18:05:42 +01:00
2a1495927f Merge branch 'master' of gitlab.com:LeRatierBretonnien/foundryvtt-reve-de-dragon 2021-03-25 17:53:30 +01:00
8d42871988 Fix competence base 2021-03-25 17:52:02 +01:00
868ed01723 Merge branch 'master-improve' into 'master'
Fix /rdd [carac]

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!177
2021-03-25 16:36:49 +00:00
65c90c5bd4 Fix /rdd [carac]
- en cas de carac exact (reve), choisir cette caractéristique
(pas de message par rapport à reve-actuel)
- support /rdd odorat-gout
2021-03-25 10:27:33 +01:00
c16101428a Add 2021-03-25 07:45:32 +01:00
77d5646497 Permet les macros spéciales (SF) 2021-03-25 07:34:19 +01:00
1c0c775de3 Merge branch 'master-improve' into 'master'
Jets de masse

See merge request LeRatierBretonnien/foundryvtt-reve-de-dragon!174
2021-03-25 06:32:16 +00:00
e8a59b56a4 Fix: privilégier le nom exact 2021-03-25 01:58:41 +01:00
39f6307058 Version 1.3.38 2021-03-25 00:16:53 +01:00
a532a989d6 Jets de masse
Quelques exemples:

- `/rdd dexterite bricolage -2`
- `/rdd vue survie en sous-sol -2`
- `/rdd vue désert 0`
- `/rdd vue vigi -3`
- `/rdd vol vigi 0` : Volonté Vigilance
- `/rdd chance-actuelle 0`
- `/rdd reve-actuel -8`

Attention:
- `/rdd vue vig 0`

 => Navigation et Vigilance correspondent, c'est Navigation qui est
pris (premier dans l'ordre alphabétique), avec un message.
2021-03-25 00:15:08 +01:00
a802307dac Update release 2021-03-24 11:10:17 +01:00
260 changed files with 26208 additions and 7735 deletions

2
.gitignore vendored
View File

@ -1,5 +1,3 @@
.vscode/settings.json .vscode/settings.json
.idea
todo.txt todo.txt
todo.md todo.md
/.vscode

43
RdD.geany Normal file
View File

@ -0,0 +1,43 @@
[editor]
line_wrapping=false
line_break_column=72
auto_continue_multiline=true
[file_prefs]
final_new_line=true
ensure_convert_new_lines=false
strip_trailing_spaces=false
replace_tabs=false
[indentation]
indent_width=2
indent_type=0
indent_hard_tab_width=8
detect_indent=false
detect_indent_width=false
indent_mode=2
[project]
name=RdD
base_path=/home/morr/work/foundryvtt/foundryvtt-reve-de-dragon
description=
file_patterns=
[long line marker]
long_line_behaviour=1
long_line_column=72
[files]
current_page=8
FILE_NAME_0=9759;JSON;0;EUTF-8;0;1;0;%2Fhome%2Fmorr%2Fwork%2Ffoundryvtt%2Ffoundryvtt-reve-de-dragon%2Ftemplate.json;0;2
FILE_NAME_1=8120;CSS;0;EUTF-8;0;1;0;%2Fhome%2Fmorr%2Fwork%2Ffoundryvtt%2Ffoundryvtt-reve-de-dragon%2Fstyles%2Fsimple.css;0;2
FILE_NAME_2=19778;Javascript;0;EUTF-8;0;1;0;%2Fhome%2Fmorr%2Fwork%2Ffoundryvtt%2Ffoundryvtt-reve-de-dragon%2Fmodule%2Ftmr-utility.js;0;2
FILE_NAME_3=21106;Javascript;0;EUTF-8;0;1;0;%2Fhome%2Fmorr%2Fwork%2Ffoundryvtt%2Ffoundryvtt-reve-de-dragon%2Fmodule%2Factor.js;0;2
FILE_NAME_4=6228;Javascript;0;EUTF-8;0;1;0;%2Fhome%2Fmorr%2Fwork%2Ffoundryvtt%2Ffoundryvtt-reve-de-dragon%2Fmodule%2Factor-sheet.js;0;2
FILE_NAME_5=20083;HTML;0;EUTF-8;0;1;0;%2Fhome%2Fmorr%2Fwork%2Ffoundryvtt%2Ffoundryvtt-reve-de-dragon%2Ftemplates%2Factor-sheet.html;0;2
FILE_NAME_6=1312;Javascript;0;EUTF-8;0;1;0;%2Fhome%2Fmorr%2Fwork%2Ffoundryvtt%2Ffoundryvtt-reve-de-dragon%2Fmodule%2Frdd-tmr-dialog.js;0;2
FILE_NAME_7=1767;Javascript;0;EUTF-8;0;1;0;%2Fhome%2Fmorr%2Fwork%2Ffoundryvtt%2Ffoundryvtt-reve-de-dragon%2Fmodule%2Frdd-roll-dialog.js;0;2
FILE_NAME_8=266;None;0;EUTF-8;0;1;0;%2Fhome%2Fmorr%2Fwork%2Ffoundryvtt%2Ffoundryvtt-reve-de-dragon%2Fpacks%2Fqueues-de-dragon.db;0;2
[VTE]
last_dir=/home/sigmar

View File

@ -1,61 +0,0 @@
# Actor notes
> The Actor#getData default implementation gives you the following for use in sheet rendering:
```
actor -> the Actor instance
data -> a cloned copy of Actor#data
items -> a cloned copy of Actor#data#items
effects -> a cloned copy of Actor#data#effects
```
> if all you need is a safe copy of `Actor#data`, you'll be much better off by simply defining your own function and avoiding all the wasted work that the parent class does which will slow down your sheet
```js
getData(options) {
return {
data: foundry.utils.deepClone(this.object.data)
}
}
```
who knows, maybe you don't even need to copy your actor data, skip the copy and it's even faster:
```js
getData(options) {
return {
data: this.object.data
}
}
```
Atropos19/02/2021
There are two recommended ways to create owned items in 0.8.0:
```js
await Item.create(itemData, {parent: actor});
await actor.createEmbeddedDocuments("Item", itemDataArray);
```
You can update an embedded item in one of two ways:
```js
//Method 1:
const item = actor.items.get(itemId);
item.update(data);
//Method 2:
actor.updateEmbeddedDocuments("Item", [{_id: itemId, ...}]);
```
I noticed adding an ActiveEffect to an actor in code using
```js
this.createEmbeddedDocuments('ActiveEffect', [effet], options);
this.applyActiveEffects();
```
Atropos — Aujourdhui à 14:42
Two notes on this:
1. You don't actually need to call this.applyActiveEffects() because this will happen automatically whenever an effect is created/updated/deleted
2. If you want to suppress the automatic display of the sheet for the newly created document, you can pass options.renderSheet = false as part of your options object

BIN
fonts/goudyacc.woff Normal file

Binary file not shown.

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 17 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.2 KiB

59
icons/humanoides/cyan.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 12 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.8 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 29 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.3 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 13 KiB

59
icons/humanoides/ogre.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 18 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 16 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 8.9 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 10 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 387 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 382 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 372 KiB

File diff suppressed because it is too large Load Diff

After

Width:  |  Height:  |  Size: 368 KiB

130
icons/tmr/gift.svg Normal file
View File

@ -0,0 +1,130 @@
<?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"
version="1.1"
id="Capa_1"
x="0px"
y="0px"
width="512"
height="512"
viewBox="0 0 512 512"
xml:space="preserve"
sodipodi:docname="gift.svg"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"><metadata
id="metadata51"><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 /></cc:Work></rdf:RDF></metadata><defs
id="defs49" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="3840"
inkscape:window-height="2066"
id="namedview47"
showgrid="false"
inkscape:zoom="2.415894"
inkscape:cx="64"
inkscape:cy="163.34211"
inkscape:window-x="-11"
inkscape:window-y="-11"
inkscape:window-maximized="1"
inkscape:current-layer="g14"
inkscape:document-rotation="0" />
<g
id="g14"
transform="matrix(5.7,0,0,5.7,1.6591,1.6521435)">
<g
id="g24-9"
transform="matrix(0.1754386,0,0,0.1754386,3.2674006,3.2686582)"
style="fill:#ffffff;stroke:none"><path
d="m 81.245,212.419 c -9.902,13.127 -19.256,25.526 -8.273,47.079 4.957,9.729 18.132,11.771 28.311,11.771 20.904,0 45.125,-8.057 63.033,-19.182 -2.994,-3.719 -6.111,-8.237 -6.111,-13.949 0,-6.576 4.131,-11.571 7.451,-15.585 1.601,-1.936 3.415,-4.129 3.882,-5.569 0.523,-1.607 0.357,-4.439 0.197,-7.178 -0.299,-5.108 -0.67,-11.466 3.069,-16.605 2.653,-3.644 6.503,-5.517 10.286,-6.759 -3.608,-8.125 -8.398,-16.488 -14.204,-24.48 -14.902,-20.512 -32.983,-33.767 -46.06,-33.767 -2.845,0 -5.39,0.592 -7.78,1.81 -21.868,11.143 -21.404,26.636 -20.912,43.039 0.22,7.359 0.429,14.31 -1.603,20.561 -2.198,6.767 -6.612,12.619 -11.286,18.814 z"
id="path2"
style="fill:#ffffff;stroke:none" /><path
d="m 464.076,203.816 c -7.567,-14.789 -26.952,-17.893 -41.88,-17.893 -9.41,0 -19.295,1.161 -29.221,3.252 1.645,2.602 3.775,5.369 5.992,8.235 10.528,13.614 24.948,32.259 9.778,62.032 -5.735,11.255 -17.472,17.797 -34.132,19.144 4.004,3.046 7.514,6.264 10.369,9.608 7.716,9.035 10.98,18.948 9.44,28.668 -5.153,32.537 -27.667,39.408 -44.107,44.425 -2.622,0.8 -5.172,1.586 -7.547,2.43 17.125,17.508 34.971,27.756 49.438,27.756 4.384,0 8.483,-0.96 12.185,-2.855 32.102,-16.428 31.354,-39.981 30.631,-62.76 -0.318,-10.034 -0.619,-19.512 2.054,-27.791 2.912,-9.018 8.93,-17.024 15.301,-25.501 14.344,-19.083 27.892,-37.108 11.699,-68.75 z"
id="path4"
style="fill:#ffffff;stroke:none" /><path
d="m 270.444,394.702 c 2.878,0.456 5.642,0.687 8.214,0.687 18.176,0 25.863,-11.274 34.001,-23.211 4.148,-6.084 8.066,-11.83 13.384,-15.693 5.755,-4.182 12.766,-6.321 20.188,-8.587 15.727,-4.8 30.581,-9.333 34.364,-33.225 0.893,-5.63 -1.213,-11.479 -6.258,-17.386 -8.141,-9.532 -23.127,-18.049 -39.956,-23.652 -1.862,-0.538 -3.721,-1.116 -5.575,-1.729 -9.632,-2.772 -19.668,-4.561 -29.237,-5.027 0.292,5.036 0.549,11.19 -3.092,16.193 -3.771,5.18 -9.963,6.789 -14.938,8.081 -2.629,0.683 -5.348,1.389 -6.67,2.351 -1.28,0.933 -2.769,3.273 -4.207,5.537 -2.776,4.368 -6.232,9.804 -12.397,11.806 -1.511,0.491 -3.127,0.739 -4.804,0.739 -1.835,0 -3.626,-0.305 -5.359,-0.754 -3.383,17.09 -3.525,36.966 0.635,54.293 2.436,10.148 8.497,27.485 21.707,29.577 z"
id="path6"
style="fill:#ffffff;stroke:none" /><path
d="m 126.439,366.003 c -16.52,-4.826 -39.144,-11.435 -44.37,-44.438 -1.539,-9.719 1.725,-19.632 9.44,-28.667 2.257,-2.643 4.924,-5.206 7.915,-7.669 -19.207,-0.406 -32.657,-7.071 -38.927,-19.376 -14.955,-29.353 -0.779,-48.145 9.572,-61.866 1.457,-1.931 2.882,-3.822 4.177,-5.669 -8.438,-1.537 -16.798,-2.384 -24.81,-2.384 -15.076,0 -34.636,3.13 -42.2,18.042 -16.315,32.161 -1.866,50.776 12.108,68.778 6.156,7.931 11.971,15.422 14.674,23.692 2.944,9.006 2.782,19.021 2.61,29.623 -0.386,23.87 -0.751,46.416 30.949,62.497 3.678,1.866 7.743,2.811 12.085,2.811 15.828,0 35.7,-12.34 54.219,-33.068 -2.312,-0.8 -4.839,-1.546 -7.442,-2.306 z"
id="path8"
style="fill:#ffffff;stroke:none" /><path
d="m 276.172,62.189 c 12.786,0 24.223,5.22 34.962,15.96 9.115,9.115 11.603,22.92 7.36,39.616 9.602,-6.462 19.178,-9.98 27.922,-9.98 5.036,0 9.792,1.123 14.137,3.337 29.352,14.955 28.93,38.491 28.62,55.676 -0.036,2.032 -0.067,4.02 -0.056,5.943 13.727,-6.889 25.322,-15.114 32.853,-23.947 7.611,-8.928 10.762,-17.875 9.364,-26.592 C 425.63,86.594 402.997,80.027 381.11,73.676 371.468,70.879 362.361,68.236 355.314,63.135 347.636,57.578 341.881,49.38 335.789,40.701 324.269,24.291 312.358,7.323 285.965,7.323 c -3.748,0 -7.768,0.339 -11.947,1.009 -20.054,3.212 -28.987,28.625 -32.527,43.488 -1.487,6.242 -2.569,12.945 -3.271,19.898 3.292,-0.724 7.018,-2.048 10.899,-3.439 7.965,-2.855 16.995,-6.09 27.053,-6.09 z"
id="path10"
style="fill:#ffffff;stroke:none" /><path
d="m 80.254,180.726 c 0.028,-2.296 -0.039,-4.745 -0.114,-7.261 -0.516,-17.203 -1.222,-40.762 28.551,-55.932 4.345,-2.214 9.101,-3.336 14.136,-3.336 8.349,0 17.457,3.203 26.621,9.117 -6.331,-19.186 -4.373,-35.058 5.734,-45.165 10.691,-10.692 22.104,-15.89 34.887,-15.89 9.877,0 18.926,3.121 26.909,5.875 1.419,0.49 2.817,0.97 4.191,1.424 -0.685,-4.98 -1.561,-9.809 -2.666,-14.377 -3.594,-14.851 -12.618,-40.235 -32.683,-43.376 -4.124,-0.646 -8.094,-0.973 -11.801,-0.973 -26.95,0 -38.601,17.153 -49.868,33.742 -5.641,8.306 -10.969,16.151 -17.999,21.277 -7.655,5.583 -17.23,8.524 -27.367,11.638 -22.821,7.009 -44.376,13.629 -49.874,48.746 -1.361,8.696 1.798,17.605 9.392,26.48 9.129,10.667 24.272,20.436 41.951,28.011 z"
id="path12"
style="fill:#ffffff;stroke:none" /><path
d="m 328.161,374.443 c -1.295,1.753 -2.6,3.664 -3.935,5.621 -8.438,12.375 -19.993,29.324 -45.568,29.324 -3.304,0 -6.804,-0.289 -10.403,-0.859 -12.671,-2.006 -22.761,-11.63 -29.146,-27.494 -6.21,18.666 -16.992,30 -30.871,32.198 -3.581,0.567 -7.063,0.854 -10.349,0.854 -25.198,0 -36.474,-16.121 -45.533,-29.075 -1.561,-2.232 -3.085,-4.399 -4.611,-6.387 -2.519,4.654 -4.752,9.299 -6.633,13.862 -5.821,14.126 -13.439,39.965 0.946,54.3 11.86,11.818 23.598,17.323 36.938,17.323 11.172,0 21.87,-3.855 32.217,-7.584 9.445,-3.404 18.367,-6.619 27.066,-6.634 9.527,0 18.977,3.24 28.98,6.671 10.371,3.556 21.096,7.234 32.052,7.234 h 0.005 c 13.408,-0.002 25.147,-5.516 36.943,-17.354 14.313,-14.363 6.645,-40.121 0.8,-54.197 -2.432,-5.852 -5.439,-11.836 -8.898,-17.803 z"
id="path14"
style="fill:#ffffff;stroke:none" /><path
d="m 190.069,76.259 c -9.005,0 -16.944,3.746 -24.987,11.789 -9.459,9.458 -4.171,27.047 -0.177,36.69 7.686,18.555 21.693,36.525 36.309,48.605 2.38,-3.296 5.398,-6.483 9.806,-7.914 1.511,-0.491 3.127,-0.739 4.805,-0.739 4.22,0 8.227,1.567 11.763,2.949 2.6,1.016 5.287,2.067 7.057,2.067 1.77,0 4.457,-1.051 7.057,-2.067 3.535,-1.382 7.543,-2.948 11.762,-2.948 1.678,0 3.294,0.249 4.805,0.739 3.715,1.206 6.442,3.662 8.633,6.377 13.957,-12.04 27.143,-29.278 34.512,-47.07 3.994,-9.643 9.282,-27.231 -0.176,-36.69 -8.092,-8.091 -16.055,-11.859 -25.063,-11.859 -7.626,0 -15.102,2.679 -22.331,5.27 -6.931,2.484 -13.477,4.83 -20.049,4.83 -7.115,0 -14.044,-2.39 -21.379,-4.92 -7.286,-2.512 -14.816,-5.109 -22.347,-5.109 z"
id="path16"
style="fill:#ffffff;stroke:none" /><path
d="m 396.271,253.086 c 11.144,-21.87 1.661,-34.13 -8.379,-47.111 -4.504,-5.824 -8.758,-11.324 -10.789,-17.574 -2.199,-6.768 -2.067,-14.096 -1.928,-21.855 0.296,-16.44 0.575,-31.969 -20.978,-42.951 -2.392,-1.218 -4.936,-1.811 -7.781,-1.811 -13.076,0 -31.153,13.253 -46.055,33.763 -7.177,9.878 -12.801,20.322 -16.549,30.183 4.48,1.242 9.45,3.059 12.663,7.474 3.74,5.139 3.368,11.496 3.069,16.604 -0.16,2.739 -0.326,5.571 0.196,7.178 0.467,1.44 2.281,3.633 3.882,5.568 3.319,4.014 7.45,9.008 7.45,15.583 0,3.601 -1.241,6.724 -2.907,9.475 6.998,4.038 14.811,7.587 22.921,10.41 3.011,0.836 5.989,1.759 8.917,2.766 9.424,2.568 18.994,4.068 27.956,4.068 10.181,0.001 23.356,-2.041 28.312,-11.77 z"
id="path18"
style="fill:#ffffff;stroke:none" /><path
d="m 95.897,319.376 c 3.839,24.242 18.717,28.588 34.468,33.189 7.066,2.064 13.742,4.015 19.059,7.877 5.757,4.182 9.957,10.189 14.404,16.547 8.308,11.878 16.155,23.098 34.061,23.098 2.555,0 5.299,-0.229 8.159,-0.683 13.211,-2.092 19.271,-19.429 21.708,-29.577 4.71,-19.62 3.901,-42.504 -0.881,-60.914 -3.359,1.307 -7.109,2.672 -11.051,2.672 -1.678,0 -3.294,-0.249 -4.805,-0.739 -6.165,-2.001 -9.621,-7.438 -12.398,-11.805 -1.439,-2.264 -2.928,-4.605 -4.208,-5.538 -1.322,-0.962 -4.041,-1.668 -6.67,-2.351 -4.976,-1.292 -11.168,-2.9 -14.938,-8.08 -2.434,-3.342 -3.123,-7.199 -3.229,-10.893 -26.569,3.035 -54.982,15.244 -67.422,29.811 -5.043,5.908 -7.149,11.757 -6.257,17.386 z"
id="path20"
style="fill:#ffffff;stroke:none" /><path
d="m 246.796,295.599 c 2.499,0.978 5.084,1.988 6.664,1.988 0.204,0 0.37,-0.019 0.48,-0.055 1.376,-0.447 3.416,-3.657 4.906,-6.001 2.04,-3.21 4.354,-6.849 7.784,-9.346 3.469,-2.525 7.677,-3.618 11.388,-4.583 2.666,-0.692 6.317,-1.641 7.139,-2.768 0.79,-1.086 0.571,-4.821 0.411,-7.548 -0.225,-3.845 -0.48,-8.204 0.856,-12.32 1.292,-3.98 4.011,-7.267 6.41,-10.168 1.889,-2.283 4.238,-5.124 4.238,-6.661 0,-1.536 -2.351,-4.378 -4.238,-6.661 -2.399,-2.9 -5.118,-6.188 -6.41,-10.168 -1.336,-4.115 -1.081,-8.474 -0.856,-12.319 0.16,-2.728 0.379,-6.462 -0.412,-7.549 -0.82,-1.127 -4.471,-2.075 -7.137,-2.768 -3.712,-0.964 -7.918,-2.057 -11.388,-4.583 -3.432,-2.497 -5.745,-6.136 -7.786,-9.347 -1.489,-2.344 -3.529,-5.553 -4.904,-5.999 -0.11,-0.036 -0.276,-0.055 -0.48,-0.055 -1.58,0 -4.165,1.01 -6.665,1.988 -3.63,1.419 -7.745,3.027 -12.153,3.027 -4.408,0 -8.523,-1.609 -12.154,-3.028 -2.5,-0.978 -5.085,-1.988 -6.665,-1.988 -0.204,0 -0.371,0.019 -0.482,0.055 -1.375,0.446 -3.415,3.656 -4.904,5.999 -2.041,3.211 -4.355,6.85 -7.787,9.348 -3.47,2.525 -7.677,3.617 -11.389,4.581 -2.666,0.692 -6.317,1.64 -7.139,2.768 -0.79,1.086 -0.572,4.822 -0.413,7.549 0.225,3.845 0.48,8.203 -0.856,12.319 -1.293,3.98 -4.012,7.267 -6.41,10.167 -1.889,2.284 -4.239,5.126 -4.239,6.662 0,1.537 2.351,4.378 4.239,6.662 2.398,2.9 5.117,6.187 6.41,10.167 1.336,4.115 1.081,8.473 0.856,12.318 -0.159,2.728 -0.377,6.463 0.414,7.55 0.821,1.128 4.472,2.076 7.138,2.768 3.712,0.964 7.918,2.056 11.389,4.581 3.432,2.497 5.745,6.136 7.786,9.347 1.489,2.344 3.53,5.554 4.905,6.001 0.111,0.036 0.277,0.055 0.482,0.055 1.58,0 4.165,-1.011 6.666,-1.988 3.63,-1.419 7.745,-3.028 12.153,-3.028 4.408,0 8.523,1.612 12.153,3.031 z"
id="path22"
style="fill:#ffffff;stroke:none" /></g></g>
<g
id="g16">
</g>
<g
id="g18">
</g>
<g
id="g20">
</g>
<g
id="g22">
</g>
<g
id="g24">
</g>
<g
id="g26">
</g>
<g
id="g28">
</g>
<g
id="g30">
</g>
<g
id="g32">
</g>
<g
id="g34">
</g>
<g
id="g36">
</g>
<g
id="g38">
</g>
<g
id="g40">
</g>
<g
id="g42">
</g>
<g
id="g44">
</g>
</svg>

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 528 B

197
icons/tmr/pelerin.svg Normal file
View File

@ -0,0 +1,197 @@
<?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"
width="512"
height="512"
viewBox="0 0 135.46666 135.46667"
version="1.1"
id="svg878"
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)"
sodipodi:docname="pelerin.svg">
<defs
id="defs872">
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath1730">
<g
inkscape:label="Clip"
id="use1732"
style="fill:#d38d5f;stroke:#502d16">
<g
id="g1541"
transform="matrix(0.28980934,0,0,0.21909426,120.56466,-12.741092)"
style="display:inline;fill:#d38d5f;stroke:#502d16;stroke-width:2.16856">
<path
sodipodi:nodetypes="cccccc"
id="path1535"
d="m -174.5565,130.97253 h 15.40856 v 508.4827 l -7.70428,24 -7.70428,-24 z"
style="fill:#d38d5f;stroke:#502d16;stroke-width:2.16856" />
<path
transform="matrix(1.001146,0,0,0.893038,2.193524,15.82179)"
style="fill:#d38d5f;stroke:#502d16;stroke-width:2.29344"
d="m -145.09735,123.91028 c 0,13.11269 -10.64218,17.6523 -23.75487,17.6523 -13.11269,0 -23.75487,-4.53961 -23.75487,-17.6523 0,-13.11269 10.64218,-23.75487 23.75487,-23.75487 13.11269,0 23.75487,10.64218 23.75487,23.75487 z"
id="path1537"
sodipodi:nodetypes="csssc" />
<path
style="fill:#d38d5f;stroke:#502d16;stroke-width:2.16856"
d="m -146.94948,221.199 c 0,8.50553 -8.91642,12.68366 -19.90273,12.68366 -10.98631,0 -19.90273,-4.17813 -19.90273,-12.68366 0,-8.50553 8.91642,-9.95873 19.90273,-9.95873 10.98631,0 19.90273,1.4532 19.90273,9.95873 z"
id="path1539"
sodipodi:nodetypes="csssc" />
</g>
<g
style="display:inline;fill:#d38d5f;stroke:#502d16"
id="g1559"
transform="matrix(0.20847315,-0.03662954,0.03662954,0.20847315,-0.34176516,-0.20270665)">
<g
inkscape:label="Fond écu"
id="g1543"
style="fill:#d38d5f;stroke:#502d16" />
<g
style="opacity:1;fill:#d38d5f;stroke:#502d16"
inkscape:label="Meubles"
id="g1553">
<g
id="g1551"
transform="matrix(0.714908,0,0,0.756557,137.7704,128.4719)"
style="display:inline;fill:#d38d5f;fill-opacity:1;stroke:#502d16;stroke-width:2.71947;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<path
sodipodi:nodetypes="ccccc"
id="path1545"
d="m 160.08787,143.23938 39.92645,57.31251 39.53535,-57.31251 h -40.3837 z"
style="fill:#d38d5f;fill-opacity:1;fill-rule:evenodd;stroke:#502d16;stroke-width:2.71947;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccccccccccccccccccc"
id="path1547"
d="m 193.20453,145.31745 c -24.41443,20.15923 -49.98749,37.33861 -73.2768,58.5917 -6.37089,11.43876 -4.50952,20.09512 9.2768,25.68955 14.75917,-16.92275 18.76874,-17.90421 41.38418,-46.03566 -22.42258,29.55858 -41.45116,42.84434 -41.29043,46.09816 5.38114,19.66042 0.98803,22.70493 25.28125,31.0625 2.90109,-14.41044 25.62687,-63.19056 32.51802,-70.81345 -6.73696,8.18151 -29.75646,56.59527 -32.58052,71.37595 18.94602,17.92 18.75832,19.45149 44.6875,14.03125 l 0.375,-80.91001 0.375,80.91001 c 21.42445,5.42024 29.31401,4.7897 44.65625,-14.03125 -3.59166,-13.24549 -25.62533,-59.96461 -31.64832,-69.57405 4.75359,7.7904 26.43091,52.99484 31.61707,69.01155 18.88754,-8.35757 21.70202,-8.69924 25.28125,-31.0625 -1.0235,-6.998 -18.88266,-18.38043 -42.22262,-45.81545 23.11839,25.66768 42.65103,40.10972 42.31637,45.75295 15.18653,-6.16263 15.88219,-19.26899 8.92398,-28.52504 -25.17844,-18.14393 -47.18822,-37.47898 -72.36824,-56.58981 0,0 -4.64225,-4.09784 -6.93074,-3.0414 z"
style="fill:#d38d5f;fill-opacity:1;fill-rule:evenodd;stroke:#502d16;stroke-width:2.71947;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
id="path1549"
d="m 168.24779,168.92114 c 23.13397,11.51861 44.28729,9.17267 64.46537,0"
style="fill:#d38d5f;fill-opacity:1;fill-rule:evenodd;stroke:#502d16;stroke-width:2.71947;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
<g
inkscape:label="Reflet final"
id="g1555"
style="fill:#d38d5f;stroke:#502d16" />
<g
inkscape:label="Contour final"
id="g1557"
style="fill:#d38d5f;stroke:#502d16" />
</g>
</g>
</clipPath>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="0.35"
inkscape:cx="400"
inkscape:cy="560"
inkscape:document-units="mm"
inkscape:current-layer="svg878"
inkscape:document-rotation="0"
showgrid="false"
units="px"
inkscape:window-width="2073"
inkscape:window-height="997"
inkscape:window-x="114"
inkscape:window-y="114"
inkscape:window-maximized="0" />
<metadata
id="metadata875">
<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>
<g
id="g1510"
style="fill:#784421;stroke:#ffffff;image-rendering:auto"
transform="translate(-1.0583648,-3.7366014)">
<g
inkscape:label="Clip"
id="g1726"
style="fill:#784421;stroke:#ffffff">
<g
id="g3257"
transform="matrix(0.28980934,0,0,0.21909426,120.56466,-12.741092)"
style="display:inline;fill:#784421;stroke:#ffffff;stroke-width:2.16856">
<path
sodipodi:nodetypes="cccccc"
id="rect3250"
d="m -174.5565,130.97253 h 15.40856 v 508.4827 l -7.70428,24 -7.70428,-24 z"
style="fill:#784421;stroke:#ffffff;stroke-width:2.16856" />
<path
transform="matrix(1.001146,0,0,0.893038,2.193524,15.82179)"
style="fill:#784421;stroke:#ffffff;stroke-width:2.29344"
d="m -145.09735,123.91028 c 0,13.11269 -10.64218,17.6523 -23.75487,17.6523 -13.11269,0 -23.75487,-4.53961 -23.75487,-17.6523 0,-13.11269 10.64218,-23.75487 23.75487,-23.75487 13.11269,0 23.75487,10.64218 23.75487,23.75487 z"
id="path3252"
sodipodi:nodetypes="csssc" />
<path
style="fill:#784421;stroke:#ffffff;stroke-width:2.16856"
d="m -146.94948,221.199 c 0,8.50553 -8.91642,12.68366 -19.90273,12.68366 -10.98631,0 -19.90273,-4.17813 -19.90273,-12.68366 0,-8.50553 8.91642,-9.95873 19.90273,-9.95873 10.98631,0 19.90273,1.4532 19.90273,9.95873 z"
id="path3254"
sodipodi:nodetypes="csssc" />
</g>
<g
style="display:inline;fill:#784421;stroke:#ffffff"
id="g2066"
transform="matrix(0.20847315,-0.03662954,0.03662954,0.20847315,-0.34176516,-0.20270665)">
<g
inkscape:label="Fond écu"
id="g2068"
style="fill:#784421;stroke:#ffffff" />
<g
style="opacity:1;fill:#784421;stroke:#ffffff"
inkscape:label="Meubles"
id="g2070">
<g
id="g4219"
transform="matrix(0.714908,0,0,0.756557,137.7704,128.4719)"
style="display:inline;fill:#784421;fill-opacity:1;stroke:#ffffff;stroke-width:2.71947;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">
<path
sodipodi:nodetypes="ccccc"
id="path4221"
d="m 160.08787,143.23938 39.92645,57.31251 39.53535,-57.31251 h -40.3837 z"
style="fill:#784421;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.71947;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="ccccccccccccccccccccc"
id="path4223"
d="m 193.20453,145.31745 c -24.41443,20.15923 -49.98749,37.33861 -73.2768,58.5917 -6.37089,11.43876 -4.50952,20.09512 9.2768,25.68955 14.75917,-16.92275 18.76874,-17.90421 41.38418,-46.03566 -22.42258,29.55858 -41.45116,42.84434 -41.29043,46.09816 5.38114,19.66042 0.98803,22.70493 25.28125,31.0625 2.90109,-14.41044 25.62687,-63.19056 32.51802,-70.81345 -6.73696,8.18151 -29.75646,56.59527 -32.58052,71.37595 18.94602,17.92 18.75832,19.45149 44.6875,14.03125 l 0.375,-80.91001 0.375,80.91001 c 21.42445,5.42024 29.31401,4.7897 44.65625,-14.03125 -3.59166,-13.24549 -25.62533,-59.96461 -31.64832,-69.57405 4.75359,7.7904 26.43091,52.99484 31.61707,69.01155 18.88754,-8.35757 21.70202,-8.69924 25.28125,-31.0625 -1.0235,-6.998 -18.88266,-18.38043 -42.22262,-45.81545 23.11839,25.66768 42.65103,40.10972 42.31637,45.75295 15.18653,-6.16263 15.88219,-19.26899 8.92398,-28.52504 -25.17844,-18.14393 -47.18822,-37.47898 -72.36824,-56.58981 0,0 -4.64225,-4.09784 -6.93074,-3.0414 z"
style="fill:#784421;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.71947;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
<path
sodipodi:nodetypes="cc"
id="path4225"
d="m 168.24779,168.92114 c 23.13397,11.51861 44.28729,9.17267 64.46537,0"
style="fill:#784421;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:2.71947;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
</g>
</g>
<g
inkscape:label="Reflet final"
id="g2076"
style="fill:#784421;stroke:#ffffff" />
<g
inkscape:label="Contour final"
id="g2078"
style="fill:#784421;stroke:#ffffff" />
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 2.9 KiB

58
icons/tmr/scroll.svg Normal file
View File

@ -0,0 +1,58 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 511.999 511.999" style="enable-background:new 0 0 511.999 511.999;" xml:space="preserve">
<path style="fill:#CCAC68;" d="M145.179,371.239H95.282c-35.205,0-63.745,28.539-63.745,63.745l0,0
c0,35.205,28.539,63.745,63.745,63.745H266.31v-93.993L145.179,371.239z"/>
<path style="fill:#E6C275;" d="M356.848,140.762L154.642,13.272H90.44l0,0c-60.783,0-99.78,64.617-71.453,118.395l138.469,262.878
h-0.022c25.403,47.058-8.675,104.182-62.152,104.182h336.415c53.477,0,87.555-57.123,62.152-104.182L356.848,140.762z"/>
<path style="fill:#FFD782;" d="M90.44,13.272c35.205,0,63.745,28.54,63.745,63.745l0,0c0,35.205-28.54,63.745-63.745,63.745h266.408
c35.205,0,63.745-28.54,63.745-63.745l0,0c0-35.205-28.54-63.745-63.745-63.745C356.848,13.272,90.44,13.272,90.44,13.272z"/>
<path d="M342.963,489.153c0,0-195.544,0-195.559,0c1.764,0,6.043-5.742,7.172-6.989c17.747-19.618,25.167-48.132,18.443-73.982
c-2.737-10.522-8.091-19.987-13.121-29.534L27.455,127.206C15.728,104.945,16.489,78.792,29.49,57.25
c13.001-21.543,35.785-34.403,60.947-34.403c29.869,0,54.17,24.3,54.17,54.17s-24.3,54.17-54.17,54.17
c-5.289,0-9.575,4.286-9.575,9.576c0,5.289,4.286,9.575,9.575,9.575h260.695l31.745,58.803c2.512,4.655,8.318,6.387,12.973,3.877
c4.655-2.512,6.389-8.321,3.877-12.973l-27.694-51.301c33.163-7.016,58.129-36.507,58.129-71.729c0-40.429-32.892-73.32-73.32-73.32
H240.78c-5.289,0-9.575,4.286-9.575,9.575s4.286,9.575,9.575,9.575h116.063c29.869,0,54.17,24.3,54.17,54.17
c0,29.866-24.293,54.164-54.17,54.17H139.796c0.919-0.839,1.818-1.7,2.694-2.584c13.491-13.615,21.266-32.414,21.266-51.587
c0-20.045-8.544-39.648-23.128-53.374c-0.28-0.263-0.546-0.537-0.83-0.797h56.304c5.289,0,9.575-4.286,9.575-9.575
s-4.286-9.575-9.575-9.575c0,0-105.664,0-105.665,0c-31.931,0-60.842,16.32-77.341,43.658
c-16.498,27.337-17.463,60.524-2.581,88.774l118.798,225.535H95.277c-40.428,0-73.32,32.891-73.32,73.32s32.892,73.32,73.32,73.32
c0.027,0,0.052-0.001,0.078-0.001h247.609c5.289,0,9.575-4.286,9.575-9.575S348.252,489.153,342.963,489.153z M41.107,434.984
c0-29.869,24.3-54.17,54.17-54.17h44.118c3.82,7.251,8.046,14.427,11.417,21.9c3.922,8.533,5.779,17.635,5.584,26.694
c-0.706,32.866-28.393,59.744-61.136,59.744C65.399,489.146,41.107,464.848,41.107,434.984z"/>
<path d="M502.27,389.999l-78.422-145.272c-2.514-4.655-8.322-6.389-12.973-3.877c-4.655,2.512-6.389,8.321-3.877,12.973
l78.423,145.272c10.312,19.103,9.829,41.639-1.293,60.283c-11.123,18.645-30.724,29.776-52.434,29.776h-44.048
c-5.289,0-9.575,4.286-9.575,9.575s4.286,9.575,9.575,9.575h44.048c28.52,0,54.269-14.622,68.88-39.114
C515.184,444.697,515.818,415.093,502.27,389.999z"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 496 496" style="enable-background:new 0 0 496 496;" xml:space="preserve">
<path style="fill:#5B402E;" d="M0,232v167.2C0,460.8,52,456,113.6,456h268c61.6,0,113.6,4.8,113.6-56.8V232H0z"/>
<path style="fill:#493322;" d="M112,456h270.4c61.6,0,113.6,4.8,113.6-56.8V232"/>
<path style="fill:#5B402E;" d="M496,192v-40c0-61.6-52-112-113.6-112H113.6C52,40,0,90.4,0,152v40H496z"/>
<path style="fill:#493322;" d="M0,152v40h496v-40c0-61.6-52-112-113.6-112"/>
<rect y="232" style="fill:#F2B111;" width="496" height="64"/>
<polyline style="fill:#E88813;" points="0,296 496,296 496,232 "/>
<rect y="152" style="fill:#F2B111;" width="496" height="40"/>
<g>
<polyline style="fill:#E88813;" points="0,192 496,192 496,152 "/>
<rect x="104" y="32" style="fill:#E88813;" width="56" height="152"/>
<rect x="336" y="32" style="fill:#E88813;" width="56" height="152"/>
<rect x="104" y="288" style="fill:#E88813;" width="56" height="176"/>
<rect x="336" y="288" style="fill:#E88813;" width="56" height="176"/>
</g>
<g>
<circle style="fill:#493322;" cx="184" cy="264.8" r="8.8"/>
<circle style="fill:#493322;" cx="226.4" cy="264.8" r="8.8"/>
<circle style="fill:#493322;" cx="269.6" cy="264.8" r="8.8"/>
<circle style="fill:#493322;" cx="312" cy="264.8" r="8.8"/>
<circle style="fill:#493322;" cx="33.6" cy="264.8" r="8.8"/>
<circle style="fill:#493322;" cx="75.2" cy="264.8" r="8.8"/>
<circle style="fill:#493322;" cx="420" cy="264.8" r="8.8"/>
<circle style="fill:#493322;" cx="462.4" cy="264.8" r="8.8"/>
</g>
<path style="fill:#F2B111;" d="M276,346.4c0-15.2-12.8-28-28-28s-28,12.8-28,28c0,10.4,5.6,20,13.6,25.6l-8,52h44.8l-8-52
C270.4,367.2,276,356.8,276,346.4z"/>
<path style="fill:#E88813;" d="M270.4,424l-8-52c8-4.8,13.6-15.2,13.6-25.6c0-15.2-12.8-28-28-28s-28,12.8-28,28"/>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

94
icons/tmr/wave.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1,44 +0,0 @@
{
"ACTOR": {
"TypePersonnage": "Personnage",
"TypeCreature": "Créature",
"TypeEntite": "Entité de cauchemar",
"TypeVehicule": "Véhicule"
},
"ITEM": {
"TypeObjet": "Objet",
"TypeCompetence": "Compétence",
"TypeCompetencecreature": "Compétence de créature",
"TypeMaladie": "Maladie",
"TypePoison": "Poison",
"TypeNombreastral": "Nombre astral",
"TypeTarot": "Carte de tarot",
"TypeCasetmr": "TMR spéciale",
"TypeRencontrestmr": "Rencontre TMR",
"TypeMunition": "Munition",
"TypeMonnaie": "Monnaie",
"TypeHerbe": "Herbe ou plante",
"TypeIngredient": "Ingrédient",
"TypeLivre": "Livre",
"TypePotion": "Potion",
"TypeArme": "Arme",
"TypeArmure": "Armure",
"TypeConteneur": "Conteneur",
"TypeNourritureboisson": "Nourriture & boisson",
"TypeChant": "Chant",
"TypeDanse": "Danse",
"TypeMusique": "Musique",
"TypeOeuvre": "Oeuvre",
"TypeTache": "Tâche",
"TypeJeu": "Jeu",
"TypeRecettealchimique": "Recette alchimique",
"TypeRecettecuisine": "Recette de cuisine",
"TypeSort": "Sort",
"TypeMeditation": "Méditation",
"TypeSignedraconique": "Signe draconique",
"TypeQueue": "Queue de Dragon",
"TypeOmbre": "Ombre de Thanatos",
"TypeSouffle": "Souffle de Dragon",
"TypeTete": "Tête de Dragon"
}
}

View File

@ -35,10 +35,12 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(), encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
} }
formData.calc.surEncombrementMessage = (formData.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : ""; formData.calc.surEncombrementMessage = (formData.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : "";
formData.options.isGM = game.user.isGM;
formData.data.competencecreature = formData.itemsByType["competencecreature"];
RdDUtility.filterItemsPerTypeForSheet(formData); RdDUtility.filterItemsPerTypeForSheet(formData);
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets); RdDUtility.buildArbreDeConteneur(this, formData);
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
console.log("Creature : ", this.objetVersConteneur, formData); console.log("Creature : ", this.objetVersConteneur, formData);
@ -70,6 +72,17 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
}); });
} }
/* -------------------------------------------- */
/** @override */
setPosition(options = {}) {
const position = super.setPosition(options);
const sheetBody = this.element.find(".sheet-body");
const bodyHeight = position.height - 192;
sheetBody.css("height", bodyHeight);
return position;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
_updateObject(event, formData) { _updateObject(event, formData) {

View File

@ -5,7 +5,6 @@
import { HtmlUtility } from "./html-utility.js"; import { HtmlUtility } from "./html-utility.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDUtility } from "./rdd-utility.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDActorEntiteSheet extends ActorSheet { export class RdDActorEntiteSheet extends ActorSheet {
@ -32,27 +31,14 @@ export class RdDActorEntiteSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
const objectData = Misc.data(this.object); let formData = super.getData();
let formData = {
title: this.title, formData.itemsByType = Misc.classify(formData.items);
id: objectData.id,
type: objectData.type,
img: objectData.img,
name: objectData.name,
// actor: this.object,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
data: foundry.utils.deepClone(Misc.templateData(this.object)),
effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)),
// items: items,
limited: this.object.limited,
options: this.options,
owner: this.document.isOwner,
itemsByType: Misc.classify(this.object.items.map(i => foundry.utils.deepClone(i.data))),
};
formData.options.isGM = game.user.isGM; formData.options.isGM = game.user.isGM;
RdDUtility.filterItemsPerTypeForSheet(formData);
formData.data.carac.taille.isTaille = true; // To avoid button link;
formData.data.competencecreature = formData.itemsByType["competencecreature"];
return formData; return formData;
@ -71,14 +57,14 @@ export class RdDActorEntiteSheet extends ActorSheet {
// Update Inventory Item // Update Inventory Item
html.find('.item-edit').click(ev => { html.find('.item-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
const item = this.actor.getEmbeddedDocument('Item', li.data("itemId")); const item = this.actor.getOwnedItem(li.data("itemId"));
item.sheet.render(true); item.sheet.render(true);
}); });
// Delete Inventory Item // Delete Inventory Item
html.find('.item-delete').click(ev => { html.find('.item-delete').click(ev => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
this.actor.deleteEmbeddedDocuments('Item', [li.data("itemId")]); this.actor.deleteOwnedItem(li.data("itemId"));
li.slideUp(200, () => this.render(false)); li.slideUp(200, () => this.render(false));
}); });
@ -117,7 +103,7 @@ export class RdDActorEntiteSheet extends ActorSheet {
this.render(true); this.render(true);
}); });
html.find('.encaisser-direct').click(ev => { html.find('#encaisser-direct').click(ev => {
this.actor.encaisser(); this.actor.encaisser();
}); });
@ -132,12 +118,10 @@ export class RdDActorEntiteSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
setPosition(options = {}) { setPosition(options={}) {
const position = super.setPosition(options); const position = super.setPosition(options);
const sheetHeader = this.element.find(".sheet-header");
const sheetTabs = this.element.find(".sheet-tabs");
const sheetBody = this.element.find(".sheet-body"); const sheetBody = this.element.find(".sheet-body");
const bodyHeight = position.height - sheetHeader[0].clientHeight - sheetTabs[0].clientHeight; const bodyHeight = position.height - 192;
sheetBody.css("height", bodyHeight); sheetBody.css("height", bodyHeight);
return position; return position;
} }

View File

@ -11,9 +11,6 @@ import { RdDBonus } from "./rdd-bonus.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDCombatManager } from "./rdd-combat.js"; import { RdDCombatManager } from "./rdd-combat.js";
import { RdDCarac } from "./rdd-carac.js"; import { RdDCarac } from "./rdd-carac.js";
import { RdDItem } from "./item.js";
import { DialogSplitItem } from "./dialog-split-item.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDActorSheet extends ActorSheet { export class RdDActorSheet extends ActorSheet {
@ -30,55 +27,60 @@ export class RdDActorSheet extends ActorSheet {
dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }], dragDrop: [{ dragSelector: ".item-list .item", dropSelector: null }],
editCaracComp: false, editCaracComp: false,
showCompNiveauBase: false, showCompNiveauBase: false,
montrerArchetype: false, montrerArchetype: false
hideControls: true
}); });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
const objectData = Misc.data(this.object); let formData = super.getData();
// -------------- version 0.7.9
// let formData = {
// cssClass: this.entity.owner ? "editable" : "locked",
// editable: this.isEditable,
// entity: duplicate(this.entity.data),
// limited: this.entity.limited,
// options: this.options,
// owner: this.entity.owner,
// title: this.title
// }
// // Entity data
// formData.actor = formData.entity;
// formData.data = formData.entity.data;
//this.actor.checkMonnaiePresence(this.actor.data.items); // Always check // // Owned items
// formData.items = formData.actor.items;
let formData = { // formData.items.sort((a, b) => (a.sort || 0) - (b.sort || 0));
title: this.title,
id: objectData.id,
type: objectData.type,
img: objectData.img,
name: objectData.name,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
data: foundry.utils.deepClone(Misc.templateData(this.object)),
effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)),
limited: this.object.limited,
options: this.options,
owner: this.document.isOwner,
itemsByType: Misc.classify(this.object.items.map(i => foundry.utils.deepClone(i.data))),
};
formData.itemsByType = Misc.classify(formData.items);
RdDUtility.filterItemsPerTypeForSheet(formData); RdDUtility.filterItemsPerTypeForSheet(formData);
formData.options.isGM = game.user.isGM; formData.options.isGM = game.user.isGM;
if (formData.type == 'creature') return formData; // Shortcut // la taille est la taille: on ne peut pas l'utiliser pour un jet
formData.data.carac.taille.isTaille = true;
formData.competenceByCategory = Misc.classify(formData.competences, it => it.data.categorie); if (this.actor.data.type == 'creature') return formData; // Shortcut
formData.competenceByCategory = Misc.classify(formData.data.competences, it => it.data.categorie);
formData.calc = { formData.calc = {
comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.competences), comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.data.competences),
competenceXPTotal: RdDItemCompetence.computeTotalXP(formData.competences), competenceXPTotal: RdDItemCompetence.computeTotalXP(formData.data.competences),
caracTotal: RdDCarac.computeTotal(formData.data.carac, formData.data.beaute), caracTotal: RdDCarac.computeTotal(formData.data.carac, formData.data.beaute),
// Mise à jour de l'encombrement total et du prix de l'équipement // Mise à jour de l'encombrement total et du prix de l'équipement
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(), encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
prixTotalEquipement: this.actor.computePrixTotalEquipement(), prixTotalEquipement: await this.actor.computePrixTotalEquipement(),
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr, surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
fatigue: RdDUtility.calculFatigueHtml(formData.data.sante.fatigue.value, formData.data.sante.endurance.max), fatigue: {
malus: RdDUtility.calculMalusFatigue(formData.data.sante.fatigue.value, formData.data.sante.endurance.max),
html: "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(formData.data.sante.fatigue.value, formData.data.sante.endurance.max).html() + "</table>"
},
resumeBlessures: this.actor.computeResumeBlessure(formData.data.blessures), resumeBlessures: this.actor.computeResumeBlessure(formData.data.blessures),
}; };
formData.calc.surEncombrementMessage = (formData.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : ""; formData.calc.surEncombrementMessage = (formData.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : "";
formData.competences.forEach(item => { formData.data.competences.forEach(item => {
item.visible = !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(item); item.visible = !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(item);
RdDItemCompetence.levelUp(item); RdDItemCompetence.levelUp(item);
}); });
@ -89,29 +91,36 @@ export class RdDActorSheet extends ActorSheet {
// toujours avoir une liste d'armes (pour mettre esquive et corps à corps) // toujours avoir une liste d'armes (pour mettre esquive et corps à corps)
formData.combat = duplicate(formData.armes ?? []); formData.data.combat = duplicate(formData.itemsByType.arme ?? []);
RdDItemArme.computeNiveauArmes(formData.combat, formData.competences); RdDItemArme.computeNiveauArmes(formData.data.combat, formData.data.competences);
RdDItemArme.ajoutCorpsACorps(formData.combat, formData.competences, formData.data.carac); RdDItemArme.ajoutCorpsACorps(formData.data.combat, formData.data.competences, formData.data.carac );
formData.esquive = RdDItemCompetence.getEsquive(formData.competences); formData.esquive = RdDItemCompetence.getEsquive(formData.data.competences);
formData.combat = RdDCombatManager.finalizeArmeList(formData.combat, formData.competences, formData.data.carac); formData.data.combat = RdDCombatManager.finalizeArmeList(formData.data.combat, formData.itemsByType.competence, formData.data.carac);
this.armesList = formData.combat;
this.armesList = formData.data.combat;
// Mise à jour de l'encombrement total et du prix de l'équipement
// Common data // Common data
formData.data.competenceByCategory = formData.competenceByCategory;
formData.data.isGM = game.user.isGM;
formData.ajustementsConditions = CONFIG.RDD.ajustementsConditions; formData.ajustementsConditions = CONFIG.RDD.ajustementsConditions;
formData.difficultesLibres = CONFIG.RDD.difficultesLibres; formData.difficultesLibres = CONFIG.RDD.difficultesLibres;
formData.hautreve = { // low is normal, this the base used to compute the grid.
isDemiReve: this.actor.listeEffets( it => it.label == "Demi-rêve").length > 0, formData.data.fatigue = {
sortsReserve: formData.data.reve.reserve.list, malus: RdDUtility.calculMalusFatigue(formData.data.sante.fatigue.value, formData.data.sante.endurance.max),
rencontres: duplicate(formData.data.reve.rencontre.list), html: "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(formData.data.sante.fatigue.value, formData.data.sante.endurance.max).html() + "</table>"
casesTmr: formData.itemsByType.casetmr,
cacheTMR: this.actor.isTMRCache()
} }
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets); formData.hautreve = {
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs); sortsReserve: formData.data.reve.reserve.list,
rencontres: duplicate(formData.data.reve.rencontre.list),
casesTmr: formData.itemsByType.casetmr
}
RdDUtility.buildArbreDeConteneur(this, formData);
formData.subacteurs = { formData.subacteurs = {
vehicules: this.actor.listeVehicules(), vehicules: this.actor.listeVehicules(),
montures: this.actor.listeMontures(), montures: this.actor.listeMontures(),
@ -129,196 +138,221 @@ export class RdDActorSheet extends ActorSheet {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onDropActor(event, dragData) { async _onDrop(event) {
console.log("DRAG", this.actor.id, dragData); let toSuper = await RdDUtility.processItemDropEvent(this, event);
this.actor.addSubacteur(dragData.id || dragData.data._id); if (toSuper) {
super._onDropActor(event, dragData); super._onDrop(event);
} }
/* -------------------------------------------- */
async _onDropItem(event, dragData) {
const callSuper = await this.actor.processDropItem(event, dragData, this.objetVersConteneur);
if (callSuper) {
await super._onDropItem(event, dragData)
}
}
/* -------------------------------------------- */
async createItem(name, type) {
await this.actor.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async createEmptyTache() { async createEmptyTache() {
await this.createItem('Nouvelle tache', 'tache'); await this.actor.createOwnedItem({ name: 'Nouvelle tache', type: 'tache' }, { renderSheet: true });
} }
/* -------------------------------------------- */ /** @override */ /* -------------------------------------------- */
async creerObjet() {
let itemType = $(".item-type").val();
await this.actor.createOwnedItem({ name: 'Nouveau ' + itemType, type: itemType }, { renderSheet: true });
}
/* -------------------------------------------- */
async selectObjetType() {
let typeObjets = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "monnaie"];
let options = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
for (let typeName of typeObjets) {
options += `<option value="${typeName}">${typeName}</option>`
}
options += '</select>';
let d = new Dialog({
title: "Créer un équipement",
content: options,
buttons: {
one: {
icon: '<i class="fas fa-check"></i>',
label: "Créer l'objet",
callback: () => this.creerObjet()
}
}
});
d.render(true);
}
/* -------------------------------------------- */
async selectTypeOeuvre() {
let typeOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu" ];
let options = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`;
for (let typeName of typeOeuvres) {
options += `<option value="${typeName}">${typeName}</option>`
}
options += '</select>';
let d = new Dialog({
title: "Créer une oeuvre",
content: options,
buttons: {
one: {
icon: '<i class="fas fa-check"></i>',
label: "Créer l'oeuvre",
callback: () => this.creerObjet()
}
}
});
d.render(true);
}
/* -------------------------------------------- */
/** @override */
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM); HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
HtmlUtility._showControlWhen($(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
html.find('#show-hide-competences').click((event) => {
this.options.showCompNiveauBase = !this.options.showCompNiveauBase;
this.render(true);
});
// Everything below here is only needed if the sheet is editable // Everything below here is only needed if the sheet is editable
if (!this.options.editable) return; if (!this.options.editable) return;
html.find('.item-split').click(async event => { html.find('.item-edit').click(ev => {
const li = $(event.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
const item = this.actor.items.get(li.data("item-id")); const item = this.actor.getOwnedItem(li.data("item-id"));
this.splitItem(item);
});
html.find('.item-edit').click(async event => {
const li = $(event.currentTarget).parents(".item");
const item = this.actor.items.get(li.data("item-id"));
item.sheet.render(true); item.sheet.render(true);
}); });
html.find('.display-label a').click(async event => { // Update Inventory Item
let myID = event.currentTarget.attributes['data-item-id'].value; html.find('.rencontre-delete').click(ev => {
const item = this.actor.getEmbeddedDocument('Item', myID); const li = $(ev.currentTarget).parents(".item");
item.sheet.render(true);
});
html.find('.rencontre-delete').click(async event => {
const li = $(event.currentTarget).parents(".item");
const rencontreKey = li.data("item-id"); const rencontreKey = li.data("item-id");
this.actor.deleteTMRRencontre(rencontreKey); this.actor.deleteTMRRencontre(rencontreKey);
}); });
html.find('.item-delete').click(async event => {
const li = $(event.currentTarget).parents(".item"); // Delete Inventory Item
html.find('.item-delete').click(ev => {
const li = $(ev.currentTarget).parents(".item");
RdDUtility.confirmerSuppression(this, li); RdDUtility.confirmerSuppression(this, li);
}); });
html.find('.item-vendre').click(async event => { html.find('.subacteur-delete').click(ev => {
const li = $(event.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
const itemId = li.data("item-id");
const item = this.actor.getObjet(itemId);
item?.proposerVente();
});
html.find('.item-action').click(async event => {
const li = $(event.currentTarget).parents(".item");
const itemId = li.data("item-id");
const item = this.actor.getObjet(itemId);
this.actor.actionItem(item);
});
html.find('.subacteur-delete').click(async event => {
const li = $(event.currentTarget).parents(".item");
RdDUtility.confirmerSuppressionSubacteur(this, li); RdDUtility.confirmerSuppressionSubacteur(this, li);
}); });
html.find('.encaisser-direct').click(async event => { html.find('#encaisser-direct').click(ev => {
this.actor.encaisser(); this.actor.encaisser();
}); });
html.find('.remise-a-neuf').click(async event => { html.find('.remise-a-neuf').click(ev => {
if (game.user.isGM) { if (game.user.isGM) {
this.actor.remiseANeuf(); this.actor.remiseANeuf();
ev.preventDefault();
} }
}); });
html.find('.creer-tache').click(async event => { html.find('.creer-tache').click(ev => {
this.createEmptyTache(); this.createEmptyTache();
}); });
html.find('.creer-un-objet').click(async event => { html.find('.creer-un-objet').click(ev => {
RdDUtility.selectObjetType( this ); this.selectObjetType();
}); });
html.find('.creer-une-oeuvre').click(async event => { html.find('.creer-une-oeuvre').click(ev => {
RdDUtility.selectTypeOeuvre(this); this.selectTypeOeuvre();
}); });
html.find('#nettoyer-conteneurs').click(async event => { html.find('#nettoyer-conteneurs').click(ev => {
this.actor.nettoyerConteneurs(); this.actor.nettoyerConteneurs();
}); });
// Blessure control // Blessure control
html.find('.blessure-control').click(async event => { html.find('.blessure-control').click(ev => {
const tr = $(event.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
let btype = tr.data("blessure-type"); let btype = li.data("blessure-type");
let index = tr.data('blessure-index'); let index = li.data('blessure-index');
let active = $(event.currentTarget).data('blessure-active'); let active = $(ev.currentTarget).data('blessure-active');
//console.log(btype, index, active); //console.log(btype, index, active);
await this.actor.manageBlessureFromSheet(btype, index, active); this.actor.manageBlessureFromSheet(btype, index, active).then(this.render(true));
}); });
// Blessure data // Blessure data
html.find('.blessures-soins').change(async event => { html.find('.blessures-soins').change(ev => {
const tr = $(event.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
let btype = tr.data('blessure-type'); let btype = li.data('blessure-type');
let index = tr.data('blessure-index'); let index = li.data('blessure-index');
let psoins = tr.find('.blessure-premiers_soins').val(); let psoins = li.find('input[name=premiers_soins]').val();
let pcomplets = tr.find('.blessure-soins_complets').val(); let pcomplets = li.find('input[name=soins_complets]').val();
let jours = tr.find('.blessure-jours').val(); let jours = li.find('input[name=jours]').val();
let loc = tr.find('.blessure-localisation').val(); let loc = li.find('input[name=localisation]').val();
//console.log(btype, index, psoins, pcomplets, jours, loc); //console.log(btype, index, psoins, pcomplets, jours, loc);
await this.actor.setDataBlessureFromSheet(btype, index, psoins, pcomplets, jours, loc); this.actor.setDataBlessureFromSheet(btype, index, psoins, pcomplets, jours, loc).then(this.render(true));
}); });
// Equip Inventory Item // Equip Inventory Item
html.find('.item-equip').click(async event => { html.find('.item-equip').click(ev => {
const li = $(event.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
this.actor.equiperObjet(li.data("item-id")); this.actor.equiperObjet(li.data("item-id"));
this.render(true);
}); });
// Roll Carac // Roll Carac
html.find('.carac-label a').click(async event => { html.find('.carac-label a').click((event) => {
let caracName = event.currentTarget.attributes.name.value; let caracName = event.currentTarget.attributes.name.value;
this.actor.rollCarac(caracName.toLowerCase()); this.actor.rollCarac(caracName.toLowerCase());
}); });
html.find('.chance-actuelle').click(async event => { html.find('.chance-actuelle').click((event) => {
this.actor.rollCarac('chance-actuelle'); this.actor.rollCarac('chance-actuelle');
}); });
html.find('.chance-appel').click(async event => { html.find('.chance-appel').click((event) => {
this.actor.rollAppelChance(); this.actor.rollAppelChance();
}); });
html.find('#jet-astrologie').click(async event => { html.find('#jet-astrologie').click((event) => {
this.actor.astrologieNombresAstraux(); this.actor.astrologieNombresAstraux();
}); });
// Roll Skill // Roll Skill
html.find('a.competence-label').click(async event => { html.find('.competence-label a').click((event) => {
let compName = event.currentTarget.name; let compName = event.currentTarget.text;
this.actor.rollCompetence(compName); this.actor.rollCompetence(compName);
}); });
html.find('.tache-label a').click(async event => { html.find('.tache-label a').click((event) => {
const li = $(event.currentTarget).parents(".item"); const li = $(event.currentTarget).parents(".item");
let tacheId = li.data('item-id'); let tacheId = li.data('item-id');
this.actor.rollTache(tacheId); this.actor.rollTache(tacheId);
}); });
html.find('.meditation-label a').click(async event => { html.find('.meditation-label a').click((event) => {
const li = $(event.currentTarget).parents(".item"); const li = $(event.currentTarget).parents(".item");
let meditationId = li.data('item-id'); let meditationId = li.data('item-id');
this.actor.rollMeditation(meditationId); this.actor.rollMeditation(meditationId);
}); });
html.find('.chant-label a').click(async event => { html.find('.chant-label a').click((event) => {
const li = $(event.currentTarget).parents(".item"); const li = $(event.currentTarget).parents(".item");
let chantId = li.data('item-id'); let chantId = li.data('item-id');
this.actor.rollChant(chantId); this.actor.rollChant(chantId);
}); });
html.find('.danse-label a').click(async event => { html.find('.danse-label a').click((event) => {
const li = $(event.currentTarget).parents(".item"); const li = $(event.currentTarget).parents(".item");
let danseId = li.data('item-id'); let danseId = li.data('item-id');
this.actor.rollDanse(danseId); this.actor.rollDanse(danseId);
}); });
html.find('.musique-label a').click(async event => { html.find('.musique-label a').click((event) => {
const li = $(event.currentTarget).parents(".item"); const li = $(event.currentTarget).parents(".item");
let musiqueId = li.data('item-id'); let musiqueId = li.data('item-id');
this.actor.rollMusique(musiqueId); this.actor.rollMusique(musiqueId);
}); });
html.find('.oeuvre-label a').click(async event => { html.find('.oeuvre-label a').click((event) => {
const li = $(event.currentTarget).parents(".item"); const li = $(event.currentTarget).parents(".item");
let oeuvreId = li.data('item-id'); let oeuvreId = li.data('item-id');
this.actor.rollOeuvre(oeuvreId); this.actor.rollOeuvre(oeuvreId);
}); });
html.find('.jeu-label a').click(async event => { html.find('.jeu-label a').click((event) => {
const li = $(event.currentTarget).parents(".item"); const li = $(event.currentTarget).parents(".item");
let jeuId = li.data('item-id'); let jeuId = li.data('item-id');
this.actor.rollJeu(jeuId); this.actor.rollJeu(jeuId);
}); });
html.find('.recettecuisine-label a').click(async event => { html.find('.recettecuisine-label a').click((event) => {
const li = $(event.currentTarget).parents(".item"); const li = $(event.currentTarget).parents(".item");
let recetteId = li.data('item-id'); let recetteId = li.data('item-id');
this.actor.rollRecetteCuisine(recetteId); this.actor.rollRecetteCuisine(recetteId);
}); });
html.find('.subacteur-label a').click(async event => { html.find('.subacteur-label a').click((event) => {
const li = $(event.currentTarget).parents(".item"); const li = $(event.currentTarget).parents(".item");
let actorId = li.data('actor-id'); let actorId = li.data('actor-id');
let actor = game.actors.get(actorId); let actor = game.actors.get(actorId);
@ -327,27 +361,19 @@ export class RdDActorSheet extends ActorSheet {
} }
}); });
// Boutons spéciaux MJs
html.find('.forcer-tmr-aleatoire').click(async event => {
this.actor.cacheTMRetMessage();
});
html.find('.afficher-tmr').click(async event => {
this.actor.afficheTMRetMessage();
});
// Points de reve actuel // Points de reve actuel
html.find('.ptreve-actuel a').click(async event => { html.find('.ptreve-actuel a').click((event) => {
this.actor.rollCarac('reve-actuel'); this.actor.rollCarac('reve-actuel');
}); });
// Roll Weapon1 // Roll Weapon1
html.find('.arme-label a').click(async event => { html.find('.arme-label a').click((event) => {
let armeName = event.currentTarget.text; let armeName = event.currentTarget.text;
let competenceName = event.currentTarget.attributes['data-competence-name'].value; let competenceName = event.currentTarget.attributes['data-competence-name'].value;
this.actor.rollArme(competenceName, armeName); this.actor.rollArme(competenceName, armeName);
}); });
// Initiative pour l'arme // Initiative pour l'arme
html.find('.arme-initiative a').click(async event => { html.find('.arme-initiative a').click((event) => {
let combatant = game.combat.data.combatants.find(c => c.actor.data._id == this.actor.data._id); let combatant = game.combat.data.combatants.find(c => c.actor.data._id == this.actor.data._id);
if (combatant) { if (combatant) {
let armeName = event.currentTarget.attributes['data-arme-name'].value; let armeName = event.currentTarget.attributes['data-arme-name'].value;
@ -358,178 +384,201 @@ export class RdDActorSheet extends ActorSheet {
} }
}); });
// Display TMR, visuualisation // Display TMR, visuualisation
html.find('.visu-tmr').click(async event => { html.find('#visu-tmr').click((event) => {
this.actor.displayTMR("visu"); this.actor.displayTMR("visu");
}); });
// Display TMR, normal // Display TMR, normal
html.find('.monte-tmr').click(async event => { html.find('#monte-tmr').click((event) => {
this.actor.displayTMR("normal"); this.actor.displayTMR("normal");
}); });
// Display TMR, fast // Display TMR, fast
html.find('.monte-tmr-rapide').click(async event => { html.find('#monte-tmr-rapide').click((event) => {
this.actor.displayTMR("rapide"); this.actor.displayTMR("rapide");
}); });
html.find('.dormir-une-heure').click(async event => { html.find('#dormir-une-heure').click((event) => {
this.actor.dormir(1); this.actor.dormir(1);
}); });
html.find('.dormir-chateau-dormant').click(async event => { html.find('#dormir-chateau-dormant').click((event) => {
this.actor.dormirChateauDormant(); this.actor.dormirChateauDormant();
}); });
html.find('.enlever-tous-effets').click(async event => { html.find('#enlever-tous-effets').click((event) => {
this.actor.enleverTousLesEffets(); this.actor.enleverTousLesEffets();
}); });
html.find('.conteneur-name a').click(async event => { // Display info about queue
html.find('.queuesouffle-label a').click((event) => {
let myID = event.currentTarget.attributes['data-item-id'].value;
const item = this.actor.getOwnedItem(myID);
item.sheet.render(true);
});
// Info sort
html.find('.sort-label a').click((event) => {
let myID = event.currentTarget.attributes['data-id'].value;
const item = this.actor.getOwnedItem(myID);
item.sheet.render(true);
});
// Info sort
html.find('.case-label a').click((event) => {
let myID = event.currentTarget.attributes['data-id'].value;
const item = this.actor.getOwnedItem(myID);
item.sheet.render(true);
});
// Display info about queue
html.find('.conteneur-name a').click((event) => {
let myID = event.currentTarget.attributes['data-item-id'].value; let myID = event.currentTarget.attributes['data-item-id'].value;
RdDUtility.toggleAfficheContenu(myID); RdDUtility.toggleAfficheContenu(myID);
this.render(true); this.render(true);
}); });
html.find('.carac-xp-augmenter').click(async event => {
let caracName = event.currentTarget.name.replace("augmenter.", "");
this.actor.updateCaracXPAuto(caracName);
});
html.find('.competence-xp-augmenter').click(async event => {
let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCompetenceXPAuto(compName);
});
if (this.options.editCaracComp) { if (this.options.editCaracComp) {
// On carac change // On carac change
html.find('.carac-value').change(async event => { html.find('.carac-value').change((event) => {
let caracName = event.currentTarget.name.replace(".value", "").replace("data.carac.", ""); let caracName = event.currentTarget.name.replace(".value", "").replace("data.carac.", "");
//console.log("Value changed :", event, caracName); //console.log("Value changed :", event, caracName);
this.actor.updateCarac(caracName, parseInt(event.target.value)); this.actor.updateCarac(caracName, parseInt(event.target.value));
}); });
html.find('.carac-xp').change(async event => { html.find('.carac-xp').change((event) => {
let caracName = event.currentTarget.name.replace(".xp", "").replace("data.carac.", ""); let caracName = event.currentTarget.name.replace(".xp", "").replace("data.carac.", "");
//console.log("Value changed :", event, caracName); //console.log("Value changed :", event, caracName);
this.actor.updateCaracXP(caracName, parseInt(event.target.value)); this.actor.updateCaracXP(caracName, parseInt(event.target.value));
}); });
// On competence change // On competence change
html.find('.competence-value').change(async event => { html.find('.competence-value').change((event) => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
//console.log("Competence changed :", compName); //console.log("Competence changed :", compName);
this.actor.updateCompetence(compName, parseInt(event.target.value)); this.actor.updateCompetence(compName, parseInt(event.target.value));
}); });
// On competence xp change // On competence xp change
html.find('.competence-xp').change(async event => { html.find('.competence-xp').change((event) => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCompetenceXP(compName, parseInt(event.target.value)); this.actor.updateCompetenceXP(compName, parseInt(event.target.value));
}); });
// On competence xp change // On competence xp change
html.find('.competence-xp-sort').change(async event => { html.find('.competence-xp-sort').change((event) => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value)); this.actor.updateCompetenceXPSort(compName, parseInt(event.target.value));
}); });
// On competence archetype change // On competence archetype change
html.find('.competence-archetype').change(async event => { html.find('.competence-archetype').change((event) => {
let compName = event.currentTarget.attributes.compname.value; let compName = event.currentTarget.attributes.compname.value;
this.actor.updateCompetenceArchetype(compName, parseInt(event.target.value)); this.actor.updateCompetenceArchetype(compName, parseInt(event.target.value));
}); });
} }
html.find('#show-hide-competences').click(async event => { // Gestion du bouton lock/unlock
this.options.showCompNiveauBase = !this.options.showCompNiveauBase; html.find('.lock-unlock-sheet').click((event) => {
this.render(true);
});
html.find('.lock-unlock-sheet').click(async event => {
this.options.editCaracComp = !this.options.editCaracComp; this.options.editCaracComp = !this.options.editCaracComp;
this.render(true); this.render(true);
}); });
html.find('#show-hide-archetype').click(async event => { html.find('#show-hide-archetype').click((event) => {
this.options.montrerArchetype = !this.options.montrerArchetype; this.options.montrerArchetype = !this.options.montrerArchetype;
this.render(true); this.render(true);
}); });
html.find('.lock-unlock-controls').click(async event => {
this.options.hideControls = !this.options.hideControls;
this.render(true);
});
// On pts de reve change // On pts de reve change
html.find('.pointsreve-value').change(async event => { html.find('.pointsreve-value').change((event) => {
let reveValue = event.currentTarget.value; let reveValue = event.currentTarget.value;
this.actor.update({ "data.reve.reve.value": reveValue }); this.actor.update({ "data.reve.reve.value": reveValue });
}); });
// On seuil de reve change // On seuil de reve change
html.find('.seuil-reve-value').change(async event => { html.find('.seuil-reve-value').change((event) => {
console.log("seuil-reve-value", event.currentTarget) console.log("seuil-reve-value", event.currentTarget)
this.actor.setPointsDeSeuil(event.currentTarget.value); this.actor.setPointsDeSeuil(event.currentTarget.value);
}); });
html.find('#attribut-protection-edit').change(async event => { html.find('#attribut-protection-edit').change((event) => {
this.actor.updateAttributeValue(event.currentTarget.attributes.name.value, parseInt(event.target.value)); this.actor.updateAttributeValue(event.currentTarget.attributes.name.value, parseInt(event.target.value));
}); });
// On stress change // On stress change
html.find('.compteur-edit').change(async event => { html.find('.compteur-edit').change((event) => {
let fieldName = event.currentTarget.attributes.name.value; let fieldName = event.currentTarget.attributes.name.value;
this.actor.updateCompteurValue(fieldName, parseInt(event.target.value)); this.actor.updateCompteurValue(fieldName, parseInt(event.target.value));
}); });
html.find('#ethylisme').change(async event => { html.find('#ethylisme').change((event) => {
this.actor.setEthylisme(parseInt(event.target.value)); this.actor.setEthylisme(parseInt(event.target.value));
}); });
html.find('.stress-test').click(async event => { html.find('.stress-test').click((event) => {
this.actor.transformerStress(); this.actor.transformerStress();
this.render(true);
}); });
html.find('.moral-malheureux').click(async event => { html.find('.moral-malheureux').click((event) => {
this.actor.jetDeMoral('malheureuse'); this.actor.jetDeMoral('malheureuse');
this.render(true);
}); });
html.find('.moral-neutre').click(async event => { html.find('.moral-neutre').click((event) => {
this.actor.jetDeMoral('neutre'); this.actor.jetDeMoral('neutre');
this.render(true);
}); });
html.find('.moral-heureux').click(async event => { html.find('.moral-heureux').click((event) => {
this.actor.jetDeMoral('heureuse'); this.actor.jetDeMoral('heureuse');
this.render(true);
}); });
html.find('#ethylisme-test').click(async event => { html.find('#ethylisme-test').click((event) => {
this.actor.jetEthylisme(); this.actor.ethylismeTest();
this.render(true);
}); });
html.find('#jet-vie').click(async event => { html.find('#jet-vie').click((event) => {
this.actor.jetVie(); this.actor.jetVie();
this.render(true);
}); });
html.find('#jet-endurance').click(async event => { html.find('#jet-endurance').click((event) => {
this.actor.jetEndurance(); this.actor.jetEndurance();
this.render(true);
}); });
html.find('.monnaie-plus').click(async event => { html.find('.monnaie-plus').click((event) => {
const li = $(event.currentTarget).parents(".item"); const li = $(event.currentTarget).parents(".item");
this.actor.monnaieIncDec(li.data("item-id"), 1); this.actor.monnaieIncDec(li.data("item-id"), 1);
this.render(true);
}); });
html.find('.monnaie-moins').click(async event => { html.find('.monnaie-moins').click((event) => {
const li = $(event.currentTarget).parents(".item"); const li = $(event.currentTarget).parents(".item");
this.actor.monnaieIncDec(li.data("item-id"), -1); this.actor.monnaieIncDec(li.data("item-id"), -1);
this.render(true);
}); });
html.find('#vie-plus').click(async event => { html.find('#vie-plus').click((event) => {
this.actor.santeIncDec("vie", 1); this.actor.santeIncDec("vie", 1);
this.render(true);
}); });
html.find('#vie-moins').click(async event => { html.find('#vie-moins').click((event) => {
this.actor.santeIncDec("vie", -1); this.actor.santeIncDec("vie", -1);
this.render(true);
}); });
html.find('#endurance-plus').click(async event => { html.find('#endurance-plus').click((event) => {
this.actor.santeIncDec("endurance", 1); this.actor.santeIncDec("endurance", 1);
this.render(true);
}); });
html.find('#endurance-moins').click(async event => { html.find('#endurance-moins').click((event) => {
this.actor.santeIncDec("endurance", -1); this.actor.santeIncDec("endurance", -1);
this.render(true);
}); });
html.find('.data-sante-sonne').click(async event => { html.find('.data-sante-sonne').click((event) => {
this.actor.setSonne(event.currentTarget.checked); this.actor.setSonne(event.currentTarget.checked);
this.render(true);
}); });
html.find('#ptreve-actuel-plus').click(async event => { html.find('#ptreve-actuel-plus').click((event) => {
this.actor.reveActuelIncDec(1); this.actor.reveActuelIncDec(1);
this.render(true);
}); });
html.find('#ptreve-actuel-moins').click(async event => { html.find('#ptreve-actuel-moins').click((event) => {
this.actor.reveActuelIncDec(-1); this.actor.reveActuelIncDec(-1);
this.render(true);
}); });
html.find('#fatigue-plus').click(async event => { html.find('#fatigue-plus').click((event) => {
this.actor.santeIncDec("fatigue", 1); this.actor.santeIncDec("fatigue", 1);
this.render(true);
}); });
html.find('#fatigue-moins').click(async event => { html.find('#fatigue-moins').click((event) => {
this.actor.santeIncDec("fatigue", -1); this.actor.santeIncDec("fatigue", -1);
this.render(true);
}); });
} }
@ -538,10 +587,8 @@ export class RdDActorSheet extends ActorSheet {
/** @override */ /** @override */
setPosition(options = {}) { setPosition(options = {}) {
const position = super.setPosition(options); const position = super.setPosition(options);
const sheetHeader = this.element.find(".sheet-header");
const sheetTabs = this.element.find(".sheet-tabs");
const sheetBody = this.element.find(".sheet-body"); const sheetBody = this.element.find(".sheet-body");
const bodyHeight = position.height - sheetHeader[0].clientHeight - sheetTabs[0].clientHeight; const bodyHeight = position.height - 192;
sheetBody.css("height", bodyHeight); sheetBody.css("height", bodyHeight);
return position; return position;
} }
@ -553,19 +600,4 @@ export class RdDActorSheet extends ActorSheet {
// Update the Actor // Update the Actor
return this.object.update(formData); return this.object.update(formData);
} }
async splitItem(item) {
const dialog = await DialogSplitItem.create(item, (item, split) => this._onSplitItem(item, split));
dialog.render(true);
}
async _onSplitItem(item, split) {
if (split >= 1 && split < Misc.data(item).data.quantite) {
await item.diminuerQuantite(split);
const itemData = duplicate( Misc.data(item));
itemData.data.quantite = split;
await this.actor.createEmbeddedDocuments('Item', [itemData])
}
}
} }

View File

@ -34,26 +34,12 @@ export class RdDActorVehiculeSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
const objectData = Misc.data(this.object); let formData = super.getData();
let formData = {
title: this.title, formData.itemsByType = Misc.classify(formData.items);
id: objectData.id,
type: objectData.type,
img: objectData.img,
name: objectData.name,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
data: foundry.utils.deepClone(Misc.templateData(this.object)),
effects: this.object.effects.map(e => foundry.utils.deepClone(e.data)),
limited: this.object.limited,
options: this.options,
owner: this.document.isOwner,
itemsByType: Misc.classify(this.object.items.map(i => foundry.utils.deepClone(i.data))),
};
RdDUtility.filterItemsPerTypeForSheet(formData); RdDUtility.filterItemsPerTypeForSheet(formData);
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets); RdDUtility.buildArbreDeConteneur(this, formData);
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
formData.options.isGM = game.user.isGM; formData.options.isGM = game.user.isGM;
@ -68,24 +54,10 @@ export class RdDActorVehiculeSheet extends ActorSheet {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onDropItem(event, dragData) { async _onDrop(event) {
const callSuper = await this.actor.processDropItem(event, dragData, this.objetVersConteneur); let toSuper = await RdDUtility.processItemDropEvent(this, event);
if (callSuper) { if ( toSuper) {
await super._onDropItem(event, dragData) super._onDrop(event);
}
}
/* -------------------------------------------- */
async createItem(name, type) {
await this.actor.createEmbeddedDocuments('Item', [{ name: name, type: type }], { renderSheet: true });
}
/* -------------------------------------------- */
async monnaieIncDec(id, value) {
let monnaie = this.getMonnaie(id);
if (monnaie) {
const quantite = Math.max(0, Misc.templateData(monnaie).quantite + value);
await this.updateEmbeddedDocuments('Item', [{ _id: monnaie.id, 'data.quantite': quantite }]);
} }
} }
@ -102,7 +74,7 @@ export class RdDActorVehiculeSheet extends ActorSheet {
// Update Inventory Item // Update Inventory Item
html.find('.item-edit').click(ev => { html.find('.item-edit').click(ev => {
const li = $(ev.currentTarget).parents(".item"); const li = $(ev.currentTarget).parents(".item");
const item = this.actor.getEmbeddedDocument('Item', li.data("itemId")); const item = this.actor.getOwnedItem(li.data("itemId"));
item.sheet.render(true); item.sheet.render(true);
}); });
// Delete Inventory Item // Delete Inventory Item
@ -111,22 +83,6 @@ export class RdDActorVehiculeSheet extends ActorSheet {
RdDUtility.confirmerSuppression(this, li); RdDUtility.confirmerSuppression(this, li);
}); });
html.find('.creer-un-objet').click(async event => {
RdDUtility.selectObjetType( this );
});
html.find('#nettoyer-conteneurs').click(async event => {
this.actor.nettoyerConteneurs();
});
html.find('.monnaie-plus').click(async event => {
const li = $(event.currentTarget).parents(".item");
this.actor.monnaieIncDec(li.data("item-id"), 1);
});
html.find('.monnaie-moins').click(async event => {
const li = $(event.currentTarget).parents(".item");
this.actor.monnaieIncDec(li.data("item-id"), -1);
});
// Display info about queue // Display info about queue
html.find('.conteneur-name a').click((event) => { html.find('.conteneur-name a').click((event) => {
let myID = event.currentTarget.attributes['data-item-id'].value; let myID = event.currentTarget.attributes['data-item-id'].value;
@ -138,12 +94,10 @@ export class RdDActorVehiculeSheet extends ActorSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
setPosition(options = {}) { setPosition(options={}) {
const position = super.setPosition(options); const position = super.setPosition(options);
const sheetHeader = this.element.find(".sheet-header");
const sheetTabs = this.element.find(".sheet-tabs");
const sheetBody = this.element.find(".sheet-body"); const sheetBody = this.element.find(".sheet-body");
const bodyHeight = position.height - sheetHeader[0].clientHeight - sheetTabs[0].clientHeight; const bodyHeight = position.height - 192;
sheetBody.css("height", bodyHeight); sheetBody.css("height", bodyHeight);
return position; return position;
} }

File diff suppressed because it is too large Load Diff

View File

@ -8,40 +8,27 @@ export class ChatUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static onSocketMessage(sockmsg) { static onSocketMessage(sockmsg) {
switch (sockmsg.msg) { switch (sockmsg.msg) {
case "msg_delete_chat_message": return ChatUtility.onRemoveMessages(sockmsg.data); case "msg_delete_chat_message": return ChatUtility.onRemoveMessages(sockmsg.part);
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static onRemoveMessages(data) { static onRemoveMessages(part) {
if (Misc.isElectedUser()) { if (Misc.isElectedUser()) {
if (data.part) { const toDelete = game.messages.filter(it => it.data.content.includes(part));
const toDelete = game.messages.filter(it => it.data.content.includes(data.part));
toDelete.forEach(it => it.delete()); toDelete.forEach(it => it.delete());
} }
if (data.messageId) {
game.messages.get(data.messageId)?.delete();
}
}
}
static removeMessages(data) {
if (Misc.isElectedUser()){
ChatUtility.onRemoveMessages(data);
}
else {
game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_delete_chat_message", data: data });
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static removeChatMessageContaining(part) { static removeChatMessageContaining(part) {
ChatUtility.removeMessages({ part: part }); if (Misc.isElectedUser()) {
ChatUtility.onRemoveMessages(part);
} }
else {
static removeChatMessageId(messageId) { game.socket.emit("system.foundryvtt-reve-de-dragon", {
if (messageId){ msg: "msg_delete_chat_message", data: { part: part }
ChatUtility.removeMessages({ messageId: messageId }); });
} }
} }
@ -57,7 +44,7 @@ export class ChatUtility {
if (!game.user.isGM) { if (!game.user.isGM) {
ChatUtility.blindMessageToGM(chatOptions); ChatUtility.blindMessageToGM(chatOptions);
chatOptions.whisper = [game.user.id]; chatOptions.whisper = [game.user._id];
chatOptions.content = "Message envoyé en aveugle au Gardien"; chatOptions.content = "Message envoyé en aveugle au Gardien";
} }
else { else {
@ -75,7 +62,7 @@ export class ChatUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static prepareChatMessage(rollMode, name) { static prepareChatMessage(rollMode, name) {
return { return {
user: game.user.id, user: game.user._id,
whisper: ChatUtility.getWhisperRecipients(rollMode, name) whisper: ChatUtility.getWhisperRecipients(rollMode, name)
} }
} }
@ -85,7 +72,7 @@ export class ChatUtility {
switch (rollMode) { switch (rollMode) {
case "blindroll": return ChatUtility.getUsers(user => user.isGM); case "blindroll": return ChatUtility.getUsers(user => user.isGM);
case "gmroll": return ChatUtility.getWhisperRecipientsAndGMs(name); case "gmroll": return ChatUtility.getWhisperRecipientsAndGMs(name);
case "selfroll": return [game.user.id]; case "selfroll": return [game.user._id];
} }
return undefined; return undefined;
} }
@ -114,7 +101,7 @@ export class ChatUtility {
static handleGMChatMessage(data) { static handleGMChatMessage(data) {
console.log("blindMessageToGM", data); console.log("blindMessageToGM", data);
if (game.user.isGM) { // message privé pour GM only if (game.user.isGM) { // message privé pour GM only
data.user = game.user.id; data.user = game.user._id;
ChatMessage.create(data); ChatMessage.create(data);
} }
} }

View File

@ -1,119 +0,0 @@
import { ChatUtility } from "./chat-utility.js";
import { HtmlUtility } from "./html-utility.js";
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
import { Misc } from "./misc.js";
import { RdDRollTables } from "./rdd-rolltables.js";
import { TMRType, TMRUtility } from "./tmr-utility.js";
export class DialogCreateSigneDraconique extends Dialog {
static async createSigneForActors() {
const signe = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
let dialogData = {
signe: signe,
tmrs: TMRUtility.listSelectedTMR(signe.data.typesTMR ?? []),
actors: game.actors.filter(actor => actor.isHautRevant()).map(actor => {
let actorData = duplicate(Misc.data(actor));
actorData.selected = actor.hasPlayerOwner;
return actorData;
})
};
const html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/dialog-create-signedraconique.html", dialogData);
new DialogCreateSigneDraconique(dialogData, html)
.render(true);
}
constructor(dialogData, html, callback) {
let options = { classes: ["DialogCreateSigneDraconiqueActorsActors"], width: 500, height: 650, 'z-index': 99999 };
let conf = {
title: "Créer un signe",
content: html,
default: "Ajouter aux haut-rêvants",
buttons: {
"Ajouter aux haut-rêvants": { label: "Ajouter aux haut-rêvants", callback: it => { this._onCreerSigneActeurs(); } }
}
};
super(conf, options);
this.dialogData = dialogData;
}
async _onCreerSigneActeurs() {
await $("[name='signe.data.ephemere']").change();
await $(".signe-xp-sort").change();
this.validerSigne();
this.dialogData.actors.filter(it => it.selected).map(it => game.actors.get(it._id))
.forEach(actor => this._createSigneForActor(actor, this.dialogData.signe));
}
async _createSigneForActor(actor, signe) {
actor.createEmbeddedDocuments("Item", [signe]);
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(Misc.data(actor).name),
content: await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html", {
signe: signe,
alias: Misc.data(actor).name
})
});
}
validerSigne() {
this.dialogData.signe.name = $("[name='signe.name']").val();
this.dialogData.signe.data.valeur.norm = $("[name='signe.data.valeur.norm']").val();
this.dialogData.signe.data.valeur.sign = $("[name='signe.data.valeur.sign']").val();
this.dialogData.signe.data.valeur.part = $("[name='signe.data.valeur.part']").val();
this.dialogData.signe.data.difficulte = $("[name='signe.data.difficulte']").val();
this.dialogData.signe.data.ephemere = $("[name='signe.data.ephemere']").prop("checked");
this.dialogData.signe.data.duree = $("[name='signe.data.duree']").val();
this.dialogData.signe.data.typesTMR = $(".select-tmr").val();
}
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
this.setEphemere(this.dialogData.signe.data.ephemere);
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
html.find("[name='signe.data.ephemere']").change((event) => this.setEphemere(event.currentTarget.checked));
html.find(".select-actor").change((event) => this.onSelectActor(event));
html.find(".signe-xp-sort").change((event) => this.onValeurXpSort(event));
}
async setSigneAleatoire() {
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique({ephemere: true});
$("[name='signe.name']").val(newSigne.name);
$("[name='signe.data.valeur.norm']").val(newSigne.data.valeur.norm);
$("[name='signe.data.valeur.sign']").val(newSigne.data.valeur.sign);
$("[name='signe.data.valeur.part']").val(newSigne.data.valeur.part);
$("[name='signe.data.difficulte']").val(newSigne.data.difficulte);
$("[name='signe.data.duree']").val(newSigne.data.duree);
$("[name='signe.data.ephemere']").prop("checked", newSigne.data.ephemere);
$(".select-tmr").val(newSigne.data.typesTMR);
this.setEphemere(newSigne.data.ephemere);
}
async setEphemere(ephemere) {
this.dialogData.signe.data.ephemere = ephemere;
HtmlUtility._showControlWhen($(".signe-data-duree"), ephemere);
}
async onSelectActor(event) {
event.preventDefault();
const options = event.currentTarget.options;
for (var i = 0; i < options.length; i++) { // looping over the options
const actorId = options[i].attributes["data-actor-id"].value;
const actor = this.dialogData.actors.find(it => it._id == actorId);
if (actor) {
actor.selected = options[i].selected;
}
};
}
onValeurXpSort(event) {
const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0;
const xp = Number(event.currentTarget.value);
const oldValeur = this.dialogData.signe.data.valeur;
this.dialogData.signe.data.valeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur);
}
}

View File

@ -1,71 +0,0 @@
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { RdDUtility } from "./rdd-utility.js";
export class DialogFabriquerPotion extends Dialog {
/* -------------------------------------------- */
static async create(actor, item, dialogConfig) {
let potionData = DialogFabriquerPotion.prepareData(actor, item);
let conf = {
title: `Fabriquer une potion de ${potionData.data.categorie}`,
content: await renderTemplate(dialogConfig.html, potionData),
default: potionData.buttonName,
};
let options = { classes: ["dialogfabriquerpotion"], width: 600, height: 160, 'z-index': 99999 };
mergeObject(options, dialogConfig.options ?? {}, { overwrite: true })
const dialog = new DialogFabriquerPotion(actor, potionData, conf, options);
dialog.render(true);
return dialog;
}
/* -------------------------------------------- */
static prepareData(actor, item) {
let potionData = duplicate(Misc.data(item));
potionData.nbBrinsSelect = RdDUtility.buildListOptions(1, potionData.data.quantite);
potionData.nbBrins = Math.min(potionData.data.quantite, DialogFabriquerPotion.getNombreBrinOptimal(potionData));
potionData.buttonName = "Fabriquer";
return potionData;
}
/* -------------------------------------------- */
constructor(actor, potionData, conf, options) {
conf.buttons = {
[potionData.buttonName]: {
label: potionData.buttonName, callback: it => this.onFabriquer(it)
}
};
super(conf, options);
this.actor = actor;
this.potionData = potionData;
}
static getNombreBrinOptimal(herbeData) {
switch (herbeData.data.categorie ?? '') {
case "Soin": return 12 - herbeData.data.niveau;
case "Repos": return 7 - herbeData.data.niveau;
}
return 1;
}
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
html.find("#nbBrins").change(event => {
this.potionData.nbBrins = Misc.toInt(event.currentTarget.value);
});
}
/* -------------------------------------------- */
async onFabriquer(it) {
await $("#nbBrins").change();
this.actor.fabriquerPotion(this.potionData);
this.close();
}
}

View File

@ -1,95 +0,0 @@
import { Misc } from "./misc.js";
import { RdDUtility } from "./rdd-utility.js";
export class DialogItemAchat extends Dialog {
static async onButtonAcheter(event) {
const buttonAcheter = event.currentTarget;
if (!buttonAcheter.attributes['data-jsondata']?.value) {
ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes")
return;
}
const chatMessageIdVente = RdDUtility.findChatMessageId(buttonAcheter);
const vendeurId = buttonAcheter.attributes['data-vendeurId']?.value;
const vendeur = vendeurId ? game.actors.get(vendeurId) : undefined;
const acheteur = RdDUtility.getSelectedActor();
if (!acheteur && !vendeur) {
ui.notifications.info("Pas d'acheteur ni de vendeur, aucun changement");
return;
}
let venteData = DialogItemAchat.prepareVenteData(buttonAcheter, vendeurId, vendeur, acheteur);
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-achat.html`, venteData);
const dialog = new DialogItemAchat(html, vendeur, acheteur, venteData, chatMessageIdVente);
dialog.render(true);
}
constructor(html, vendeur, acheteur, venteData, chatMessageIdVente) {
let options = { classes: ["dialogachat"], width: 400, height: 300, 'z-index': 99999 };
const actionAchat = venteData.prixLot > 0 ? "Acheter" : "Prendre";
let conf = {
title: actionAchat,
content: html,
default: actionAchat,
buttons: {
[actionAchat]: { label: actionAchat, callback: it => { this.onAchat(); } },
"decliner": { label: "Décliner", callback: it => { } }
}
};
super(conf, options);
this.vendeur = vendeur;
this.acheteur = acheteur;
this.chatMessageIdVente = chatMessageIdVente;
this.venteData = venteData;
}
static prepareVenteData(buttonAcheter, vendeurId, vendeur, acheteur) {
const jsondata = buttonAcheter.attributes['data-jsondata']?.value;
const prixLot = buttonAcheter.attributes['data-prixLot']?.value ?? 0;
let venteData = {
item: JSON.parse(jsondata),
vendeurId: vendeurId,
vendeur: Misc.data(vendeur),
acheteur: Misc.data(acheteur),
tailleLot: parseInt(buttonAcheter.attributes['data-tailleLot']?.value ?? 1),
quantiteIllimite: buttonAcheter.attributes['data-quantiteIllimite']?.value == 'true',
quantiteNbLots: parseInt(buttonAcheter.attributes['data-quantiteNbLots']?.value),
nombreLots: 1,
prixLot: prixLot,
prixTotal: prixLot,
isVente: prixLot > 0
};
return venteData;
}
async onAchat() {
await $(".nombreLots").change();
(this.vendeur ?? this.acheteur).achatVente({
vendeurId: this.vendeur?.id,
acheteurId: this.acheteur?.id,
nombreLots: this.venteData.nombreLots,
prixTotal: this.venteData.prixTotal,
chatMessageIdVente: this.chatMessageIdVente
});
}
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
html.find(".nombreLots").change(event => this.setNombreLots(Number(event.currentTarget.value)));
}
setNombreLots(nombreLots) {
this.venteData.nombreLots = nombreLots;
this.venteData.prixTotal = (nombreLots * this.venteData.prixLot).toFixed(2);
$(".prixTotal").text(this.venteData.prixTotal);
}
}

View File

@ -1,90 +0,0 @@
import { Misc } from "./misc.js";
export class DialogConsommer extends Dialog {
static async create(actor, item, template = undefined, options = {}) {
const consommerData = DialogConsommer.prepareData(actor, item, options);
const html = await renderTemplate(template ?? `systems/foundryvtt-reve-de-dragon/templates/dialog-item-consommer.html`, consommerData);
return new DialogConsommer(actor, item, consommerData, html, options)
}
constructor(actor, item, consommerData, html, options = {}) {
mergeObject(options, { classes: ["dialogconsommer"], width: 350, height: 450, 'z-index': 99999 }, { overwrite: false })
let conf = {
title: consommerData.title,
content: html,
default: consommerData.buttonName,
buttons: {
[consommerData.buttonName]: {
label: consommerData.buttonName, callback: it => this.onConsommer(it)
}
}
};
super(conf, options);
this.actor = actor;
this.item = item;
this.consommerData = consommerData;
}
async onConsommer(event) {
await $(".se-forcer").change();
await $(".consommer-doses").change();
this.actor.consommer(this.item, this.consommerData.choix);
}
/* -------------------------------------------- */
static prepareData(actor, item, options) {
const itemData = duplicate(Misc.data(item));
let consommerData = {
item: itemData,
cuisine: Misc.data(actor.getCompetence('cuisine')),
choix: {
doses: options.doses ?? 1,
seForcer: options.seForcer ?? false,
}
}
switch (itemData.type) {
case 'nourritureboisson':
consommerData.title = itemData.data.boisson ? `${itemData.name}: boire une dose` : `${itemData.name}: manger une portion`;
consommerData.buttonName = itemData.data.boisson ? "Boire" : "Manger";
break;
case 'potion':
consommerData.title = `${itemData.name}: boire la potion`;
consommerData.buttonName = "Boire";
break;
}
DialogConsommer.calculDoses(consommerData, consommerData.choix.doses)
return consommerData;
}
static calculDoses(consommerData) {
const doses = consommerData.choix.doses;
consommerData.totalSust = Misc.keepDecimals(doses * (consommerData.item.data.sust ?? 0), 2);
consommerData.totalDesaltere = consommerData.item.data.boisson
? Misc.keepDecimals(doses * (consommerData.item.data.desaltere ?? 0), 2)
: 0;
}
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
html.find(".se-forcer").change(event => this.setSeForcer(event));
html.find(".consommer-doses").change(event => this.selectDoses(event));
}
setSeForcer(event) {
this.consommerData.choix.seForcer = event.currentTarget.checked;
}
selectDoses(event) {
this.consommerData.choix.doses = Number(event.currentTarget.value);
DialogConsommer.calculDoses(this.consommerData);
$(".total-sust").text(this.consommerData.totalSust);
$(".total-desaltere").text(this.consommerData.totalDesaltere);
}
}

View File

@ -1,94 +0,0 @@
import { HtmlUtility } from "./html-utility.js";
import { Misc } from "./misc.js";
export class DialogItemVente extends Dialog {
static async create(item, callback) {
const itemData = Misc.data(item);
const venteData = {
item: itemData,
alias: item.actor?.name ?? game.user.name,
vendeurId: item.actor?.id,
prixOrigine: itemData.data.cout,
prixUnitaire: itemData.data.cout,
prixLot: itemData.data.cout,
tailleLot: 1,
quantiteNbLots: itemData.data.quantite,
quantiteMaxLots: itemData.data.quantite,
quantiteMax: itemData.data.quantite,
quantiteIllimite: !item.isOwned,
isOwned: item.isOwned,
};
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-vente.html`, venteData);
return new DialogItemVente(venteData, html, callback);
}
constructor(venteData, html, callback) {
let options = { classes: ["dialogvente"], width: 400, height: 300, 'z-index': 99999 };
let conf = {
title: "Proposer",
content: html,
default: "proposer",
buttons: { "proposer": { label: "Proposer", callback: it => { this.onProposer(it); } } }
};
super(conf, options);
this.callback = callback;
this.venteData = venteData;
}
async onProposer(it) {
await $(".tailleLot").change();
await $(".quantiteNbLots").change();
await $(".quantiteIllimite").change();
await $(".prixLot").change();
this.callback(this.venteData);
}
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
HtmlUtility._showControlWhen($(".quantiteNbLots"), !this.venteData.quantiteIllimite)
html.find(".tailleLot").change(event => this.setTailleLot(Number(event.currentTarget.value)));
html.find(".quantiteNbLots").change(event => this.setNbLots(Number(event.currentTarget.value)));
html.find(".quantiteIllimite").change(event => this.setQuantiteIllimite(event.currentTarget.checked));
html.find(".prixLot").change(event => this.setPrixLot(Number(event.currentTarget.value)));
}
setPrixLot(prixLot) {
this.venteData.prixLot = prixLot;
}
setTailleLot(tailleLot) {
// recalculer le prix du lot
if (tailleLot != this.venteData.tailleLot) {
this.venteData.prixLot = (tailleLot * this.venteData.prixOrigine).toFixed(2);
$(".prixLot").val(this.venteData.prixLot);
}
this.venteData.tailleLot = tailleLot;
if (this.venteData.isOwned) {
// recalculer le nombre de lots max
this.venteData.quantiteMaxLots = Math.floor(this.venteData.quantiteMax / tailleLot);
this.venteData.quantiteNbLots = Math.min(this.venteData.quantiteMaxLots, this.venteData.quantiteNbLots);
$(".quantiteNbLots").val(this.venteData.quantiteNbLots);
$(".quantiteNbLots").attr("max", this.venteData.quantiteMaxLots)
}
}
setNbLots(nbLots) {
if (this.venteData.isOwned) {
nbLots = Math.max(0, Math.min(nbLots, this.venteData.quantiteMaxLots));
}
this.venteData.quantiteNbLots = nbLots;
$(".quantiteNbLots").val(this.venteData.quantiteNbLots);
}
setQuantiteIllimite(checked) {
this.venteData.quantiteIllimite = checked;
$(".label-quantiteIllimite").text(this.venteData.quantiteIllimite ? "Illimités" : "disponibles");
HtmlUtility._showControlWhen($(".quantiteNbLots"), !this.venteData.quantiteIllimite)
}
}

View File

@ -1,52 +0,0 @@
import { Misc } from "./misc.js";
export class DialogSplitItem extends Dialog {
static async create(item, callback) {
const itemData = Misc.data(item);
const splitData = {
item: itemData,
choix: { quantite: 1, max: itemData.data.quantite - 1 }
};
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-item-split.html`, splitData);
return new DialogSplitItem(item, splitData, html, callback)
}
constructor(item, splitData, html, callback) {
let options = { classes: ["dialogsplit"], width: 300, height: 160, 'z-index': 99999 };
let conf = {
title: "Séparer en deux",
content: html,
default: "separer",
buttons: {
"separer": {
label: "Séparer", callback: it => {
this.onSplit();
}
}
}
};
super(conf, options);
this.callback = callback;
this.item = item;
this.splitData = splitData;
}
async onSplit(){
await $(".choix-quantite").change();
this.callback(this.item, this.splitData.choix.quantite);
}
/* -------------------------------------------- */
activateListeners(html) {
super.activateListeners(html);
html.find(".choix-quantite").change(event => {
this.splitData.choix.quantite = Number(event.currentTarget.value);
});
}
}

View File

@ -24,11 +24,6 @@ export class Grammar {
return words?.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "") ?? words; return words?.toLowerCase().normalize("NFD").replace(/[\u0300-\u036f]/g, "") ?? words;
} }
/* -------------------------------------------- */
static toLowerCaseNoAccentNoSpace(words) {
return words?.toLowerCase().normalize("NFD").replace(/[ \u0300-\u036f]/g, "") ?? words;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static articleDetermine(genre) { static articleDetermine(genre) {
switch (Grammar.toLowerCaseNoAccent(genre)) { switch (Grammar.toLowerCaseNoAccent(genre)) {

View File

@ -3,7 +3,7 @@ import { RdDUtility } from "./rdd-utility.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
// Activate chat listeners defined // Activate chat listeners defined
// Hooks.on('renderChatLog', (log, html, data) => { Hooks.on('renderChatLog', (log, html, data) => {
// RdDUtility.chatListeners(html); RdDUtility.chatListeners(html);
// }); });

View File

@ -112,7 +112,7 @@ export class RdDItemArme extends Item {
if (defCategory == 'boucliers') { if (defCategory == 'boucliers') {
return false; return false;
} }
// Parer avec une hache ou une arme dhast exige toujours une significative // Parer avec une hache ou une arme dhast exige toujours une signi$cative
if (defCategory.match(/(hast|haches)/)) { if (defCategory.match(/(hast|haches)/)) {
return true; return true;
} }

View File

@ -4,8 +4,8 @@ import { Misc } from "./misc.js";
const competenceTroncs = [["Esquive", "Dague", "Corps à corps"], const competenceTroncs = [["Esquive", "Dague", "Corps à corps"],
["Epée à 1 main", "Epée à 2 mains", "Hache à 1 main", "Hache à 2 mains", "Lance", "Masse à 1 main", "Masse à 2 mains"]]; ["Epée à 1 main", "Epée à 2 mains", "Hache à 1 main", "Hache à 2 mains", "Lance", "Masse à 1 main", "Masse à 2 mains"]];
const xp_par_niveau = [5, 5, 5, 10, 10, 10, 10, 15, 15, 15, 15, 20, 20, 20, 20, 30, 30, 40, 40, 60, 60, 100, 100, 100, 100, 100, 100, 100, 100, 100]; const competence_xp_par_niveau = [5, 5, 5, 10, 10, 10, 10, 15, 15, 15, 15, 20, 20, 20, 20, 30, 30, 40, 40, 60, 60, 100, 100, 100, 100, 100, 100, 100, 100, 100];
const niveau_max = xp_par_niveau.length - 10; const competence_niveau_max = competence_xp_par_niveau.length - 10;
/* -------------------------------------------- */ /* -------------------------------------------- */
const limitesArchetypes = [ const limitesArchetypes = [
{ "niveau": 0, "nombreMax": 100, "nombre": 0 }, { "niveau": 0, "nombreMax": 100, "nombre": 0 },
@ -24,14 +24,14 @@ const limitesArchetypes = [
/* -------------------------------------------- */ /* -------------------------------------------- */
const categorieCompetences = { const categorieCompetences = {
"generale": { base: -4, label: "Générales" }, "generale": { base: "-4", label: "Générales" },
"particuliere": { base: -8, label: "Particulières" }, "particuliere": { base: "-8", label: "Particulières" },
"specialisee": { base: -11, label: "Spécialisées" }, "specialisee": { base: "-11", label: "Spécialisées" },
"connaissance": { base: -11, label: "Connaissances" }, "connaissance": { base: "-11", label: "Connaissances" },
"draconic": { base: -11, label: "Draconics" }, "draconic": { base: "-11", label: "Draconics" },
"melee": { base: -6, label: "Mêlée" }, "melee": { base: "-6", label: "Mêlée" },
"tir": { base: -8, label: "Tir" }, "tir": { base: "-8", label: "Tir" },
"lancer": { base: -8, label: "Lancer" } "lancer": { base: "-8", label: "Lancer" }
} }
const compendiumCompetences = { const compendiumCompetences = {
@ -44,9 +44,9 @@ const compendiumCompetences = {
function _buildCumulXP() { function _buildCumulXP() {
let cumulXP = { "-11": 0 }; let cumulXP = { "-11": 0 };
let cumul = 0; let cumul = 0;
for (let i = 0; i <= xp_par_niveau.length; i++) { for (let i = 0; i <= competence_xp_par_niveau.length; i++) {
let level = i - 10; let level = i - 10;
cumul += xp_par_niveau[i]; cumul += competence_xp_par_niveau[i];
cumulXP[level] = cumul; cumulXP[level] = cumul;
} }
return cumulXP; return cumulXP;
@ -56,48 +56,29 @@ const competence_xp_cumul = _buildCumulXP();
export class RdDItemCompetence extends Item { export class RdDItemCompetence extends Item {
/* -------------------------------------------- */
static actorCompendium(actorType) { static actorCompendium(actorType) {
return compendiumCompetences[actorType]; return compendiumCompetences[actorType];
} }
/* -------------------------------------------- */
static getCategorieCompetences() { static getCategorieCompetences() {
return categorieCompetences; return categorieCompetences;
} }
/* -------------------------------------------- */
static getNiveauBase(category) { static getNiveauBase(category) {
return categorieCompetences[category].base; return categorieCompetences[category].base;
} }
/* -------------------------------------------- */
static getLabelCategorie(category) { static getLabelCategorie(category) {
return categorieCompetences[category].label; return categorieCompetences[category].label;
} }
/* -------------------------------------------- */
static getCategorie(competence) {
return Misc.data(competence)?.data.categorie;
}
static isDraconic(competence) {
return Misc.data(competence).data.categorie == 'draconic';
}
/* -------------------------------------------- */
static getVoieDraconic(competences, voie) {
voie = Grammar.toLowerCaseNoAccent(voie);
return competences.find(it => RdDItemCompetence.isDraconic(it) && Grammar.toLowerCaseNoAccent(Misc.data(it).name).includes(voie));
}
/* -------------------------------------------- */
static getEsquive(competences) { static getEsquive(competences) {
return { name: 'Esquive', niveau: RdDItemCompetence.findCompetence(competences, 'Esquive')?.data.niveau ?? -6 }; return { name: 'Esquive', niveau: RdDItemCompetence.findCompetence(competences, 'Esquive')?.data.niveau ?? -6 };
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static isCompetenceArme(competence) { static isCompetenceArme(competence) {
switch (Misc.templateData(competence).categorie) { switch (competence.data.categorie) {
case 'melee': case 'melee':
return Misc.data(competence).name != 'Esquive'; return competence.name != 'Esquive';
case 'tir': case 'tir':
case 'lancer': case 'lancer':
return true; return true;
@ -107,15 +88,15 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static isArmeUneMain(competence) { static isArmeUneMain(competence) {
return Misc.data(competence)?.name.toLowerCase().includes("1 main"); return competence?.name.toLowerCase().includes("1 main");
} }
static isArme2Main(competence) { static isArme2Main(competence) {
return Misc.data(competence)?.name.toLowerCase().includes("2 main"); return competence?.name.toLowerCase().includes("2 main");
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static isMalusEncombrementTotal(competence) { static isMalusEncombrementTotal(competence) {
return Misc.data(competence)?.name.toLowerCase().match(/(natation|acrobatie)/); return competence?.name.toLowerCase().match(/(natation|acrobatie)/);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -132,18 +113,17 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeTotalXP(competences) { static computeTotalXP(competences) {
const total = competences.map(c => RdDItemCompetence.computeXP(c)) const total = competences.map(c => RdDItemCompetence.computeXP(c))
.reduce(Misc.sum(), 0); .reduce((a, b) => a + b, 0);
const economieTronc = RdDItemCompetence.computeEconomieXPTronc(competences); const economieTronc = RdDItemCompetence.computeEconomieXPTronc(competences);
return total - economieTronc; return total - economieTronc;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeXP(competence) { static computeXP(competence) {
const itemData = Misc.data(competence); const factor = competence.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double !
const factor = itemData.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double ! const xpNiveau = RdDItemCompetence.computeDeltaXP(competence.data.base, competence.data.niveau ?? competence.data.base);
const xpNiveau = RdDItemCompetence.computeDeltaXP(itemData.data.base, itemData.data.niveau ?? itemData.data.base); const xp = competence.data.xp ?? 0;
const xp = itemData.data.xp ?? 0; const xpSort = competence.data.xp_sort ?? 0;
const xpSort = itemData.data.xp_sort ?? 0;
return factor * (xpNiveau + xp) + xpSort; return factor * (xpNiveau + xp) + xpSort;
} }
@ -169,11 +149,10 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeCompetenceXPCost(competence) { static computeCompetenceXPCost(competence) {
const compData = Misc.data(competence); let xp = RdDItemCompetence.getDeltaXp(competence.data.base, competence.data.niveau ?? competence.data.base);
let xp = RdDItemCompetence.getDeltaXp(compData.data.base, compData.data.niveau ?? compData.data.base); xp += competence.data.xp ?? 0;
xp += compData.data.xp ?? 0; if (competence.name.includes('Thanatos')) xp *= 2; /// Thanatos compte double !
if (compData.name.includes('Thanatos')) xp *= 2; /// Thanatos compte double ! xp += competence.data.xp_sort ?? 0;
xp += compData.data.xp_sort ?? 0;
return xp; return xp;
} }
@ -182,22 +161,20 @@ export class RdDItemCompetence extends Item {
let economie = 0; let economie = 0;
for (let troncList of competenceTroncs) { for (let troncList of competenceTroncs) {
let list = troncList.map(name => RdDItemCompetence.findCompetence(competences, name)) let list = troncList.map(name => RdDItemCompetence.findCompetence(competences, name))
.sort(Misc.descending(c => Misc.templateData(c).niveau)); // tri du plus haut au plus bas .sort((c1, c2) => c2.data.niveau - c1.data.niveau); // tri du plus haut au plus bas
list.splice(0, 1); // ignorer la plus élevée list.splice(0, 1); // ignorer la plus élevée
list.map(c => Misc.templateData(c)).forEach(tplData => { list.forEach(c => {
economie += RdDItemCompetence.getDeltaXp(tplData.base, Math.min(tplData.niveau, 0)); economie += RdDItemCompetence.getDeltaXp(c.data.base, Math.min(c.data.niveau, 0));
}); });
} }
return economie; return economie;
} }
/* -------------------------------------------- */
static levelUp(itemData) { static levelUp(itemData) {
itemData.data.xpNext = RdDItemCompetence.getCompetenceNextXp(itemData.data.niveau); itemData.data.xpNext = RdDItemCompetence.getCompetenceNextXp(itemData.data.niveau);
itemData.data.isLevelUp = itemData.data.xp >= itemData.data.xpNext; itemData.data.isLevelUp = itemData.data.xp >= itemData.data.xpNext;
} }
/* -------------------------------------------- */
static isVisible(itemData) { static isVisible(itemData) {
return Number(itemData.data.niveau) != RdDItemCompetence.getNiveauBase(itemData.data.categorie); return Number(itemData.data.niveau) != RdDItemCompetence.getNiveauBase(itemData.data.categorie);
} }
@ -215,15 +192,15 @@ export class RdDItemCompetence extends Item {
return undefined; return undefined;
} }
let competence = competences.find(it => Grammar.toLowerCaseNoAccent(it.name) == name); let competence = competences.find(it => Grammar.toLowerCaseNoAccent(it.name) == name);
if (!competence) { if (competence) {
competence = competences[0];
if (competences.length > 1) {
const names = competences.map(it => it.name).reduce((a, b) => `${a}<br>${b}`);
ui.notifications.info(`Plusieurs compétences possibles:<br>${names}<br>La première sera choisie: ${competence.name}`);
}
}
return competence; return competence;
} }
if (competences.length>1) {
const names = competences.map(it => it.name).reduce((a, b) => `${a}<br>${b}`);
ui.notifications.info(`Plusieurs compétences possibles:<br>${names}<br>La première sera choisie: ${competences[0].name}`);
}
return competences[0];
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static getCompetenceNextXp(niveau) { static getCompetenceNextXp(niveau) {
@ -233,7 +210,7 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static getCompetenceXp(niveau) { static getCompetenceXp(niveau) {
RdDItemCompetence._valideNiveau(niveau); RdDItemCompetence._valideNiveau(niveau);
return niveau < -10 ? 0 : xp_par_niveau[niveau + 10]; return niveau < -10 ? 0 : competence_xp_par_niveau[niveau + 10];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -245,16 +222,16 @@ export class RdDItemCompetence extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static _valideNiveau(niveau) { static _valideNiveau(niveau) {
if (niveau < -11 || niveau > niveau_max) { if (niveau < -11 || niveau > competence_niveau_max) {
console.warn(`Niveau ${niveau} en dehors des niveaux de compétences: [-11, ${niveau_max} ]`); console.warn(`Niveau ${niveau} en dehors des niveaux de compétences: [-11, ${competence_niveau_max} ]`);
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static computeResumeArchetype(competences) { static computeResumeArchetype(competences) {
const archetype = RdDItemCompetence.getLimitesArchetypes(); const archetype = RdDItemCompetence.getLimitesArchetypes();
competences.map(it => Math.max(0, Misc.templateData(it).niveau_archetype)) competences.forEach(it => {
.forEach(niveau => { let niveau = Math.max(0, it.data.niveau_archetype);
archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 }; archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 };
archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1; archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1;
}); });

View File

@ -5,8 +5,8 @@ export class RdDItemCompetenceCreature extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static setRollDataCreature(rollData) { static setRollDataCreature(rollData) {
rollData.competence = Misc.data(rollData.competence);
rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.data.carac_value } }; rollData.carac = { "carac_creature": { label: rollData.competence.name, value: rollData.competence.data.carac_value } };
rollData.competence = duplicate(rollData.competence);
rollData.competence.data.defaut_carac = "carac_creature"; rollData.competence.data.defaut_carac = "carac_creature";
rollData.competence.data.categorie = "creature"; rollData.competence.data.categorie = "creature";
rollData.selectedCarac = rollData.carac.carac_creature; rollData.selectedCarac = rollData.carac.carac_creature;
@ -19,11 +19,10 @@ export class RdDItemCompetenceCreature extends Item {
/* -------------------------------------------- */ /* -------------------------------------------- */
static toArme(itemData) { static toArme(itemData) {
if (RdDItemCompetenceCreature.isCompetenceAttaque(itemData)) { if (RdDItemCompetenceCreature.isCompetenceAttaque(itemData)) {
itemData = Misc.data(itemData); let arme = duplicate(Misc.data(itemData));
let arme = { name: itemData.name, data: duplicate(itemData) };
mergeObject(arme.data, mergeObject(arme.data,
{ {
competence: itemData.name, competence: arme.name,
resistance: 100, resistance: 100,
equipe: true, equipe: true,
dommagesReels: arme.data.dommages, dommagesReels: arme.data.dommages,

View File

@ -1,23 +1,22 @@
import { Misc } from "./misc.js";
const monnaiesData = [ const monnaiesData = [
{ {
name: "Etain (1 denier)", type: 'monnaie', _id: randomID(16), name: "Etain (1 denier)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp", img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
data: { quantite: 0, valeur_deniers: 1, encombrement: 0.001, description: "" } data: { quantite: 0, valeur_deniers: 1, encombrement: 0.001, description: "" }
}, },
{ {
name: "Bronze (10 deniers)", type: 'monnaie', _id: randomID(16), name: "Bronze (10 deniers)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp", img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp",
data: { quantite: 0, valeur_deniers: 10, encombrement: 0.002, description: "" } data: { quantite: 0, valeur_deniers: 10, encombrement: 0.002, description: "" }
}, },
{ {
name: "Argent (1 sol)", type: 'monnaie', _id: randomID(16), name: "Argent (1 sol)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp", img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp",
data: { quantite: 0, valeur_deniers: 100, encombrement: 0.003, description: "" } data: { quantite: 0, valeur_deniers: 100, encombrement: 0.003, description: "" }
}, },
{ {
name: "Or (10 sols)", type: 'monnaie', _id: randomID(16), name: "Or (10 sols)", type: 'monnaie',
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp", img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
data: { quantite: 0, valeur_deniers: 1000, encombrement: 0.004, description: "" } data: { quantite: 0, valeur_deniers: 1000, encombrement: 0.004, description: "" }
} }
@ -25,37 +24,17 @@ const monnaiesData = [
export class Monnaie { export class Monnaie {
static isSystemMonnaie(item) {
let present = monnaiesData.find(monnaie => monnaie.data.valeur_deniers == Misc.data(item)?.data?.valeur_deniers);
return present;
}
static monnaiesData() { static monnaiesData() {
return monnaiesData; return monnaiesData;
} }
static filtrerMonnaies(items) { static filtrerMonnaies(items) {
return items.filter(it => Misc.data(it).type == 'monnaie'); return items.filter(it => it.type == 'monnaie');
} }
static monnaiesManquantes(items) { static monnaiesManquantes(items) {
const valeurs = Monnaie.filtrerMonnaies(items) const valeurs = Monnaie.filtrerMonnaies(items)
.map(it => Misc.templateData(it).valeur_deniers); .map(it => it.data.valeur_deniers)
const manquantes = monnaiesData.filter(monnaie => !valeurs.find(v => v != Misc.templateData(monnaie).valeur_deniers)); return duplicate(monnaiesData.filter(monnaie => !valeurs.find(v => v != monnaie.data.valeur_deniers)));
//const manquantes = monnaiesData.filter(monnaie => !valeurs.find(v => v != Misc.templateData(monnaie).valeur_deniers) );
//console.log("Valeurs : ", valeurs, manquantes);
return []; //manquantes;
}
static deValeur(monnaie, v) {
return v != monnaie.data.valeur_deniers;
}
static arrondiDeniers(sols) {
return sols.toFixed(2);
}
static triValeurDenier() {
return Misc.ascending(item => Misc.data(item).data.valeur_deniers);
} }
} }

315
module/item-rdd.js Normal file
View File

@ -0,0 +1,315 @@
import { Misc } from "./misc.js";
import { RdDUtility } from "./rdd-utility.js";
/* -------------------------------------------- */
export class RdDItem extends Item {
/* -------------------------------------------- */
async postItem() {
console.log(this);
const properties = this[`_${this.data.type}ChatData`]();
const itemData = Misc.data(this);
let chatData = duplicate(itemData);
chatData["properties"] = properties
//Check if the posted item should have availability/pay buttons
chatData.hasPrice = "cout" in chatData.data;
chatData.data.cout_deniers = 0;
let dialogResult = [-1, -1]; // dialogResult[0] = quantité, dialogResult[1] = prix
if (chatData.hasPrice )
{
let sols = chatData.data.cout;
chatData.data.cout_deniers = Math.floor(sols * 100);
dialogResult = await new Promise( (resolve, reject) => {new Dialog({
content :
`<p>Modifier la quantité?</p>
<div class="form-group">
<label> Quantité</label>
<input name="quantity" type="text" value="1"/>
</div>
<p>Modifier la prix?</p>
<div class="form-group">
<label> Prix en Sols</label>
<input name="price" type="text" value="${chatData.data.cout}"/>
</div>
`,
title : "Quantité & Prix",
buttons : {
post : {
label : "Soumettre",
callback: (dlg) => {
resolve( [ dlg.find('[name="quantity"]').val(), dlg.find('[name="price"]').val() ] )
}
},
}
}).render(true)
})
}
if (dialogResult[0] > 0)
{
if (this.isOwned)
{
if (itemData.data.quantite == 0)
dialogResult[0] = -1
else if (itemData.data.quantite < dialogResult[0])
{
dialogResult[0] = itemData.data.quantite;
ui.notifications.notify(`Impossible de poster plus que ce que vous avez. La quantité à été réduite à ${dialogResult[0]}.`)
this.update({"data.quantite" : 0})
}
else {
ui.notifications.notify(`Quantité réduite par ${dialogResult[0]}.`)
this.update({"data.quantite" : itemData.data.quantite - dialogResult[0]})
}
}
}
if ( chatData.hasPrice ) {
if (dialogResult[0] > 0)
chatData.postQuantity = Number(dialogResult[0]);
if (dialogResult[1] > 0) {
chatData.postPrice = dialogResult[1];
chatData.data.cout_deniers = Math.floor(dialogResult[1] * 100); // Mise à jour cout en deniers
}
chatData.finalPrice = Number(chatData.postPrice) * Number(chatData.postQuantity);
chatData.data.cout_deniers_total = chatData.data.cout_deniers * Number(chatData.postQuantity);
chatData.data.quantite = chatData.postQuantity;
console.log("POST : ", chatData.finalPrice, chatData.data.cout_deniers_total, chatData.postQuantity);
}
// Don't post any image for the item (which would leave a large gap) if the default image is used
if (chatData.img.includes("/blank.png"))
chatData.img = null;
// JSON object for easy creation
chatData.jsondata = JSON.stringify(
{
compendium : "postedItem",
payload: itemData,
});
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-item.html', chatData).then(html => {
let chatOptions = RdDUtility.chatDataSetup(html);
ChatMessage.create(chatOptions)
});
}
/* -------------------------------------------- */
_objetChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Encombrement</b>: ${rddData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_armeChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Compétence</b>: ${rddData.competence}`,
`<b>Dommages</b>: ${rddData.dommages}`,
`<b>Force minimum</b>: ${rddData.force}`,
`<b>Resistance</b>: ${rddData.resistance}`,
`<b>Encombrement</b>: ${rddData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_conteneurChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Capacité</b>: ${rddData.capacite} Enc.`,
`<b>Encombrement</b>: ${rddData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_munitionChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Encombrement</b>: ${rddData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_armureChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Protection</b>: ${rddData.protection}`,
`<b>Détérioration</b>: ${rddData.deterioration}`,
`<b>Malus armure</b>: ${rddData.malus}`,
`<b>Encombrement</b>: ${rddData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_competenceChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Catégorie</b>: ${rddData.categorie}`,
`<b>Niveau</b>: ${rddData.niveau}`,
`<b>Caractéristique par défaut</b>: ${rddData.carac_defaut}`,
`<b>XP</b>: ${rddData.xp}`
]
return properties;
}
/* -------------------------------------------- */
_competencecreatureChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Catégorie</b>: ${rddData.categorie}`,
`<b>Niveau</b>: ${rddData.niveau}`,
`<b>Caractéristique</b>: ${rddData.carac_value}`,
`<b>XP</b>: ${rddData.xp}`
]
return properties;
}
/* -------------------------------------------- */
_sortChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Draconic</b>: ${rddData.draconic}`,
`<b>Difficulté</b>: ${rddData.difficulte}`,
`<b>Case TMR</b>: ${rddData.caseTMR}`,
`<b>Points de Rêve</b>: ${rddData.ptreve}`
]
return properties;
}
/* -------------------------------------------- */
_herbeChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Milieu</b>: ${rddData.milieu}`,
`<b>Rareté</b>: ${rddData.rarete}`,
`<b>Catégorie</b>: ${rddData.categorie}`,
]
return properties;
}
/* -------------------------------------------- */
_ingredientChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Milieu</b>: ${rddData.milieu}`,
`<b>Rareté</b>: ${rddData.rarete}`,
`<b>Catégorie</b>: ${rddData.categorie}`,
]
return properties;
}
/* -------------------------------------------- */
_tacheChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Caractéristique</b>: ${rddData.carac}`,
`<b>Compétence</b>: ${rddData.competence}`,
`<b>Périodicité</b>: ${rddData.periodicite}`,
`<b>Fatigue</b>: ${rddData.fatigue}`,
`<b>Difficulté</b>: ${rddData.difficulte}`,
`<b>Points de Tâche</b>: ${rddData.points_de_tache}`,
`<b>Points de Tâche atteints</b>: ${rddData.points_de_tache_courant}`
]
return properties;
}
/* -------------------------------------------- */
_livreChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Compétence</b>: ${rddData.competence}`,
`<b>Auteur</b>: ${rddData.auteur}`,
`<b>Difficulté</b>: ${rddData.difficulte}`,
`<b>Points de Tâche</b>: ${rddData.points_de_tache}`,
`<b>Encombrement</b>: ${rddData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_potionChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Rareté</b>: ${rddData.rarete}`,
`<b>Catégorie</b>: ${rddData.categorie}`,
`<b>Encombrement</b>: ${rddData.encombrement}`,
]
return properties;
}
/* -------------------------------------------- */
_queueChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Refoulement</b>: ${rddData.refoulement}`
]
return properties;
}
/* -------------------------------------------- */
_ombreChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Refoulement</b>: ${rddData.refoulement}`
]
return properties;
}
/* -------------------------------------------- */
_souffleChatData() {
const rddData = Misc.data(this).data;
let properties = [];
return properties;
}
/* -------------------------------------------- */
_teteChatData() {
const rddData = Misc.data(this).data;
let properties = [];
return properties;
}
/* -------------------------------------------- */
_tarotChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Concept</b>: ${rddData.concept}`,
`<b>Aspect</b>: ${rddData.aspect}`,
]
return properties;
}
/* -------------------------------------------- */
_nombreastralChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Valeur</b>: ${rddData.value}`,
`<b>Jour</b>: ${rddData.jourlabel}`,
]
return properties;
}
/* -------------------------------------------- */
_monnaieChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Valeur en Deniers</b>: ${rddData.valeur_deniers}`,
`<b>Encombrement</b>: ${rddData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_meditationChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Thème</b>: ${rddData.theme}`,
`<b>Compétence</b>: ${rddData.competence}`,
`<b>Support</b>: ${rddData.support}`,
`<b>Heure</b>: ${rddData.heure}`,
`<b>Purification</b>: ${rddData.purification}`,
`<b>Vêture</b>: ${rddData.veture}`,
`<b>Comportement</b>: ${rddData.comportement}`,
`<b>Case TMR</b>: ${rddData.tmr}`
]
return properties;
}
/* -------------------------------------------- */
_casetmrChatData() {
const rddData = Misc.data(this).data;
let properties = [
`<b>Coordonnée</b>: ${rddData.coord}`,
`<b>Spécificité</b>: ${rddData.specific}`
]
return properties;
}
}

View File

@ -1,11 +1,9 @@
import { RdDItemSort } from "./item-sort.js"; import { RdDItemSort } from "./item-sort.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
import { RdDItem } from "./item-rdd.js";
import { RdDAlchimie } from "./rdd-alchimie.js"; import { RdDAlchimie } from "./rdd-alchimie.js";
import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetence } from "./item-competence.js";
import { RdDHerbes } from "./rdd-herbes.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { HtmlUtility } from "./html-utility.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
/** /**
* Extend the basic ItemSheet with some very simple modifications * Extend the basic ItemSheet with some very simple modifications
@ -27,82 +25,47 @@ export class RdDItemSheet extends ItemSheet {
/* -------------------------------------------- */ /* -------------------------------------------- */
_getHeaderButtons() { _getHeaderButtons() {
let buttons = super._getHeaderButtons(); let buttons = super._getHeaderButtons();
const videSiConteneur = this.object.isConteneur() ? this.object.isVide() : true;
// Add "Post to chat" button // Add "Post to chat" button
// We previously restricted this to GM and editable items only. If you ever find this comment because it broke something: eh, sorry! // We previously restricted this to GM and editable items only. If you ever find this comment because it broke something: eh, sorry!
if ("cout" in Misc.templateData(this.object) && videSiConteneur) { buttons.unshift(
buttons.unshift({ {
class: "post",
icon: "fas fa-comments-dollar",
onclick: ev => this.item.proposerVente()
});
}
else {
buttons.unshift({
class: "post", class: "post",
icon: "fas fa-comment", icon: "fas fa-comment",
onclick: ev => this.item.postItem() onclick: ev => new RdDItem(Misc.data(this.item)).postItem()
}); })
}
return buttons return buttons
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
setPosition(options = {}) { setPosition(options={}) {
const position = super.setPosition(options); const position = super.setPosition(options);
const sheetHeader = this.element.find(".sheet-header");
const sheetBody = this.element.find(".sheet-body"); const sheetBody = this.element.find(".sheet-body");
const bodyHeight = position.height - sheetHeader[0].clientHeight; const bodyHeight = position.height - 192;
sheetBody.css("height", bodyHeight); sheetBody.css("height", bodyHeight);
return position; return position;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async getData() { async getData() {
const objectData = Misc.data(this.object); let formData = super.getData();
let formData = {
title: objectData.name,
id: objectData.id,
type: objectData.type,
img: objectData.img,
name: objectData.name,
data: objectData.data,
isGM: game.user.isGM,
owner: this.document.isOwner,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
isSoins: false
}
if (this.actor) {
formData.isOwned = true;
formData.actorId = this.actor.id;
}
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences(); formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences();
if (formData.type == 'tache' || formData.type == 'livre' || formData.type == 'meditation' || formData.type == 'oeuvre') { if ( formData.item.type == 'tache' || formData.item.type == 'livre' || formData.item.type == 'meditation' || formData.item.type == 'oeuvre') {
formData.caracList = duplicate(game.system.model.Actor.personnage.carac); formData.caracList = duplicate(game.system.model.Actor.personnage.carac);
formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences'); formData.competences = await RdDUtility.loadCompendiumNames( 'foundryvtt-reve-de-dragon.competences' );
} }
if (formData.type == 'arme') { if (formData.item.type == 'arme') {
formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences', it => RdDItemCompetence.isCompetenceArme(it)); formData.competences = await RdDUtility.loadCompendium( 'foundryvtt-reve-de-dragon.competences', it => RdDItemCompetence.isCompetenceArme(it));
console.log(formData.competences);
} }
if (formData.type == 'recettealchimique') { if ( formData.item.type == 'recettealchimique' ) {
RdDAlchimie.processManipulation(objectData, this.actor && this.actor.id); RdDAlchimie.processManipulation(formData.item, this.actor && this.actor._id );
} }
if (formData.type == 'potion') { if ( this.actor ) {
if (this.dateUpdated) { formData.isOwned = true;
formData.data.prdate = this.dateUpdated; formData.actorId = this.actor._id;
this.dateUpdated = undefined;
}
RdDHerbes.updatePotionData(formData);
}
if (formData.isOwned && formData.type == 'herbe' && (formData.data.categorie == 'Soin' || formData.data.categorie == 'Repos')) {
formData.isIngredientPotionBase = true;
} }
formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true); formData.bonusCaseList = RdDItemSort.getBonusCaseList(formData, true);
formData.isGM = game.user.isGM; // Pour verrouiller certaines éditions
return formData; return formData;
} }
@ -112,41 +75,22 @@ export class RdDItemSheet extends ItemSheet {
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
HtmlUtility._showControlWhen($(".item-cout"), ReglesOptionelles.isUsing('afficher-prix-joueurs') || game.user.isGM || !this.object.isOwned);
HtmlUtility._showControlWhen($(".item-magique"), this.object.isMagique());
// Everything below here is only needed if the sheet is editable // Everything below here is only needed if the sheet is editable
if (!this.options.editable) return; if (!this.options.editable) return;
// Select competence categorie // Select competence categorie
html.find(".categorie").change(event => this._onSelectCategorie(event)); html.find("#categorie").on("click", this._onClickSelectCategorie.bind(this) );
html.find('.sheet-competence-xp').change((event) => { html.find('#sheet-competence-xp').change((event) => {
if (this.object.data.type == 'competence') { if ( this.object.data.type == 'competence') {
RdDUtility.checkThanatosXP(this.object.data.name); RdDUtility.checkThanatosXP( this.object.data.name );
} }
}); } );
html.find('.enchanteDate').change((event) => { html.find('#creer-tache-livre').click((event) => {
let jour = Number($('#jourMois').val());
let mois = $('#nomMois').val();
this.dateUpdated = game.system.rdd.calendrier.getIndexFromDate(jour, mois);
});
html.find('.creer-tache-livre').click((event) => {
let actorId = event.currentTarget.attributes['data-actor-id'].value; let actorId = event.currentTarget.attributes['data-actor-id'].value;
let actor = game.actors.get(actorId); let actor = game.actors.get( actorId );
actor.creerTacheDepuisLivre(this.item); actor.creerTacheDepuisLivre( this.item );
});
html.find('.consommer-potion').click((event) => {
let actorId = event.currentTarget.attributes['data-actor-id'].value;
let actor = game.actors.get(actorId);
actor.consommerPotion(this.item);
});
html.find('.creer-potion-base').click((event) => {
let actorId = event.currentTarget.attributes['data-actor-id'].value;
let actor = game.actors.get(actorId);
actor.dialogFabriquerPotion(this.item);
}); });
html.find('.alchimie-tache a').click((event) => { html.find('.alchimie-tache a').click((event) => {
@ -154,41 +98,38 @@ export class RdDItemSheet extends ItemSheet {
let recetteId = event.currentTarget.attributes['data-recette-id'].value; let recetteId = event.currentTarget.attributes['data-recette-id'].value;
let tacheName = event.currentTarget.attributes['data-alchimie-tache'].value; let tacheName = event.currentTarget.attributes['data-alchimie-tache'].value;
let tacheData = event.currentTarget.attributes['data-alchimie-data'].value; let tacheData = event.currentTarget.attributes['data-alchimie-data'].value;
let actor = game.actors.get(actorId); let actor = game.actors.get( actorId );
if (actor) { if ( actor ) {
actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData); actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData);
} else { } else {
ui.notifications.info("Impossible trouver un actur pour réaliser cette tache Alchimique."); ui.notifications.info("Impossible de trouver un acteur pour réaliser cette tâche alchimique.");
} }
}); });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _onSelectCategorie(event) { async _onClickSelectCategorie(event) {
event.preventDefault(); event.preventDefault();
if (this.object.isCompetence()){
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value); let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
Misc.templateData(this.object).base = level; this.object.data.data.base = level;
$("#base").val(level); $("#base").val( level );
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
get template() { get template()
//console.log(this); {
let type = this.object.data.type; let type = this.item.type;
return `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html`; return `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html`;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
_updateObject(event, formData) { // Deprecated en v0.8 à clarifier _updateObject(event, formData) {
//console.log("UPDATE !", formData);
// Données de bonus de cases ? // Données de bonus de cases ?
formData = RdDItemSort.buildBonusCaseStringFromFormData(formData); formData = RdDItemSort.buildBonusCaseStringFromFormData( formData );
return this.object.update(formData); return this.object.update(formData);
} }

View File

@ -1,95 +0,0 @@
import { RdDItemSigneDraconique } from "./item-signedraconique.js";
import { Misc } from "./misc.js";
import { TMRType, TMRUtility } from "./tmr-utility.js";
/**
* Item sheet pour signes draconiques
* @extends {ItemSheet}
*/
export class RdDSigneDraconiqueItemSheet extends ItemSheet {
/** @override */
static get defaultOptions() {
return mergeObject(super.defaultOptions, {
classes: ["foundryvtt-reve-de-dragon", "sheet", "item"],
template: "systems/foundryvtt-reve-de-dragon/templates/item-signedraconique-sheet.html",
width: 550,
height: 550
});
}
/* -------------------------------------------- */
_getHeaderButtons() {
let buttons = super._getHeaderButtons();
buttons.unshift({ class: "post", icon: "fas fa-comment", onclick: ev => this.item.postItem() });
return buttons;
}
/* -------------------------------------------- */
/** @override */
setPosition(options = {}) {
const position = super.setPosition(options);
const sheetHeader = this.element.find(".sheet-header");
const sheetBody = this.element.find(".sheet-body");
const bodyHeight = position.height - sheetHeader[0].clientHeight;
sheetBody.css("height", bodyHeight);
return position;
}
/* -------------------------------------------- */
async getData() {
const formData = duplicate(Misc.data(this.object));
mergeObject(formData, {
title: formData.name,
isGM: game.user.isGM,
owner: this.document.isOwner,
isOwned: this.actor ? true : false,
actorId: this.actor?.id,
editable: this.isEditable,
cssClass: this.isEditable ? "editable" : "locked",
});
formData.tmrs = TMRUtility.listSelectedTMR(formData.data.typesTMR ?? []);
return formData;
}
/* -------------------------------------------- */
/** @override */
activateListeners(html) {
super.activateListeners(html);
if (!this.options.editable) return;
html.find(".signe-aleatoire").click(event => this.setSigneAleatoire());
html.find(".select-tmr").change((event) => this.onSelectTmr(event));
html.find(".signe-xp-sort").change((event) => this.onValeurXpSort(event.currentTarget.attributes['data-typereussite']?.value, Number(event.currentTarget.value)));
}
async setSigneAleatoire() {
const newSigne = await RdDItemSigneDraconique.randomSigneDraconique();
this.object.update(newSigne);
}
async onSelectTmr(event) {
event.preventDefault();
const selectedTMR = $(".select-tmr").val();
this.object.update({ 'data.typesTMR': selectedTMR });
}
async onValeurXpSort(event) {
const codeReussite = event.currentTarget.attributes['data-typereussite']?.value ?? 0;
const xp = Number(event.currentTarget.value);
const oldValeur = Misc.templateData(this.object).valeur;
const newValeur = RdDItemSigneDraconique.calculValeursXpSort(codeReussite, xp, oldValeur);
await this.object.update({ 'data.valeur': newValeur });
}
/* -------------------------------------------- */
get template() {
return `systems/foundryvtt-reve-de-dragon/templates/item-signedraconique-sheet.html`;
}
get title() {
return `Signe draconique: ${this.object.name}`;
}
}

View File

@ -1,103 +0,0 @@
import { defaultItemImg } from "./item.js";
import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
import { RdDRollTables } from "./rdd-rolltables.js";
import { TMRType, TMRUtility } from "./tmr-utility.js";
const tableSignesIndicatifs = [
{ rarete: "Très facile", difficulte: 0, xp: 6, nbCases: 14 },
{ rarete: "Facile", difficulte: -2, xp: 10, nbCases: 10 },
{ rarete: "Moyen", difficulte: -3, xp: 15, nbCases: 7 },
{ rarete: "Difficile", difficulte: -5, xp: 20, nbCases: 4 },
{ rarete: "Ardu", difficulte: -8, xp: 30, nbCases: 1 }
]
export class RdDItemSigneDraconique {
static prepareSigneDraconiqueMeditation(meditation, rolled) {
if (rolled.isSuccess != undefined) {
meditation = Misc.data(meditation);
return {
name: "de la " + meditation.name,
type: "signedraconique",
img: meditation.img,
data: {
typesTMR: [TMRUtility.typeTmrName(meditation.data.tmr)],
difficulte: RdDItemSigneDraconique.getDiffSigneMeditation(rolled.code),
ephemere: true,
duree: "1 round",
valeur: { "norm": 3, "sign": 5, "part": 10 }
}
};
}
return undefined;
}
static getDiffSigneMeditation(code) {
switch (code) {
case "norm": return -7;
case "sign": return -3;
case "part": return 0;
}
return undefined;
}
static getXpSortSigneDraconique(code, signe) {
return Misc.data(signe).data.valeur[code] ?? 0;
}
static calculValeursXpSort(qualite, valeur, avant) {
switch (qualite) {
case "norm":
return {
norm: valeur,
sign: Math.max(valeur, avant.sign),
part: Math.max(valeur, avant.part)
}
case "sign":
return {
norm: Math.min(valeur, avant.norm),
sign: valeur,
part: Math.max(valeur, avant.part)
}
case "part":
return {
norm: Math.min(valeur, avant.norm),
sign: Math.min(valeur, avant.sign),
part: valeur
}
}
}
static async randomSigneDraconique(options = { ephemere: undefined }) {
let modele = await RdDDice.rollOneOf(tableSignesIndicatifs);
return {
name: await RdDItemSigneDraconique.randomSigneDescription(),
type: "signedraconique",
img: defaultItemImg.signedraconique,
data: {
typesTMR: await RdDItemSigneDraconique.randomTmrs(modele.nbCases),
ephemere: options?.ephemere == undefined ? RdDDice.rollTotal("1d2") == 2 : options.ephemere,
duree: "1 round",
difficulte: modele.difficulte,
valeur: { norm: modele.xp, sign: modele.xp, part: Math.floor(modele.xp * 1.5) },
}
};
}
static async randomTmrs(nbTmr = undefined) {
let tmrs = Object.values(TMRType)
.map(value => TMRUtility.typeTmrName(value.name));
let keep = nbTmr ?? (await RdDDice.rollTotal("1d" + TMRType.length) + 1);
for (let i = tmrs.length; i > keep; i--) {
tmrs.splice(await RdDDice.rollTotal("1d" + i), 1);
}
return tmrs;
}
static async randomSigneDescription() {
return await RdDRollTables.drawTextFromRollTable("Signes draconiques", false);
}
}

View File

@ -51,10 +51,10 @@ export class RdDItemSort extends Item {
* Retourne une liste de bonus/case pour un item-sheet * Retourne une liste de bonus/case pour un item-sheet
* @param {} item * @param {} item
*/ */
static getBonusCaseList( item, newCase = false ) { static getBonusCaseList( data, newCase = false ) {
// Gestion spéciale case bonus // Gestion spéciale case bonus
if ( item.type == 'sort') { if ( data.item.type == 'sort') {
return this.buildBonusCaseList(item.data.bonuscase, newCase ); return this.buildBonusCaseList(data.data.bonuscase, newCase );
} }
return undefined; return undefined;
} }
@ -106,7 +106,7 @@ export class RdDItemSort extends Item {
// Sauvegarde/update // Sauvegarde/update
let bonuscase = StringList.toString(); let bonuscase = StringList.toString();
//console.log("Bonus cae :", bonuscase); //console.log("Bonus cae :", bonuscase);
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'data.bonuscase': bonuscase }] ); actor.updateEmbeddedEntity("OwnedItem", { _id: sort._id, 'data.bonuscase': bonuscase } );
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -1,562 +0,0 @@
import { DialogItemVente } from "./dialog-item-vente.js";
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { RdDUtility } from "./rdd-utility.js";
const typesObjetsEquipement = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "nourritureboisson", "monnaie"];
const typesObjetsOeuvres = ["oeuvre", "recettecuisine", "musique", "chant", "danse", "jeu"];
const encBrin = 0.00005;// un brin = 1 décigramme = 1/10g = 1/10000kg = 1/20000 enc
export const defaultItemImg = {
competence: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp",
compcreature: "systems/foundryvtt-reve-de-dragon/icons/competence_defaut.webp",
arme: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/epee_gnome.webp",
armure: "systems/foundryvtt-reve-de-dragon/icons/armes_armures/armure_plaques.webp",
conteneur: "systems/foundryvtt-reve-de-dragon/icons/objets/sac_a_dos.webp",
sort: "systems/foundryvtt-reve-de-dragon/icons/competence_oniros.webp",
herbe: "systems/foundryvtt-reve-de-dragon/icons/botanique/Endorlotte.png",
ingredient: "systems/foundryvtt-reve-de-dragon/icons/objets/sable_poudre.webp",
livre: "systems/foundryvtt-reve-de-dragon/icons/objets/livre.webp",
potion: "systems/foundryvtt-reve-de-dragon/icons/objets/liqueur_de_bagdol.webp",
queue: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
ombre: "systems/foundryvtt-reve-de-dragon/icons/queue_dragon.webp",
souffle: "systems/foundryvtt-reve-de-dragon/icons/souffle_dragon.webp",
tete: "systems/foundryvtt-reve-de-dragon/icons/tete_dragon.webp",
meditation: "systems/foundryvtt-reve-de-dragon/icons/meditations_ecrits/meditation_alchimie.webp",
recettealchimique: "systems/foundryvtt-reve-de-dragon/icons/competence_alchimie.webp",
chant: "systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp",
danse: "systems/foundryvtt-reve-de-dragon/icons/arts/danse_0.webp",
jeu: "systems/foundryvtt-reve-de-dragon/icons/arts/jeux_petasse.webp",
recettecuisine: "systems/foundryvtt-reve-de-dragon/icons/arts/recette_cuisine_1.webp",
musique: "systems/foundryvtt-reve-de-dragon/icons/arts/chant_0.webp",
maladie: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/maladie.webp",
poison: "systems/foundryvtt-reve-de-dragon/icons/maladies_venins/venin.webp",
oeuvre: "systems/foundryvtt-reve-de-dragon/icons/competence_comedie.webp",
nourritureboisson: "systems/foundryvtt-reve-de-dragon/icons/objets/provision_crue.webp",
signedraconique: "systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp",
}
/* -------------------------------------------- */
export class RdDItem extends Item {
constructor(data, context) {
if (!data.img) {
data.img = defaultItemImg[data.type];
}
super(data, context);
}
static getTypeObjetsEquipement() {
return typesObjetsEquipement;
}
static getTypesOeuvres() {
return typesObjetsOeuvres;
}
isCompetence() {
return Misc.data(this).type == 'competence';
}
isConteneur() {
return Misc.data(this).type == 'conteneur';
}
isVide() {
return this.isConteneur() && (Misc.templateData(this).contenu ?? []).length == 0;
}
isAlcool() {
const itemData = Misc.data(this);
return itemData.type == 'nourritureboisson' && itemData.data.boisson && itemData.data.alcoolise;
}
isPotion() {
return Misc.data(this).type == 'potion';
}
isEquipement() {
return RdDItem.getTypeObjetsEquipement().includes(Misc.data(this).type);
}
isCristalAlchimique() {
const itemData = Misc.data(this);
return itemData.type == 'objet' && Grammar.toLowerCaseNoAccent(itemData.name) == 'cristal alchimique' && itemData.data.quantite > 0;
}
isMagique() {
return Misc.templateData(this).magique;
}
getEncTotal() {
const itemData = Misc.data(this);
return Number(itemData.data.encombrement ?? 0) * Number(itemData.data.quantite ?? 1);
}
getEnc() {
const itemData = Misc.data(this);
switch (itemData.type) {
case 'herbe':
return encBrin;
}
return itemData.data.encombrement ?? 0;
}
prepareDerivedData() {
super.prepareDerivedData();
if (this.isEquipement(this)) {
this._calculsEquipement();
}
if (this.isPotion()) {
this.prepareDataPotion()
}
const itemData = Misc.data(this);
itemData.data.actionPrincipale = this.getActionPrincipale({ warnIfNot: false });
}
prepareDataPotion() {
const tplData = Misc.templateData(this);
const categorie = Grammar.toLowerCaseNoAccent(tplData.categorie);
tplData.magique = categorie.includes('enchante');
if (tplData.magique) {
if (categorie.includes('soin') || categorie.includes('repos')) {
tplData.puissance = tplData.herbebonus * tplData.pr;
}
}
}
_calculsEquipement() {
const tplData = Misc.templateData(this);
const quantite = this.isConteneur() ? 1 : (tplData.quantite ?? 0);
const enc = this.getEnc();
if (enc != undefined) {
tplData.encTotal = Math.max(enc, 0) * quantite;
}
if (tplData.cout != undefined) {
tplData.prixTotal = Math.max(tplData.cout, 0) * quantite;
}
}
getActionPrincipale(options = { warnIfNot: true }) {
const itemData = Misc.data(this);
if ((itemData.data.quantite ?? 0) <= 0) {
if (options.warnIfNot) {
ui.notifications.warn(`Vous n'avez plus de ${itemData.name}.`);
}
return undefined;
}
switch (itemData.type) {
case 'nourritureboisson': return itemData.data.boisson ? 'Boire' : 'Manger';
case 'potion': return 'Boire';
case 'livre': return 'Lire';
}
if (options.warnIfNot) {
ui.notifications.warn(`Impossible d'utilise un ${itemData.name}, aucune action associée définie.`);
}
return undefined;
}
async diminuerQuantite(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
if (options.diminuerQuantite == false) return;
await this.quantiteIncDec(-nombre, options);
}
async quantiteIncDec(nombre, options = { diminuerQuantite: true, supprimerSiZero: false }) {
const itemData = Misc.data(this);
const quantite = Number(itemData.data.quantite ?? -1);
if (quantite >= 0) {
const reste = Math.max(quantite + Number(nombre), 0);
if (reste == 0) {
if (options.supprimerSiZero) {
ui.notifications.notify(`${itemData.name} supprimé de votre équipement`);
await this.delete();
}
else {
ui.notifications.notify(`Il ne vous reste plus de ${itemData.name}, vous pouvez le supprimer de votre équipement, ou trouver un moyen de vous en procurer.`);
await this.update({ "data.quantite": 0 });
}
}
else {
await this.update({ "data.quantite": reste });
}
}
}
/* -------------------------------------------- */
// détermine si deux équipements sont similaires: de même type, et avec les même champs hormis la quantité
isEquipementSimilaire(other) {
const itemData = Misc.data(this);
const otherData = Misc.data(other);
const tplData = Misc.templateData(this);
const otherTplData = Misc.templateData(other);
if (!this.isEquipement()) return false;
if (itemData.type != otherData.type) return false;
if (itemData.name != otherData.name) return false;
if (tplData.quantite == undefined) return false;
const differences = Object.entries(tplData).filter(([key, value]) => !['quantite', 'encTotal', 'prixTotal', 'cout'].includes(key))
.filter(([key, value]) => value != otherTplData[key]);
if (differences.length > 0) {
let message = `Impossible de regrouper les ${itemData.type} ${itemData.name}: `;
for (const [key, value] of differences){
message += `<br>${key}: ${value} vs ${otherTplData[key]}`;
}
ui.notifications.info(message)
return false;
}
return true;
}
async proposerVente() {
console.log(this);
const dialog = await DialogItemVente.create(this, (vente) => this._onProposerVente(vente))
dialog.render(true);
}
async _onProposerVente(venteData) {
venteData["properties"] = this.getProprietes();
if (venteData.isOwned) {
if (venteData.quantiteNbLots * venteData.tailleLot > venteData.quantiteMax) {
ui.notifications.warn(`Vous avez ${venteData.quantiteMax} ${venteData.item.name}, ce n'est pas suffisant pour vendre ${venteData.quantiteNbLots} de ${venteData.tailleLot}`)
return;
}
}
venteData.jsondata = JSON.stringify(venteData.item);
console.log(venteData);
let html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-vente-item.html', venteData);
ChatMessage.create(RdDUtility.chatDataSetup(html));
}
getProprietes() {
return this[`_${Misc.data(this).type}ChatData`]();
}
/* -------------------------------------------- */
async postItem() {
console.log(this);
let chatData = duplicate(Misc.data(this));
const properties = this.getProprietes();
chatData["properties"] = properties
if (this.actor) {
chatData.actor = { id: this.actor.id };
}
//Check if the posted item should have availability/pay buttons
chatData.hasPrice = "cout" in chatData.data;
chatData.data.cout_deniers = 0;
let dialogResult = [-1, -1]; // dialogResult[0] = quantité, dialogResult[1] = prix
if (chatData.hasPrice) {
chatData.data.cout_deniers = Math.floor(chatData.data.cout * 100);
dialogResult = await new Promise((resolve, reject) => {
new Dialog({
content:
`<p>Modifier la quantité?</p>
<div class="form-group">
<label> Quantité</label>
<input name="quantity" type="text" value="1"/>
</div>
<p>Modifier la prix?</p>
<div class="form-group">
<label>Prix en Sols</label>
<input name="price" type="text" value="${chatData.data.cout}"/>
</div>
`,
title: "Quantité & Prix",
buttons: {
post: {
label: "Soumettre",
callback: (dlg) => {
resolve([Number(dlg.find('[name="quantity"]').val()), Number(dlg.find('[name="price"]').val())])
}
},
}
}).render(true)
})
}
let quantiteEnvoi = this.isOwned ? Math.min(dialogResult[0], chatData.data.quantite) : dialogResult[0];
const prixTotal = dialogResult[1];
if (quantiteEnvoi > 0) {
if (this.isOwned) {
if (chatData.data.quantite == 0) {
quantiteEnvoi = -1
}
else if (quantiteEnvoi > chatData.data.quantite) {
quantiteEnvoi = chatData.data.quantite;
ui.notifications.notify(`Impossible de poster plus que ce que vous avez. La quantité à été réduite à ${quantiteEnvoi}.`)
}
if (quantiteEnvoi > 0) {
this.diminuerQuantite(quantiteEnvoi);
}
}
}
if (chatData.hasPrice) {
if (quantiteEnvoi > 0)
chatData.postQuantity = Number(quantiteEnvoi);
if (prixTotal >= 0) {
chatData.postPrice = prixTotal;
chatData.data.cout_deniers = Math.floor(prixTotal * 100); // Mise à jour cout en deniers
}
chatData.finalPrice = Number(chatData.postPrice) * Number(chatData.postQuantity);
chatData.data.cout_deniers_total = chatData.data.cout_deniers * Number(chatData.postQuantity);
chatData.data.quantite = chatData.postQuantity;
console.log("POST : ", chatData.finalPrice, chatData.data.cout_deniers_total, chatData.postQuantity);
}
// Don't post any image for the item (which would leave a large gap) if the default image is used
if (chatData.img.includes("/blank.png"))
chatData.img = null;
// JSON object for easy creation
chatData.jsondata = JSON.stringify(
{
compendium: "postedItem",
payload: chatData,
});
renderTemplate('systems/foundryvtt-reve-de-dragon/templates/post-item.html', chatData).then(html => {
let chatOptions = RdDUtility.chatDataSetup(html);
ChatMessage.create(chatOptions)
});
}
static propertyIfDefined(name, val, condition = (it) => true) {
return condition ? [`<b>${name}</b>: ${val}`] : [];
}
/* -------------------------------------------- */
_objetChatData() {
const tplData = Misc.templateData(this);
let properties = [].concat(
RdDItem.propertyIfDefined('Résistance', tplData.resistance, tplData.resistance),
RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite),
RdDItem.propertyIfDefined('Encombrement', tplData.encombrement),
);
return properties;
}
/* -------------------------------------------- */
_nourritureboissonChatData() {
const tplData = Misc.templateData(this);
let properties = [].concat(
RdDItem.propertyIfDefined('Sustentation', tplData.sust, tplData.sust > 0),
RdDItem.propertyIfDefined('Désaltère', tplData.desaltere, tplData.boisson),
RdDItem.propertyIfDefined('Force alcool', tplData.force, tplData.boisson && tplData.alcoolise),
RdDItem.propertyIfDefined('Exotisme', tplData.exotisme, tplData.exotisme < 0),
RdDItem.propertyIfDefined('Qualité', tplData.qualite, tplData.qualite),
RdDItem.propertyIfDefined('Encombrement', tplData.encombrement),
);
return properties;
}
/* -------------------------------------------- */
_armeChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Compétence</b>: ${tplData.competence}`,
`<b>Dommages</b>: ${tplData.dommages}`,
`<b>Force minimum</b>: ${tplData.force}`,
`<b>Resistance</b>: ${tplData.resistance}`,
`<b>Encombrement</b>: ${tplData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_conteneurChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Capacité</b>: ${tplData.capacite} Enc.`,
`<b>Encombrement</b>: ${tplData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_munitionChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Encombrement</b>: ${tplData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_armureChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Protection</b>: ${tplData.protection}`,
`<b>Détérioration</b>: ${tplData.deterioration}`,
`<b>Malus armure</b>: ${tplData.malus}`,
`<b>Encombrement</b>: ${tplData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_competenceChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Catégorie</b>: ${tplData.categorie}`,
`<b>Niveau</b>: ${tplData.niveau}`,
`<b>Caractéristique par défaut</b>: ${tplData.carac_defaut}`,
`<b>XP</b>: ${tplData.xp}`
]
return properties;
}
/* -------------------------------------------- */
_competencecreatureChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Catégorie</b>: ${tplData.categorie}`,
`<b>Niveau</b>: ${tplData.niveau}`,
`<b>Caractéristique</b>: ${tplData.carac_value}`,
`<b>XP</b>: ${tplData.xp}`
]
return properties;
}
/* -------------------------------------------- */
_sortChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Draconic</b>: ${tplData.draconic}`,
`<b>Difficulté</b>: ${tplData.difficulte}`,
`<b>Case TMR</b>: ${tplData.caseTMR}`,
`<b>Points de Rêve</b>: ${tplData.ptreve}`
]
return properties;
}
/* -------------------------------------------- */
_herbeChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Milieu</b>: ${tplData.milieu}`,
`<b>Rareté</b>: ${tplData.rarete}`,
`<b>Catégorie</b>: ${tplData.categorie}`,
]
return properties;
}
/* -------------------------------------------- */
_ingredientChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Milieu</b>: ${tplData.milieu}`,
`<b>Rareté</b>: ${tplData.rarete}`,
`<b>Catégorie</b>: ${tplData.categorie}`,
]
return properties;
}
/* -------------------------------------------- */
_tacheChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Caractéristique</b>: ${tplData.carac}`,
`<b>Compétence</b>: ${tplData.competence}`,
`<b>Périodicité</b>: ${tplData.periodicite}`,
`<b>Fatigue</b>: ${tplData.fatigue}`,
`<b>Difficulté</b>: ${tplData.difficulte}`,
`<b>Points de Tâche</b>: ${tplData.points_de_tache}`,
`<b>Points de Tâche atteints</b>: ${tplData.points_de_tache_courant}`
]
return properties;
}
/* -------------------------------------------- */
_livreChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Compétence</b>: ${tplData.competence}`,
`<b>Auteur</b>: ${tplData.auteur}`,
`<b>Difficulté</b>: ${tplData.difficulte}`,
`<b>Points de Tâche</b>: ${tplData.points_de_tache}`,
`<b>Encombrement</b>: ${tplData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_potionChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Rareté</b>: ${tplData.rarete}`,
`<b>Catégorie</b>: ${tplData.categorie}`,
`<b>Encombrement</b>: ${tplData.encombrement}`,
]
return properties;
}
/* -------------------------------------------- */
_queueChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Refoulement</b>: ${tplData.refoulement}`
]
return properties;
}
/* -------------------------------------------- */
_ombreChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Refoulement</b>: ${tplData.refoulement}`
]
return properties;
}
/* -------------------------------------------- */
_souffleChatData() {
const tplData = Misc.templateData(this);
let properties = [];
return properties;
}
/* -------------------------------------------- */
_teteChatData() {
const tplData = Misc.templateData(this);
let properties = [];
return properties;
}
/* -------------------------------------------- */
_tarotChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Concept</b>: ${tplData.concept}`,
`<b>Aspect</b>: ${tplData.aspect}`,
]
return properties;
}
/* -------------------------------------------- */
_nombreastralChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Valeur</b>: ${tplData.value}`,
`<b>Jour</b>: ${tplData.jourlabel}`,
]
return properties;
}
/* -------------------------------------------- */
_monnaieChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Valeur en Deniers</b>: ${tplData.valeur_deniers}`,
`<b>Encombrement</b>: ${tplData.encombrement}`
]
return properties;
}
/* -------------------------------------------- */
_meditationChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Thème</b>: ${tplData.theme}`,
`<b>Compétence</b>: ${tplData.competence}`,
`<b>Support</b>: ${tplData.support}`,
`<b>Heure</b>: ${tplData.heure}`,
`<b>Purification</b>: ${tplData.purification}`,
`<b>Vêture</b>: ${tplData.veture}`,
`<b>Comportement</b>: ${tplData.comportement}`,
`<b>Case TMR</b>: ${tplData.tmr}`
]
return properties;
}
/* -------------------------------------------- */
_casetmrChatData() {
const tplData = Misc.templateData(this);
let properties = [
`<b>Coordonnée</b>: ${tplData.coord}`,
`<b>Spécificité</b>: ${tplData.specific}`
]
return properties;
}
}

View File

@ -1,4 +1,3 @@
import { RdDDice } from "./rdd-dice.js";
/** /**
* This class is intended as a placeholder for utility methods unrelated * This class is intended as a placeholder for utility methods unrelated
@ -23,11 +22,11 @@ export class Misc {
return (a, b) => a + b; return (a, b) => a + b;
} }
static ascending(orderFunction = x => x) { static ascending(orderFunction = x=>x) {
return (a, b) => Misc.sortingBy(orderFunction(a), orderFunction(b)); return (a, b) => Misc.sortingBy(orderFunction(a), orderFunction(b));
} }
static descending(orderFunction = x => x) { static descending(orderFunction = x=>x) {
return (a, b) => Misc.sortingBy(orderFunction(b), orderFunction(a)); return (a, b) => Misc.sortingBy(orderFunction(b), orderFunction(a));
} }
@ -49,12 +48,6 @@ export class Misc {
return isNaN(parsed) ? 0 : parsed; return isNaN(parsed) ? 0 : parsed;
} }
static keepDecimals(num, decimals) {
if (decimals <= 0 || decimals > 6) return num;
const decimal = Math.pow(10, parseInt(decimals));
return Math.round(num * decimal) / decimal;
}
static getFractionHtml(diviseur) { static getFractionHtml(diviseur) {
if (!diviseur || diviseur <= 1) return undefined; if (!diviseur || diviseur <= 1) return undefined;
switch (diviseur || 1) { switch (diviseur || 1) {
@ -64,9 +57,9 @@ export class Misc {
} }
} }
static classify(items, classifier = it => it.type) { static classify(items, classifier = it => it.type, transform = it => it) {
let itemsBy = {}; let itemsBy = {};
Misc.classifyInto(itemsBy, items, classifier); Misc.classifyInto(itemsBy, items, classifier, transform);
return itemsBy; return itemsBy;
} }
@ -81,7 +74,7 @@ export class Misc {
return itemsBy; return itemsBy;
} }
static classifyInto(itemsBy, items, classifier = it => it.type) { static classifyInto(itemsBy, items, classifier = it => it.type, transform = it => it) {
for (const item of items) { for (const item of items) {
const classification = classifier(item); const classification = classifier(item);
let list = itemsBy[classification]; let list = itemsBy[classification];
@ -89,16 +82,31 @@ export class Misc {
list = []; list = [];
itemsBy[classification] = list; itemsBy[classification] = list;
} }
list.push(item); list.push(transform(item));
} }
} }
static rollOneOf(array) {
return array[new Roll("1d" + array.length).evaluate().total - 1];
}
static distinct(array) { static distinct(array) {
return [...new Set(array)]; return [...new Set(array)];
} }
static actorData(actor) {
return Misc.data(actor);
}
static itemData(item) {
return Misc.data(item);
}
static data(it) { static data(it) {
if (it instanceof Actor || it instanceof Item || it instanceof Combatant) { if (it instanceof Item) {
return it.data;
}
if (it instanceof Actor) {
return it.data; return it.data;
} }
return it; return it;
@ -108,22 +116,13 @@ export class Misc {
return Misc.data(it)?.data ?? {} return Misc.data(it)?.data ?? {}
} }
static getEntityTypeLabel(entity) {
const documentName = entity?.documentName;
const type = entity?.data.type;
if (documentName === 'Actor' || documentName === 'Item') {
const label = CONFIG[documentName]?.typeLabels?.[type] ?? type;
return game.i18n.has(label) ? game.i18n.localize(label) : t;
}
return type;
}
static connectedGMOrUser(ownerId = undefined) { static connectedGMOrUser(ownerId = undefined) {
if (ownerId && game.user.id == ownerId) { if (ownerId && game.user.id == ownerId){
return ownerId; return ownerId;
} }
return (game.user.isGM ? game.user.id : game.users.entities.find(u => u.isGM && u.active)?.id) ?? game.user.id; return (game.user.isGM ? game.user.id : game.users.entities.find(u => u.isGM && u.active)?.id) ?? game.user.id;
} }
static isElectedUser() { static isElectedUser() {
return game.user.id == Misc.connectedGMOrUser(); return game.user.id == Misc.connectedGMOrUser();
} }

View File

@ -1,5 +1,4 @@
import { Misc } from "./misc.js" import { Misc } from "./misc.js"
import { RdDDice } from "./rdd-dice.js";
const poesieHautReve = [ const poesieHautReve = [
{ {
@ -65,8 +64,8 @@ const poesieHautReve = [
] ]
export class Poetique { export class Poetique {
static async getExtrait(){ static getExtrait(){
return await RdDDice.rollOneOf(poesieHautReve); return Misc.rollOneOf(poesieHautReve);
} }
} }

View File

@ -1,46 +1,51 @@
/* -------------------------------------------- */ /* -------------------------------------------- */
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
const matchOperations = new RegExp(/@(\w*){([\w\-]+)}/ig);
const matchOperationTerms = new RegExp(/@(\w*){([\w\-]+)}/i);
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDAlchimie { export class RdDAlchimie {
/* -------------------------------------------- */ /* -------------------------------------------- */
static processManipulation(recetteData, actorId = undefined) { static processManipulation( recette, actorId = undefined ) {
//console.log("CALLED", recette, recette.isOwned, actorId ); //console.log("CALLED", recette, recette.isOwned, actorId );
let manip = recetteData.data.manipulation; let manip = duplicate(recette.data.manipulation);
let matchArray = manip.match(matchOperations); let reg1 = new RegExp(/@(\w*){([\w\-]+)}/ig);
if (matchArray) { let matchArray = manip.match( reg1 );
for (let matchStr of matchArray) { if ( matchArray ) {
let result = matchStr.match(matchOperationTerms); for( let matchStr of matchArray) {
let reg2 = new RegExp(/@(\w*){([\w\-]+)}/i);
let result = matchStr.match(reg2);
//console.log("RESULT ", result); //console.log("RESULT ", result);
if (result[1] && result[2]) { if ( result[1] && result[2]) {
let commande = Misc.upperFirst(result[1]); let commande = Misc.upperFirst( result[1] );
let replacement = this[`_alchimie${commande}`](recetteData, result[2], actorId); let replacement = this[`_alchimie${commande}`](recette, result[2], actorId);
manip = manip.replace(result[0], replacement); manip = manip.replace( result[0], replacement);
} }
} }
} }
recetteData.data.manipulation_update = manip; recette.data.manipulation_update = manip;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _alchimieCouleur(recette, couleurs, actorId) { static _alchimieCouleur( recette, couleurs, actorId ) {
if (actorId) { let replacement
return `<span class="alchimie-tache"><a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="couleur" data-alchimie-data="${couleurs}">couleur ${couleurs}</a></span>`; if ( actorId ) {
replacement = `<span class="alchimie-tache"><a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="couleur" data-alchimie-data="${couleurs}">couleur ${couleurs}</a></span>`;
} else { } else {
return `<span class="alchimie-tache">couleur ${couleurs} </span>`; replacement = `<span class="alchimie-tache">couleur ${couleurs} </span>`;
} }
return replacement;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static _alchimieConsistance(recette, consistances, actorId) { static _alchimieConsistance( recette, consistances, actorId ) {
if (actorId) { let replacement
return `<span class="alchimie-tache"><a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="consistance" data-alchimie-data="${consistances}">consistance ${consistances}</a></span>`; if ( actorId ) {
replacement = `<span class="alchimie-tache"><a data-recette-id="${recette._id}" data-actor-id="${actorId}" data-alchimie-tache="consistance" data-alchimie-data="${consistances}">consistance ${consistances}</a></span>`;
} else { } else {
return `<span class="alchimie-tache">consistance ${consistances} </span>`; replacement = `<span class="alchimie-tache">consistance ${consistances} </span>`;
} }
return replacement;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -53,13 +58,4 @@ export class RdDAlchimie {
} }
return Math.min(0, -composantes); return Math.min(0, -composantes);
} }
static getCaracTache(tache) {
switch (tache) {
case "consistance": return 'dexterite';
case "couleur": return 'vue';
}
return 'intellect';
}
} }

View File

@ -3,7 +3,7 @@
* Extend the base Dialog entity by defining a custom window to perform roll. * Extend the base Dialog entity by defining a custom window to perform roll.
* @extends {Dialog} * @extends {Dialog}
*/ */
export class RdDAstrologieEditeur extends Dialog { export class RdDAstrologieEditeur extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
constructor(html, calendrier, calendrierData) { constructor(html, calendrier, calendrierData) {
@ -23,9 +23,9 @@
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async resetNombreAstraux() { resetNombreAstraux() {
game.system.rdd.calendrier.resetNombreAstral(); game.system.rdd.calendrier.resetNombreAstral();
await game.system.rdd.calendrier.rebuildListeNombreAstral(); game.system.rdd.calendrier.rebuildListeNombreAstral();
game.system.rdd.calendrier.showAstrologieEditor(); game.system.rdd.calendrier.showAstrologieEditor();
} }

View File

@ -11,12 +11,11 @@ export class RdDAstrologieJoueur extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async create(actor, dialogConfig) { static async create(actor, dialogConfig) {
let data = { let data = { nombres: this.organizeNombres( actor),
nombres: this.organizeNombres(actor), dates: game.system.rdd.calendrier.getJoursSuivants( 10 ),
dates: game.system.rdd.calendrier.getJoursSuivants(10),
etat: actor.getEtatGeneral(), etat: actor.getEtatGeneral(),
ajustementsConditions: CONFIG.RDD.ajustementsConditions, ajustementsConditions: CONFIG.RDD.ajustementsConditions,
astrologie: RdDItemCompetence.findCompetence(actor.data.items, 'Astrologie') astrologie: RdDItemCompetence.findCompetence( actor.data.items, 'Astrologie')
} }
const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', data); const html = await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', data);
let options = { classes: ["rdddialog"], width: 600, height: 500, 'z-index': 99999 }; let options = { classes: ["rdddialog"], width: 600, height: 500, 'z-index': 99999 };
@ -27,7 +26,7 @@ export class RdDAstrologieJoueur extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
constructor(html, actor, data) { constructor(html, actor, data ) {
let myButtons = { let myButtons = {
saveButton: { label: "Fermer", callback: html => this.quitDialog() } saveButton: { label: "Fermer", callback: html => this.quitDialog() }
@ -36,7 +35,7 @@ export class RdDAstrologieJoueur extends Dialog {
// Get all n // Get all n
// Common conf // Common conf
let dialogConf = { content: html, title: "Nombres Astraux", buttons: myButtons, default: "saveButton" }; let dialogConf = { content: html, title: "Nombres Astraux", buttons: myButtons, default: "saveButton" };
let dialogOptions = { classes: ["rdddialog"], width: 600, height: 300, 'z-index': 99999 }; let dialogOptions = { classes: ["rdddialog"], width: 600, height: 300, 'z-index': 99999 } ;
super(dialogConf, dialogOptions); super(dialogConf, dialogOptions);
this.actor = actor; this.actor = actor;
@ -45,14 +44,14 @@ export class RdDAstrologieJoueur extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
static organizeNombres(actor) { static organizeNombres(actor) {
let itemNombres = actor.listItemsData('nombreastral'); let itemNombres = actor.data.items.filter( (item) => item.type == 'nombreastral');
let itemFiltered = {}; let itemFiltered = {};
for (let item of itemNombres) { for ( let item of itemNombres) {
if (itemFiltered[item.data.jourindex]) { if ( itemFiltered[item.data.jourindex] ) {
itemFiltered[item.data.jourindex].listValues.push(item.data.value); itemFiltered[item.data.jourindex].listValues.push(item.data.value);
} else { } else {
itemFiltered[item.data.jourindex] = { itemFiltered[item.data.jourindex] = {
listValues: [item.data.value], listValues: [ item.data.value ],
jourlabel: item.data.jourlabel jourlabel: item.data.jourlabel
} }
} }
@ -61,22 +60,21 @@ export class RdDAstrologieJoueur extends Dialog {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
requestJetAstrologie() { requestJetAstrologie( ) {
let data = { let data = { id: this.actor.data._id,
id: this.actor.data._id,
carac_vue: Misc.data(this.actor).data.carac['vue'].value, carac_vue: Misc.data(this.actor).data.carac['vue'].value,
etat: this.dataNombreAstral.etat, etat: this.dataNombreAstral.etat,
astrologie: this.dataNombreAstral.astrologie, astrologie: this.dataNombreAstral.astrologie,
conditions: $("#diffConditions").val(), conditions: $("#diffConditions").val(),
date: $("#joursAstrologie").val() date: $("#joursAstrologie").val()
} }
if (game.user.isGM) { if ( game.user.isGM) {
game.system.rdd.calendrier.requestNombreAstral(data); game.system.rdd.calendrier.requestNombreAstral( data );
} else { } else {
game.socket.emit("system.foundryvtt-reve-de-dragon", { game.socket.emit("system.foundryvtt-reve-de-dragon", {
msg: "msg_request_nombre_astral", msg: "msg_request_nombre_astral",
data: data data: data
}); } );
} }
this.close(); this.close();
} }

View File

@ -13,7 +13,7 @@ export class RdDAudio {
let audioData = context2file[context]; let audioData = context2file[context];
if ( audioData ) { if ( audioData ) {
let audioPath = "systems/foundryvtt-reve-de-dragon/sounds/" + audioData.file; let audioPath = "systems/foundryvtt-reve-de-dragon/sounds/" + audioData.file;
console.log(`foundryvtt-reve-de-dragon | Playing Sound: ${audioPath}`) console.log(`wfrp4e | Playing Sound: ${audioPath}`)
AudioHelper.play({ src: audioPath }, audioData.isGlobal); AudioHelper.play({ src: audioPath }, audioData.isGlobal);
} }
} }

View File

@ -5,8 +5,6 @@ import { HtmlUtility } from "./html-utility.js";
import { RdDResolutionTable } from "./rdd-resolution-table.js"; import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { RdDUtility } from "./rdd-utility.js"; import { RdDUtility } from "./rdd-utility.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
const dossierIconesHeures = 'systems/foundryvtt-reve-de-dragon/icons/heures/' const dossierIconesHeures = 'systems/foundryvtt-reve-de-dragon/icons/heures/'
@ -37,32 +35,16 @@ const MAX_NOMBRE_ASTRAL = 12;
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDCalendrier extends Application { export class RdDCalendrier extends Application {
static createCalendrierPos() {
return { top: 200, left: 200 };
}
static getCalendrier(index) {
let calendrier = {
heureRdD: 0, // Index dans heuresList
minutesRelative: 0,
indexJour: index,
annee: Math.floor(index / (28 * 12)),
moisRdD: Math.floor(index / 28) % 12,
jour: (index % 28) // Le calendrier stocke le jour en 0-27, mais en 1-28 à l'affichage
}
return calendrier;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async initCalendrier() { async initCalendrier() {
// Calendrier // Calendrier
this.calendrier = duplicate(game.settings.get("foundryvtt-reve-de-dragon", "calendrier")); this.calendrier = duplicate(game.settings.get("foundryvtt-reve-de-dragon", "calendrier"));
this.calendrier.annee = this.calendrier.annee ?? (this.calendrier.moisRdD == 12 ? 1 : 0); console.log("CALENDRIER", this.calendrier);
this.calendrier.moisRdD = (this.calendrier.moisRdD ?? 0) % 12;
//console.log("CALENDRIER", this.calendrier);
if (this.calendrier == undefined || this.calendrier.moisRdD == undefined) { if (this.calendrier == undefined || this.calendrier.moisRdD == undefined) {
this.calendrier = RdDCalendrier.getCalendrier(0); this.calendrier.heureRdD = 0; // Index dans heuresList
this.calendrier.minutesRelative = 0;
this.calendrier.moisRdD = 0; // Index dans heuresList
this.calendrier.jour = 0;
if (game.user.isGM) { // Uniquement si GM if (game.user.isGM) { // Uniquement si GM
game.settings.set("foundryvtt-reve-de-dragon", "calendrier", this.calendrier); game.settings.set("foundryvtt-reve-de-dragon", "calendrier", this.calendrier);
} }
@ -70,7 +52,8 @@ export class RdDCalendrier extends Application {
// position // position
this.calendrierPos = duplicate(game.settings.get("foundryvtt-reve-de-dragon", "calendrier-pos")); this.calendrierPos = duplicate(game.settings.get("foundryvtt-reve-de-dragon", "calendrier-pos"));
if (this.calendrierPos == undefined || this.calendrierPos.top == undefined) { if (this.calendrierPos == undefined || this.calendrierPos.top == undefined) {
this.calendrierPos = RdDCalendrier.createCalendrierPos(); this.calendrierPos.top = 200;
this.calendrierPos.left = 200;
if (game.user.isGM) { // Uniquement si GM if (game.user.isGM) { // Uniquement si GM
game.settings.set("foundryvtt-reve-de-dragon", "calendrier-pos", this.calendrierPos); game.settings.set("foundryvtt-reve-de-dragon", "calendrier-pos", this.calendrierPos);
} }
@ -78,15 +61,14 @@ export class RdDCalendrier extends Application {
// nombre astral // nombre astral
if (game.user.isGM) { if (game.user.isGM) {
this.listeNombreAstral = this._loadListNombreAstral(); this.listeNombreAstral = this._loadListNombreAstral();
await this.rebuildListeNombreAstral(false); // Ensure always up-to-date this.rebuildListeNombreAstral(); // Ensure always up-to-date
} }
console.log(this.calendrier, this.calendrierPos, this.listeNombreAstral); console.log(this.calendrier, this.calendrierPos, this.listeNombreAstral);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_loadListNombreAstral() { _loadListNombreAstral() {
const listeNombreAstraux = game.settings.get("foundryvtt-reve-de-dragon", "liste-nombre-astral"); return Object.values(game.settings.get("foundryvtt-reve-de-dragon", "liste-nombre-astral"));
return listeNombreAstraux ?? [];
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -99,18 +81,11 @@ export class RdDCalendrier extends Application {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getDateFromIndex(index) { getDateFromIndex(index = undefined) {
const date = RdDCalendrier.getCalendrier(index ?? this.getCurrentDayIndex()); if (!index) index = this.getCurrentDayIndex();
return (date.jour+1) + ' ' + heuresDef[heuresList[date.moisRdD]].label; let month = Math.floor(index / 28);
} let day = (index - (month * 28)) + 1;
return day + " " + heuresList[month];
/* -------------------------------------------- */
getNumericDateFromIndex(index = undefined) {
const dateRdD = RdDCalendrier.getCalendrier(index ?? this.getCurrentDayIndex());
return {
day: dateRdD.jour + 1,
month: heuresList[dateRdD.moisRdD]
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -120,13 +95,9 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
getCurrentDayIndex() { getCurrentDayIndex() {
return (((this.calendrier.annee ?? 0) * 12 + (this.calendrier.moisRdD ?? 0)) * 28) + (this.calendrier.jour ?? 0); return (this.calendrier.moisRdD * 28) + this.calendrier.jour;
} }
/* -------------------------------------------- */
getIndexFromDate(jour, mois) {
return (heuresDef[mois].heure * 28) + (jour - 1);
}
/* -------------------------------------------- */ /* -------------------------------------------- */
getJoursSuivants(num) { getJoursSuivants(num) {
let jours = []; let jours = [];
@ -139,17 +110,9 @@ export class RdDCalendrier extends Application {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async ajouterNombreAstral(index, showDice = true) { ajouterNombreAstral(index) {
const nombreAstral = await RdDDice.rollTotal("1dh", { showDice: showDice, hideDice: !showDice, rollMode: "selfroll" });
const dateFuture = this.getDateFromIndex(index);
if (showDice) {
ChatMessage.create({
whisper: ChatMessage.getWhisperRecipients("GM"),
content: `Le chiffre astrologique du ${dateFuture} sera le ${nombreAstral}`
});
}
return { return {
nombreAstral: nombreAstral, nombreAstral: new Roll("1d12").roll().total,
valeursFausses: [], valeursFausses: [],
index: index index: index
} }
@ -162,56 +125,45 @@ export class RdDCalendrier extends Application {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
resetNombreAstral() { getNombreAstral(indexDate) {
const liste = this.listeNombreAstral ?? this._loadListNombreAstral();
let astralData = liste.find((nombreAstral, i) => nombreAstral.index == indexDate);
if (!astralData?.nombreAstral) {
this.rebuildListeNombreAstral();
astralData = liste.find((nombreAstral, i) => nombreAstral.index == indexDate);
}
return astralData?.nombreAstral ?? "N/A";
}
/* -------------------------------------------- */
resetNombreAstral( ) {
this.listeNombreAstral = []; this.listeNombreAstral = [];
game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral); game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral);
game.socket.emit("system.foundryvtt-reve-de-dragon", {
msg: "msg_reset_nombre_astral",
data: {}
});
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
getNombreAstral(indexDate) { rebuildListeNombreAstral() {
if ( this.listeNombreAstral == undefined ) {
this.listeNombreAstral = this._loadListNombreAstral();
}
let liste = this.listeNombreAstral || [];
let astralData = liste.find((nombreAstral, i) => nombreAstral.index == indexDate);
return astralData?.nombreAstral;
}
/* -------------------------------------------- */
async rebuildListeNombreAstral(showDice = true) {
if (game.user.isGM) {
let jourCourant = this.getCurrentDayIndex(); let jourCourant = this.getCurrentDayIndex();
let jourFin = jourCourant + 12;
let newList = []; let newList = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11].map(i => this.ajouterNombreAstral(jourCourant + i));
for (let i = 0; i < 12; i++) { if (this.listeNombreAstral) {
let dayIndex = jourCourant + i; for (const na of this.listeNombreAstral) {
let na = this.listeNombreAstral.find( n => n.index == dayIndex); if (na && na.index >= jourCourant && na.index < jourFin) {
if ( na ) { newList[na.index - jourCourant] = na;
newList[i] = duplicate(na); }
} else {
newList[i] = await this.ajouterNombreAstral(dayIndex, showDice );
} }
} }
console.log("SAVE list", newList, jourCourant);
this.listeNombreAstral = newList; this.listeNombreAstral = newList;
game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral); game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral);
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async onCalendarButton(ev) { onCalendarButton(ev) {
ev.preventDefault(); ev.preventDefault();
const calendarAvance = ev.currentTarget.attributes['data-calendar-avance']; const calendarAvance = ev.currentTarget.attributes['data-calendar-avance'];
const calendarSet = ev.currentTarget.attributes['data-calendar-set']; const calendarSet = ev.currentTarget.attributes['data-calendar-set'];
if (calendarAvance) { if (calendarAvance) {
await this.incrementTime(Number(calendarAvance.value)); this.incrementTime(Number(calendarAvance.value));
} }
else if (calendarSet) { else if (calendarSet) {
this.positionnerHeure(Number(calendarSet.value)); this.positionnerHeure(Number(calendarSet.value));
@ -220,7 +172,7 @@ export class RdDCalendrier extends Application {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async incrementTime(minutes = 0) { incrementTime(minutes = 0) {
this.calendrier.minutesRelative += minutes; this.calendrier.minutesRelative += minutes;
if (this.calendrier.minutesRelative >= 120) { if (this.calendrier.minutesRelative >= 120) {
this.calendrier.minutesRelative -= 120; this.calendrier.minutesRelative -= 120;
@ -240,8 +192,14 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
incrementerJour() { incrementerJour() {
const index = this.getCurrentDayIndex() + 1; this.calendrier.jour += 1;
this.calendrier = RdDCalendrier.getCalendrier(index); if (this.calendrier.jour >= RDD_JOUR_PAR_MOIS) {
this.calendrier.jour -= RDD_JOUR_PAR_MOIS;
if (this.calendrier.jour <= 0)
this.calendrier.jour = 0;
this.calendrier.moisRdD += 1;
// Reconstruire les nombres astraux
}
this.rebuildListeNombreAstral(); this.rebuildListeNombreAstral();
} }
@ -252,10 +210,9 @@ export class RdDCalendrier extends Application {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async positionnerHeure(indexHeure) { positionnerHeure(indexHeure) {
if (indexHeure <= this.calendrier.heureRdD) { if (indexHeure <= this.calendrier.heureRdD)
this.incrementerJour(); this.incrementerJour();
}
this.calendrier.heureRdD = indexHeure; this.calendrier.heureRdD = indexHeure;
this.calendrier.minutesRelative = 0; this.calendrier.minutesRelative = 0;
game.settings.set("foundryvtt-reve-de-dragon", "calendrier", duplicate(this.calendrier)); game.settings.set("foundryvtt-reve-de-dragon", "calendrier", duplicate(this.calendrier));
@ -297,11 +254,10 @@ export class RdDCalendrier extends Application {
console.log(request); console.log(request);
let jourDiff = this.getLectureAstrologieDifficulte(request.date); let jourDiff = this.getLectureAstrologieDifficulte(request.date);
let niveau = Number(request.astrologie.data.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat); let niveau = Number(request.astrologie.data.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat);
let rollData = { let rollData= {
caracValue: request.carac_vue, caracValue: request.carac_vue,
finalLevel: niveau, finalLevel: niveau,
showDice: false, showDice: false
rollMode: "blindroll"
}; };
await RdDResolutionTable.rollData(rollData); await RdDResolutionTable.rollData(rollData);
let nbAstral = this.getNombreAstral(request.date); let nbAstral = this.getNombreAstral(request.date);
@ -309,10 +265,11 @@ export class RdDCalendrier extends Application {
request.isValid = true; request.isValid = true;
if (!request.rolled.isSuccess) { if (!request.rolled.isSuccess) {
request.isValid = false; request.isValid = false;
nbAstral = await RdDDice.rollTotal("1dhr" + nbAstral, { showDice: true, rollMode: "selfroll" }); let nbAstralFaux = new Roll("1d11").evaluate().total;
nbAstral = nbAstral==nbAstralFaux ? 12 : nbAstralFaux;
// Mise à jour des nombres astraux du joueur // Mise à jour des nombres astraux du joueur
let astralData = this.listeNombreAstral.find((nombreAstral, i) => nombreAstral.index == request.date); let astralData = this.listeNombreAstral.find((nombreAstral, i) => nombreAstral.index == request.date);
astralData.valeursFausses.push({ actorId: request.id, nombreAstral: nbAstral }); astralData.valeursFausses.push({ actorId: request.id, nombreAstral: nbAstralFaux });
game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral); game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral);
} }
request.nbAstral = nbAstral; request.nbAstral = nbAstral;
@ -328,27 +285,11 @@ export class RdDCalendrier extends Application {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
findHeure(heure) { getAjustementAstrologique(heureNaissance, name = 'inconnu') {
heure = Grammar.toLowerCaseNoAccentNoSpace(heure); let heure = Grammar.toLowerCaseNoAccent(heureNaissance);
let parHeureOuLabel = Object.values(heuresDef).filter(it => (it.heure + 1) == heure || Grammar.toLowerCaseNoAccentNoSpace(it.label) == heure); if (heure && heuresDef[heure]) {
if (parHeureOuLabel.length == 1) { let hn = heuresDef[heure].heure;
return parHeureOuLabel[0]; let chiffreAstral = this.getCurrentNombreAstral();
}
let parLabelPartiel = Object.values(heuresDef).filter(it => Grammar.toLowerCaseNoAccentNoSpace(it.label).includes(heure));
const matchLength = heure.length;
if(parLabelPartiel.length > 0) {
parLabelPartiel.sort((a,b)=> (a.label.length - matchLength)^2 - (b.label.length- matchLength)^2);
return parLabelPartiel[0];
}
return undefined;
}
/* -------------------------------------------- */
getAjustementAstrologique(heureNaissance, name = undefined) {
let defHeure = this.findHeure(heureNaissance);
if (defHeure) {
let hn = defHeure.heure;
let chiffreAstral = this.getCurrentNombreAstral() ?? 0;
let heureCourante = this.calendrier.heureRdD; let heureCourante = this.calendrier.heureRdD;
let ecartChance = (hn + chiffreAstral - heureCourante) % 12; let ecartChance = (hn + chiffreAstral - heureCourante) % 12;
switch (ecartChance) { switch (ecartChance) {
@ -358,12 +299,9 @@ export class RdDCalendrier extends Application {
case 3: case 9: return -2; case 3: case 9: return -2;
} }
} }
else if (name) { else {
ui.notifications.warn(name + " n'a pas d'heure de naissance, ou elle est incorrecte : " + heureNaissance); ui.notifications.warn(name + " n'a pas d'heure de naissance, ou elle est incorrecte : " + heureNaissance);
} }
else{
ui.notifications.warn(heureNaissance+" ne correspond pas à une heure de naissance");
}
return 0; return 0;
} }
@ -401,9 +339,9 @@ export class RdDCalendrier extends Application {
updateDisplay() { updateDisplay() {
let data = this.fillCalendrierData(); let data = this.fillCalendrierData();
// Rebuild data // Rebuild data
let dateHTML = `Jour ${data.jourMois} de ${data.nomMois} (${data.nomSaison})` let dateHTML = `Jour ${data.jourMois} de ${data.nomMois} (${data.nomSaison})`;
if (game.user.isGM) { if (game.user.isGM) {
dateHTML = dateHTML + " - NA: " + (this.getCurrentNombreAstral() ?? "indéterminé"); dateHTML = dateHTML + " - NA: " + this.getCurrentNombreAstral();
} }
for (let handle of document.getElementsByClassName("calendar-date-rdd")) { for (let handle of document.getElementsByClassName("calendar-date-rdd")) {
handle.innerHTML = dateHTML; handle.innerHTML = dateHTML;
@ -420,21 +358,21 @@ export class RdDCalendrier extends Application {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async saveEditeur(calendrierData) { saveEditeur(calendrierData) {
this.calendrier.minutesRelative = Number(calendrierData.minutesRelative); this.calendrier.minutesRelative = Number(calendrierData.minutesRelative);
this.calendrier.jour = Number(calendrierData.jourMois) - 1; this.calendrier.jour = Number(calendrierData.jourMois) - 1;
this.calendrier.moisRdD = heuresList.findIndex(mois => mois === calendrierData.moisKey); this.calendrier.moisRdD = heuresList.findIndex(mois => mois === calendrierData.moisKey);
this.calendrier.heureRdD = heuresList.findIndex(heure => heure === calendrierData.heureKey);; // Index dans heuresList this.calendrier.heureRdD = heuresList.findIndex(heure => heure === calendrierData.heureKey);; // Index dans heuresList
game.settings.set("foundryvtt-reve-de-dragon", "calendrier", duplicate(this.calendrier)); game.settings.set("foundryvtt-reve-de-dragon", "calendrier", duplicate(this.calendrier));
await this.rebuildListeNombreAstral(); this.rebuildListeNombreAstral();
this.updateDisplay();
game.socket.emit("system.foundryvtt-reve-de-dragon", { game.socket.emit("system.foundryvtt-reve-de-dragon", {
msg: "msg_sync_time", msg: "msg_sync_time",
data: duplicate(this.calendrier) data: duplicate(this.calendrier)
}); });
this.updateDisplay();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -474,12 +412,12 @@ export class RdDCalendrier extends Application {
/* -------------------------------------------- */ /* -------------------------------------------- */
/** @override */ /** @override */
async activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM); HtmlUtility._showControlWhen($(".gm-only"), game.user.isGM);
await this.updateDisplay(); this.updateDisplay();
html.find('.calendar-btn').click(ev => this.onCalendarButton(ev)); html.find('.calendar-btn').click(ev => this.onCalendarButton(ev));

View File

@ -1,5 +1,4 @@
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js";
const tableCaracDerivee = { const tableCaracDerivee = {
// xp: coût pour passer du niveau inférieur à ce niveau // xp: coût pour passer du niveau inférieur à ce niveau
@ -39,6 +38,29 @@ const tableCaracDerivee = {
export class RdDCarac { export class RdDCarac {
/* -------------------------------------------- */
static findCarac(carac, name) {
name = Grammar.toLowerCaseNoAccent(name);
const pairs = Object.entries(carac)
.filter(([key, value]) => key.includes(name) || Grammar.toLowerCaseNoAccent(value.label).includes(name));
let c = pairs.find(([key, value]) => key == name || Grammar.toLowerCaseNoAccent(value.label) == name);
if (c) {
return c[1];
}
pairs.sort((a, b) => a[0].length- b[0].length);
if (pairs.length > 0) {
c = pairs[0][1];
if (pairs.length > 1) {
const labels = pairs.map(pair => pair[1].label).reduce((a, b) => `${a}<br>${b}`);
ui.notifications.info(`Plusieurs caractéristiques possibles:<br>${labels}<br>La première sera choisie: ${c.label}.`);
}
return c;
}
return undefined;
}
static isAgiliteOuDerivee(selectedCarac) { static isAgiliteOuDerivee(selectedCarac) {
return selectedCarac?.label.match(/(Agilité|Dérobée)/); return selectedCarac?.label.match(/(Agilité|Dérobée)/);
} }
@ -52,19 +74,17 @@ export class RdDCarac {
return selectedCarac?.label?.toLowerCase()?.match(/r(e|ê)ve(( |-)actuel)?/); return selectedCarac?.label?.toLowerCase()?.match(/r(e|ê)ve(( |-)actuel)?/);
} }
static isIgnoreEtatGeneral(rollData) { static isIgnoreEtatGeneral(selectedCarac, competence) {
const selectedCarac = rollData.selectedCarac;
return !selectedCarac || return !selectedCarac ||
rollData.ethylisme ||
RdDCarac.isChance(selectedCarac) || RdDCarac.isChance(selectedCarac) ||
(RdDCarac.isReve(selectedCarac) && !rollData.competence); (RdDCarac.isReve(selectedCarac) && !competence);
} }
static computeTotal(carac, beaute = undefined) { static computeTotal(carac, beaute = undefined) {
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((a, b) => a + b, 0);
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0); const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0);
return total + beauteSuperieur10; return total + beauteSuperieur10;
} }
@ -97,7 +117,7 @@ export class RdDCarac {
* ainsi que de Perception active et volontaire. * ainsi que de Perception active et volontaire.
*/ */
static isActionPhysique(selectedCarac) { static isActionPhysique(selectedCarac) {
return Grammar.toLowerCaseNoAccent(selectedCarac?.label)?.match(/(apparence|force|agilite|dexterite|vue|ouie|odorat|empathie|melee|tir|lancer|derobee)/); return Grammar.toLowerCaseNoAccent(selectedCarac?.label).match(/(apparence|force|agilite|dexterite|vue|ouie|odorat|empathie|melee|tir|lancer|derobee)/);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -75,36 +75,38 @@ export class RdDCombatManager extends Combat {
const currentId = this.combatant._id; const currentId = this.combatant._id;
// calculate initiative // calculate initiative
for (let cId = 0; cId < ids.length; cId++) { for (let cId = 0; cId < ids.length; cId++) {
const combatant = this.getCombatant(ids[cId]); const c = this.getCombatant(ids[cId]);
//if (!c) return results; //if (!c) return results;
let rollFormula = formula; // Init per default let rollFormula = formula; // Init per default
console.log("RR :", rollFormula);
if (!rollFormula) { if (!rollFormula) {
let armeCombat, competence; let armeCombat, competence;
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') { if (c.actor.data.type == 'creature' || c.actor.data.type == 'entite') {
for (const competenceItemData of combatant.actor.data.items) { for (const competenceItemData of c.actor.data.items) {
if (competenceItemData.data.iscombat) { if (competenceItemData.data.iscombat) {
competence = duplicate(competenceItemData); competence = duplicate(competenceItemData);
} }
} }
rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, competence.data.carac_value) + ")/100)"; rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, competence.data.carac_value) + ")/100)";
} else { } else {
for (const itemData of combatant.actor.data.items) { for (const itemData of c.actor.data.items) {
if (itemData.type == "arme" && itemData.data.equipe) { if (itemData.type == "arme" && itemData.data.equipe) {
armeCombat = duplicate(itemData); armeCombat = duplicate(itemData);
} }
} }
let compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.data.competence; let compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.data.competence;
competence = RdDItemCompetence.findCompetence(combatant.actor.data.items, compName); competence = RdDItemCompetence.findCompetence(c.actor.data.items, compName);
let bonusEcaille = (armeCombat && armeCombat.data.magique) ? armeCombat.data.ecaille_efficacite : 0; let bonusEcaille = (armeCombat && armeCombat.data.magique) ? armeCombat.data.ecaille_efficacite : 0;
rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, Misc.data(combatant.actor).data.carac[competence.data.defaut_carac].value, bonusEcaille) + ")/100)"; rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, Misc.data(c.actor).data.carac[competence.data.defaut_carac].value, bonusEcaille) + ")/100)";
} }
} }
//console.log("Combatat", c); //console.log("Combatat", c);
const roll = combatant.getInitiativeRoll(rollFormula); console.log("RR :", rollFormula);
const roll = super._getInitiativeRoll(c, rollFormula);
if (roll.total <= 0) roll.total = 0.00; if (roll.total <= 0) roll.total = 0.00;
console.log("Compute init for", rollFormula, roll.total); console.log("Compute init for", rollFormula, roll.total);
await this.updateEmbeddedDocuments("Combatant", [{ _id: combatant._id, initiative: roll.total }]); await this.updateEmbeddedEntity("Combatant", { _id: c._id, initiative: roll.total });
// Send a chat message // Send a chat message
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode"); let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
@ -112,12 +114,12 @@ export class RdDCombatManager extends Combat {
{ {
speaker: { speaker: {
scene: canvas.scene._id, scene: canvas.scene._id,
actor: combatant.actor ? combatant.actor._id : null, actor: c.actor ? c.actor._id : null,
token: combatant.token._id, token: c.token._id,
alias: combatant.token.name, alias: c.token.name,
sound: CONFIG.sounds.dice, sound: CONFIG.sounds.dice,
}, },
flavor: `${combatant.token.name} a fait son jet d'Initiative (${messageOptions.initInfo}) flavor: `${c.token.name} a fait son jet d'Initiative (${messageOptions.initInfo})
<br> <br>
`, `,
}, },
@ -143,31 +145,35 @@ export class RdDCombatManager extends Combat {
// Gestion des armes 1/2 mains // Gestion des armes 1/2 mains
let armesEquipe = []; let armesEquipe = [];
for (const arme of armes) { for (const arme of armes) {
let armeData = Misc.data(arme); if (arme.data.equipe) {
if (armeData.data.equipe) { armesEquipe.push(arme);
let compData = competences.map(c => Misc.data(c)).find(c => c.name == armeData.data.competence); let comp = competences.find(c => c.name == arme.data.competence);
arme.data.initiative = RdDCombatManager.calculInitiative(arme.data.niveau, carac[comp.data.defaut_carac].value);
armesEquipe.push(armeData);
armeData.data.initiative = RdDCombatManager.calculInitiative(armeData.data.niveau, carac[compData.data.defaut_carac].value);
// Dupliquer les armes pouvant être à 1 main et 2 mains en patchant la compétence // Dupliquer les armes pouvant être à 1 main et 2 mains en patchant la compétence
if (armeData.data.unemain && !armeData.data.deuxmains) { if (arme.data.unemain && !arme.data.deuxmains) {
armeData.data.mainInfo = "(1m)"; arme.data.mainInfo = "(1m)";
} else if (!armeData.data.unemain && armeData.data.deuxmains) { } else if (!arme.data.unemain && arme.data.deuxmains) {
armeData.data.mainInfo = "(2m)"; arme.data.mainInfo = "(2m)";
} else if (armeData.data.unemain && armeData.data.deuxmains) { } else if (arme.data.unemain && arme.data.deuxmains) {
armeData.data.mainInfo = "(1m)"; arme.data.mainInfo = "(1m)";
let arme2main = duplicate(armeData); let arme2main = duplicate(arme);
arme2main.data.mainInfo = "(2m)"; arme2main.data.mainInfo = "(2m)";
arme2main.data.dommages = arme2main.data.dommages.split("/")[1]; // Existence temporaire uniquement dans la liste des armes, donc OK arme2main.data.dommages = arme2main.data.dommages.split("/")[1]; // Existence temporaire uniquement dans la liste des armes, donc OK
arme2main.data.competence = arme2main.data.competence.replace(" 1 main", " 2 mains"); // Replace ! arme2main.data.competence = arme2main.data.competence.replace(" 1 main", " 2 mains"); // Replace !
let comp = Misc.data(competences.find(c => c.name == arme2main.data.competence)); let comp = competences.find(c => c.name == arme2main.data.competence);
arme2main.data.niveau = comp.data.niveau; arme2main.data.niveau = comp.data.niveau;
arme2main.data.initiative = RdDCombatManager.calculInitiative(arme2main.data.niveau, carac[comp.data.defaut_carac].value); arme2main.data.initiative = RdDCombatManager.calculInitiative(arme2main.data.niveau, carac[comp.data.defaut_carac].value);
armesEquipe.push(arme2main); armesEquipe.push(arme2main);
} }
} }
} }
return armesEquipe.sort(Misc.ascending(armeData => armeData.name + (armeData.data.mainInfo ?? ''))); return armesEquipe.sort((a, b) => {
const nameA = a.name + (a.data.mainInfo ?? '');
const nameB = b.name + (b.data.mainInfo ?? '');
if (nameA > nameB) return 1;
if (nameA < nameB) return -1;
return 0;
});
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -185,6 +191,7 @@ export class RdDCombatManager extends Combat {
} else { } else {
// Recupération des items 'arme' // Recupération des items 'arme'
let armes = items.filter(it => RdDItemArme.isArmeUtilisable(it)) let armes = items.filter(it => RdDItemArme.isArmeUtilisable(it))
.map(arme => duplicate(arme)) /* pas de changements aux armes d'origine */
.concat(RdDItemArme.mainsNues()); .concat(RdDItemArme.mainsNues());
let competences = items.filter(it => it.type == 'competence'); let competences = items.filter(it => it.type == 'competence');
@ -266,7 +273,7 @@ export class RdDCombatManager extends Combat {
let initOffset = 0; let initOffset = 0;
let caracForInit = 0; let caracForInit = 0;
let compNiveau = 0; let compNiveau = 0;
let compData = { name: "Aucune" }; let competence = { name: "Aucune" };
if (combatant.actor.getSurprise() == "totale") { if (combatant.actor.getSurprise() == "totale") {
initOffset = -1; // To force 0 initOffset = -1; // To force 0
initInfo = "Surprise Totale" initInfo = "Surprise Totale"
@ -281,24 +288,24 @@ export class RdDCombatManager extends Combat {
initInfo = "Draconic" initInfo = "Draconic"
} else { } else {
initOffset = 3; // Melée = 3.XX initOffset = 3; // Melée = 3.XX
compData = Misc.data(RdDItemCompetence.findCompetence(combatant.actor.data.items, arme.data.competence)); competence = RdDItemCompetence.findCompetence(combatant.actor.data.items, arme.data.competence);
compNiveau = compData.data.niveau; compNiveau = competence.data.niveau;
initInfo = arme.name + " / " + arme.data.competence; initInfo = arme.name + " / " + arme.data.competence;
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') { if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
caracForInit = compData.data.carac_value; caracForInit = competence.data.carac_value;
if (compData.data.categorie == "lancer") { if (competence.data.categorie == "lancer") {
initOffset = 5; initOffset = 5;
} }
} else { } else {
caracForInit = Misc.data(combatant.actor).data.carac[compData.data.defaut_carac].value; caracForInit = Misc.data(combatant.actor).data.carac[competence.data.defaut_carac].value;
if (compData.data.categorie == "lancer") { // Offset de principe pour les armes de jet if (competence.data.categorie == "lancer") { // Offset de principe pour les armes de jet
initOffset = 4; initOffset = 4;
} }
if (compData.data.categorie == "tir") { // Offset de principe pour les armes de jet if (competence.data.categorie == "tir") { // Offset de principe pour les armes de jet
initOffset = 5; initOffset = 5;
} }
if (compData.data.categorie == "melee") { // Offset de principe pour les armes de jet if (competence.data.categorie == "melee") { // Offset de principe pour les armes de jet
initOffset = 3; initOffset = 3;
} }
} }
@ -338,8 +345,8 @@ export class RdDCombat {
static init() { static init() {
this.initStorePasseArmes(); this.initStorePasseArmes();
Hooks.on("updateCombat", (combat, change, options, userId) => { RdDCombat.onUpdateCombat(combat, change, options, userId) }); Hooks.on("updateCombat", (combat, data) => { RdDCombat.onUpdateCombat(combat, data) });
Hooks.on("preDeleteCombat", (combat, options, userId) => { RdDCombat.onPreDeleteCombat(combat, options, userId); }); Hooks.on("preDeleteCombat", (combat, options) => { RdDCombat.onPreDeleteCombat(combat, options); });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -363,14 +370,14 @@ export class RdDCombat {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static onUpdateCombat(combat, change, options, userId) { static onUpdateCombat(combat, data) {
if (combat.data.round != 0 && combat.turns && combat.data.active) { if (combat.data.round != 0 && combat.turns && combat.data.active) {
RdDCombat.combatNouveauTour(combat); RdDCombat.combatNouveauTour(combat);
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static onPreDeleteCombat(combat, options, userId) { static onPreDeleteCombat(combat, options) {
if (game.user.isGM) { if (game.user.isGM) {
combat.cleanItemUse(); combat.cleanItemUse();
ChatUtility.removeChatMessageContaining(`<div data-combatid="${combat.id}" data-combatmessage="actor-turn-summary">`) ChatUtility.removeChatMessageContaining(`<div data-combatid="${combat.id}" data-combatmessage="actor-turn-summary">`)
@ -393,13 +400,11 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
static combatNouveauTour(combat) { static combatNouveauTour(combat) {
if (Misc.isElectedUser()) { if (Misc.isElectedUser()) {
let turn = combat.turns.find(t => t.token?.id == combat.current.tokenId); let turn = combat.turns.find(t => t.tokenId == combat.current.tokenId);
if (turn?.actor) { this.displayActorCombatStatus(combat, turn.actor);
RdDCombat.displayActorCombatStatus(combat, turn.actor);
// TODO Playaudio for player?? // TODO Playaudio for player??
} }
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static isActive() { static isActive() {
@ -511,12 +516,15 @@ export class RdDCombat {
RdDCombat._deleteDefense(attackerRoll.passeArme); RdDCombat._deleteDefense(attackerRoll.passeArme);
RdDCombat._deleteAttaque(data.attackerId); RdDCombat._deleteAttaque(data.attackerId);
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static onMsgDefense(msg) { static onMsgDefense(msg) {
let defenderToken = canvas.tokens.get(msg.defenderTokenId); let defenderToken = canvas.tokens.get(msg.defenderTokenId);
if (!game.user.isGM && !game.user.character) { // vérification / sanity check
ui.notifications.error("Le joueur " + game.user.name + " n'est connecté à aucun personnage. Impossible de continuer.");
return;
}
if (defenderToken && Misc.isElectedUser()) { if (defenderToken && Misc.isElectedUser()) {
const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId); const rddCombat = RdDCombat.createForAttackerAndDefender(msg.attackerId, msg.defenderTokenId);
if (rddCombat) { if (rddCombat) {
@ -814,19 +822,21 @@ export class RdDCombat {
} }
// # utilisation esquive // # utilisation esquive
const esquive = Misc.data(this.defender.getCompetence("esquive")); let esquiveUsage = 0;
const corpsACorps = Misc.data(this.defender.getCompetence("Corps à corps")); let esquive = this.defender.getCompetence("esquive");
const esquiveUsage = esquive ? this.defender.getItemUse(esquive._id) : 0; if (esquive) {
esquiveUsage = this.defender.getItemUse(esquive._id);
}
const paramChatDefense = { const paramChatDefense = {
passeArme: attackerRoll.passeArme, passeArme: attackerRoll.passeArme,
essais: attackerRoll.essais, essais: attackerRoll.essais,
defender: Misc.data(this.defender), defender: this.defender,
attacker: Misc.data(this.attacker), attacker: this.attacker,
attackerId: this.attackerId, attackerId: this.attackerId,
esquiveUsage: esquiveUsage, esquiveUsage: esquiveUsage,
defenderTokenId: this.defenderTokenId, defenderTokenId: this.defenderTokenId,
mainsNues: attackerRoll.dmg.mortalite != 'mortel' && corpsACorps, mainsNues: attackerRoll.dmg.mortalite != 'mortel' && this.defender.getCompetence("Corps à corps"),
armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme), armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme),
diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0, diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0,
attaqueParticuliere: attackerRoll.particuliere, attaqueParticuliere: attackerRoll.particuliere,
@ -863,7 +873,7 @@ export class RdDCombat {
attackerId: this.attacker?.data._id, attackerId: this.attacker?.data._id,
defenderId: this.defender?.data._id, defenderId: this.defender?.data._id,
defenderTokenId: this.defenderTokenId, defenderTokenId: this.defenderTokenId,
defenderRoll: defenderRoll, defenderRoll: duplicate(defenderRoll),
paramChatDefense: paramChatDefense, paramChatDefense: paramChatDefense,
rollMode: true rollMode: true
} }
@ -899,7 +909,7 @@ export class RdDCombat {
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name), whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', { content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', {
attackerId: this.attackerId, attackerId: this.attackerId,
attacker: Misc.data(this.attacker), attacker: this.attacker,
defenderTokenId: this.defenderTokenId, defenderTokenId: this.defenderTokenId,
essais: attackerRoll.essais essais: attackerRoll.essais
}) })
@ -911,7 +921,7 @@ export class RdDCombat {
console.log("RdDCombat._onEchecTotal >>>", rollData); console.log("RdDCombat._onEchecTotal >>>", rollData);
const arme = rollData.arme; const arme = rollData.arme;
const avecArme = arme && arme.data.categorie_parade != 'sans-armes'; const avecArme = arme?.data.categorie_parade != 'sans-armes';
const action = (rollData.attackerRoll ? (arme ? "la parade" : "l'esquive") : "l'attaque"); const action = (rollData.attackerRoll ? (arme ? "la parade" : "l'esquive") : "l'attaque");
ChatUtility.createChatWithRollMode(this.defender.name, { ChatUtility.createChatWithRollMode(this.defender.name, {
content: `<strong>Maladresse à ${action}!</strong> ` + await RdDRollTables.getMaladresse({ arme: avecArme }) content: `<strong>Maladresse à ${action}!</strong> ` + await RdDRollTables.getMaladresse({ arme: avecArme })
@ -970,18 +980,17 @@ export class RdDCombat {
_prepareParade(attackerRoll, armeParade) { _prepareParade(attackerRoll, armeParade) {
const compName = armeParade.data.competence; const compName = armeParade.data.competence;
const armeAttaque = attackerRoll.arme; const armeAttaque = attackerRoll.arme;
const parade = Misc.data(this.defender.getCompetence(compName));
let defenderRoll = { let defenderRoll = {
passeArme: attackerRoll.passeArme, passeArme: attackerRoll.passeArme,
diffLibre: attackerRoll.diffLibre, diffLibre: attackerRoll.diffLibre,
attackerRoll: attackerRoll, attackerRoll: attackerRoll,
competence: parade, competence: this.defender.getCompetence(compName),
arme: armeParade, arme: armeParade,
surprise: this.defender.getSurprise(true), surprise: this.defender.getSurprise(true),
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(armeAttaque, armeParade), needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(armeAttaque, armeParade),
needResist: RdDItemArme.needArmeResist(armeAttaque, armeParade), needResist: RdDItemArme.needArmeResist(armeAttaque, armeParade),
carac: Misc.templateData(this.defender).carac, carac: this.defender.data.data.carac,
show: {} show: {}
}; };
@ -1027,7 +1036,7 @@ export class RdDCombat {
/* -------------------------------------------- */ /* -------------------------------------------- */
async esquive(attackerRoll) { async esquive(attackerRoll) {
const esquive = Misc.data(this.defender.getCompetence("esquive")); let esquive = this.defender.getCompetence("esquive");
if (esquive == undefined) { if (esquive == undefined) {
ui.notifications.error(this.defender.name + " n'a pas de compétence 'esquive'"); ui.notifications.error(this.defender.name + " n'a pas de compétence 'esquive'");
return; return;
@ -1061,7 +1070,7 @@ export class RdDCombat {
competence: competence, competence: competence,
surprise: this.defender.getSurprise(true), surprise: this.defender.getSurprise(true),
surpriseDefenseur: this.defender.getSurprise(true), surpriseDefenseur: this.defender.getSurprise(true),
carac: Misc.templateData(this.defender).carac, carac: this.defender.data.data.carac,
show: {} show: {}
}; };
@ -1129,7 +1138,7 @@ export class RdDCombat {
resistance -= perteResistance; resistance -= perteResistance;
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte'; defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
defenderRoll.show.perteResistance = perteResistance; defenderRoll.show.perteResistance = perteResistance;
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'data.resistance': resistance }]); this.defender.updateEmbeddedEntity("OwnedItem", { _id: defenderRoll.arme._id, 'data.resistance': resistance });
} }
} }
} else { } else {
@ -1146,7 +1155,7 @@ export class RdDCombat {
resistance -= dmg; resistance -= dmg;
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte'; defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
defenderRoll.show.perteResistance = dmg; defenderRoll.show.perteResistance = dmg;
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'data.resistance': resistance }]); this.defender.updateEmbeddedEntity("OwnedItem", { _id: defenderRoll.arme._id, 'data.resistance': resistance });
} }
} }
// Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132) // Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
@ -1220,14 +1229,14 @@ export class RdDCombat {
await this.computeRecul(defenderRoll); await this.computeRecul(defenderRoll);
this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll); this.defender.encaisserDommages(attackerRoll, this.attacker, defenderRoll);
} } else { // envoi à un GM: les joueurs n'ont pas le droit de modifier les personnages qu'ils ne possèdent pas
else { // envoi à un GM: les joueurs n'ont pas le droit de modifier les personnages qu'ils ne possèdent pas
game.socket.emit("system.foundryvtt-reve-de-dragon", { game.socket.emit("system.foundryvtt-reve-de-dragon", {
msg: "msg_encaisser", msg: "msg_encaisser",
data: { data: {
attackerId: this.attackerId, attackerId: this.attackerId,
defenderTokenId: defenderTokenId, defenderTokenId: defenderTokenId,
attackerRoll: attackerRoll attackerRoll: attackerRoll,
gmId: game.users.entities.find(u => u.isGM)?.id,
} }
}); });
} }
@ -1245,7 +1254,7 @@ export class RdDCombat {
return true; return true;
} }
let rolled = await RdDResolutionTable.roll(this.attacker.getReveActuel(), - Number(Misc.templateData(this.defender).carac.niveau.value)); let rolled = await RdDResolutionTable.roll(this.attacker.getReveActuel(), - Number(this.defender.data.data.carac.niveau.value));
let message = { let message = {
content: "Jet de points actuels de rêve à " + rolled.finalLevel + RdDResolutionTable.explain(rolled) + "<br>", content: "Jet de points actuels de rêve à " + rolled.finalLevel + RdDResolutionTable.explain(rolled) + "<br>",

View File

@ -1,6 +1,5 @@
/* -------------------------------------------- */ /* -------------------------------------------- */
import { DialogCreateSigneDraconique } from "./dialog-create-signedraconique.js";
import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetence } from "./item-competence.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDCarac } from "./rdd-carac.js"; import { RdDCarac } from "./rdd-carac.js";
@ -13,7 +12,7 @@ import { RdDUtility } from "./rdd-utility.js";
import { TMRRencontres } from "./tmr-rencontres.js"; import { TMRRencontres } from "./tmr-rencontres.js";
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
const rddRollNumeric = /^(\d+)\s*([\+\-]?\d+)?\s*(s)?/; const rddRollNumeric = /$(\d+)\s*([\+\-]?\d+)?\s*(s)?/;
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDCommands { export class RdDCommands {
@ -79,31 +78,10 @@ export class RdDCommands {
<br><strong>/payer 10d</strong> permet d'envoyer un message pour payer 10 deniers` <br><strong>/payer 10d</strong> permet d'envoyer un message pour payer 10 deniers`
}); });
rddCommands.registerCommand({ rddCommands.registerCommand({
path: ["/astro"], func: (content, msg, params) => RdDUtility.afficherHeuresChanceMalchance(RdDCommands.toParamString(params)), path: ["/astro"], func: (content, msg, params) => RdDUtility.afficherHeuresChanceMalchance(params[0]),
descr: `Affiche les heures de chance et de malchance selon l'heure de naissance donnée en argument. Exemples pour l'heure de la Lyre: descr: `Affiche les heures de chance et de malchance selon l'heure de naissance donnée en argument. Exemples:
<br><strong>/astro 7</strong> <br><strong>/astro Lyre</strong>`
<br><strong>/astro Lyre</strong>
<br><strong>/astro Lyr</strong>`
}); });
rddCommands.registerCommand({
path: ["/signe", "+"], func: (content, msg, params) => rddCommands.creerSignesDraconiques(),
descr: "Crée un signe draconique et l'ajoute aux haut-rêvants choisis."
});
rddCommands.registerCommand({
path: ["/signe", "-"], func: (content, msg, params) => rddCommands.supprimerSignesDraconiquesEphemeres(),
descr: "Supprime les signes draconiques éphémères"
});
rddCommands.registerCommand({
path: ["/stress"], func: (content, msg, params) => RdDUtility.distribuerStress(params[0], params[1], params[2]),
descr: `Distribue du stress aux personnages. Exemples:
<br><strong>/stress 6</strong> : Distribue 6 points des Stress à tout les personnages joueurs, sans raison renseignée
<br><strong>/stress 6 Tigre</strong> : Distribue 6 points des Stress à tout les personnages joueurs, à cause d'un Tigre Vert
<br><strong>/stress 6 Glou Paulo</strong> : Distribue 6 points de Stres à l'acteur connecté au joueur Paulo, à cause d'un Glou`
});
game.system.rdd.commands = rddCommands; game.system.rdd.commands = rddCommands;
} }
} }
@ -111,10 +89,6 @@ export class RdDCommands {
this.commandsTable = {}; this.commandsTable = {};
} }
static toParamString(params) {
return params.length == 1 ? params[0] : params.reduce((a, b) => `${a} ${b}`, '');
}
/* -------------------------------------------- */ /* -------------------------------------------- */
registerCommand(command) { registerCommand(command) {
this._addCommand(this.commandsTable, command.path, '', command); this._addCommand(this.commandsTable, command.path, '', command);
@ -214,7 +188,7 @@ export class RdDCommands {
/* -------------------------------------------- */ /* -------------------------------------------- */
static _chatAnswer(msg, content) { static _chatAnswer(msg, content) {
msg.whisper = [game.user.id]; msg.whisper = [game.user._id];
msg.content = content; msg.content = content;
ChatMessage.create(msg); ChatMessage.create(msg);
} }
@ -289,7 +263,7 @@ export class RdDCommands {
finalLevel: diff, finalLevel: diff,
showDice: true, showDice: true,
diviseurSignificative: significative ? 2 : 1, diviseurSignificative: significative ? 2 : 1,
show: { title: "Table de résolution"} show: { title: "Table de résolution" }
}; };
await RdDResolutionTable.rollData(rollData); await RdDResolutionTable.rollData(rollData);
RdDCommands._chatAnswer(msg, await RdDResolutionTable.buildRollDataHtml(rollData)); RdDCommands._chatAnswer(msg, await RdDResolutionTable.buildRollDataHtml(rollData));
@ -297,14 +271,16 @@ export class RdDCommands {
/* -------------------------------------------- */ /* -------------------------------------------- */
async rollDeDraconique(msg) { async rollDeDraconique(msg) {
let ddr = await RdDDice.rollTotal("1dr + 7", { showDice:true }); let ddr = new Roll("1dr + 7").evaluate();
RdDCommands._chatAnswer(msg, `Lancer d'un Dé draconique: ${ddr}`); ddr.showDice = true;
await RdDDice.showDiceSoNice(ddr);
RdDCommands._chatAnswer(msg, `Lancer d'un Dé draconique: ${ddr.total}`);
} }
async getTMRAleatoire(msg, params) { getTMRAleatoire(msg, params) {
if (params.length < 2) { if (params.length < 2) {
let type = params[0]; let type = params[0];
const tmr = await TMRUtility.getTMRAleatoire(type ? (it => it.type == type) : (it => true)); const tmr = TMRUtility.getTMRAleatoire(type ? (it => it.type == type) : (it => true));
RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`); RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`);
} }
else { else {
@ -336,20 +312,5 @@ export class RdDCommands {
} }
} }
async creerSignesDraconiques() {
DialogCreateSigneDraconique.createSigneForActors();
return true;
}
async supprimerSignesDraconiquesEphemeres() {
game.actors.forEach(actor => {
const ephemeres = actor.filterItems(item => Misc.data(item).type = 'signedraconique' && Misc.data(item).data.ephemere)
.map(item => item.id);
if (ephemeres.length > 0) {
actor.deleteEmbeddedDocuments("Item", ephemeres);
}
});
return true;
}
} }

View File

@ -1,29 +1,59 @@
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
/* -------------------------------------------- */
/**
* Mapping des types d'Item/Actor vers le nom d'affichage.
* Par défaut, on prend le type avec la première lettre
* majuscule, pas besoin d'ajouter tous les types.
*/
const typeDisplayName = {
"competence": "Compétence",
"herbe": "Plante",
"ingredient": "Ingrédient",
"queue": "Queue de dragon",
"ombre": "Ombre de Thanatos",
"souffle": "Souffle de Dragon",
"tete": "Tête de Dragon",
"ingredient": "Ingrédient",
"rencontresTMR": "Rencontre des TMR",
"competencecreature": "Compétence de créature",
"nombreastral": "Nombre astral",
"casetmr": "Effet sur TMR",
"recettealchimique": "Recette alchimique",
"recettecuisine": "Recette de cuisine",
"tarot": "Carte de tarot draconique",
"tache": "Tâche",
"meditation": "Méditation",
"musique": "Morceau de musique",
"chant": "Chanson",
"creature": "Créature",
"entite": "Entité",
"vehicule": "Véhicule"
}
export class RddCompendiumOrganiser { export class RddCompendiumOrganiser {
static init() { static init() {
Hooks.on('renderCompendium', async (pack, html, data) => RddCompendiumOrganiser.onRenderCompendium(pack, html, data)) Hooks.on('renderCompendium', async (pack, html, data) => RddCompendiumOrganiser.onRenderCompendium(pack, html, data))
} }
static async onRenderCompendium(compendium, html, data) { static async onRenderCompendium(pack, html, data) {
console.log('onRenderCompendium', compendium, html, data); console.log('onRenderCompendium', pack, html, data);
const pack = compendium.collection
if (pack.metadata.system === 'foundryvtt-reve-de-dragon') { if (pack.metadata.system === 'foundryvtt-reve-de-dragon') {
const content = await pack.getContent();
html.find('.directory-item').each((i, element) => { html.find('.directory-item').each((i, element) => {
RddCompendiumOrganiser.setEntityTypeName(pack, element); let entity = content.find(it => it._id === element.dataset.entryId);
if (entity?.entity === 'Actor' || entity?.entity === 'Item') {
const typeName = typeDisplayName[entity.data.type] ?? Misc.upperFirst(entity.data.type);
RddCompendiumOrganiser.insertEntityType(element, typeName);
}
}); });
} }
} }
static async setEntityTypeName(pack, element) { static insertEntityType(element, type) {
const label = Misc.getEntityTypeLabel(await pack.getDocument(element.dataset.documentId)); element.children[1].insertAdjacentHTML('afterbegin', `<label>${type}: </label>`);
RddCompendiumOrganiser.insertEntityType(element, label);
}
static insertEntityType(element, label) {
if (label) {
element.children[1].insertAdjacentHTML('afterbegin', `<label class="type-compendium">${label}: </label>`);
}
} }
} }

View File

@ -25,7 +25,7 @@ export class De7 extends Die {
return { return {
type: "d7", type: "d7",
font: "HeuresDraconiques", font: "HeuresDraconiques",
fontScale: 0.7, fontScale : 0.7,
labels: ['1', '2', '3', '4', '5', '6', 'd', '0'], labels: ['1', '2', '3', '4', '5', '6', 'd', '0'],
system: system system: system
} }
@ -36,7 +36,7 @@ export class De7 extends Die {
super(termData); super(termData);
} }
async evaluate() { evaluate() {
super.evaluate(); super.evaluate();
this.explode("x=8"); this.explode("x=8");
return this; return this;
@ -46,11 +46,11 @@ export class De7 extends Die {
return this.values.filter(it => it != 8).reduce(Misc.sum(), 0); return this.values.filter(it => it != 8).reduce(Misc.sum(), 0);
} }
getResultLabel(diceTerm) { static getResultLabel(result) {
switch (diceTerm.result) { switch (result) {
case 7: return imgSigneDragon; case 7: return imgSigneDragon;
} }
return diceTerm.result.toString(); return result;
} }
} }
@ -62,7 +62,7 @@ export class DeDraconique extends Die {
return { return {
type: "dr", type: "dr",
font: "HeuresDraconiques", font: "HeuresDraconiques",
fontScale: 0.7, fontScale : 0.7,
labels: ['1', '2', '3', '4', '5', '6', 'd', '0'], labels: ['1', '2', '3', '4', '5', '6', 'd', '0'],
system: system system: system
} }
@ -73,7 +73,7 @@ export class DeDraconique extends Die {
super(termData); super(termData);
} }
async evaluate() { evaluate() {
super.evaluate(); super.evaluate();
this.explode("x=7"); this.explode("x=7");
return this; return this;
@ -83,12 +83,12 @@ export class DeDraconique extends Die {
return this.values.filter(it => it != 8).reduce(Misc.sum(), 0); return this.values.filter(it => it != 8).reduce(Misc.sum(), 0);
} }
getResultLabel(diceTerm) { static getResultLabel(result) {
switch (diceTerm.result) { switch (result) {
case 7: return imgSigneDragon; case 7: return imgSigneDragon;
case 8: return '0'; case 8: return 0;
} }
return diceTerm.result.toString(); return result;
} }
} }
@ -112,8 +112,8 @@ export class DeHeure extends Die {
super(termData); super(termData);
} }
getResultLabel(diceTerm) { static getResultLabel(result) {
return img(imagesHeures[diceTerm.result - 1]); return img(imagesHeures[result-1]);
} }
} }
@ -123,33 +123,6 @@ export class RdDDice {
CONFIG.Dice.terms[DeDraconique.DENOMINATION] = DeDraconique; CONFIG.Dice.terms[DeDraconique.DENOMINATION] = DeDraconique;
CONFIG.Dice.terms[DeHeure.DENOMINATION] = DeHeure; CONFIG.Dice.terms[DeHeure.DENOMINATION] = DeHeure;
} }
static onReady() {
if (game.modules.get("dice-so-nice")?.active) {
if (game.settings.get("core", "noCanvas")) {
ui.notifications.warn("Dice So Nice! n'affichera pas de dés car vous avez coché l'option de Foundry 'Scène de jeu désactivé' 'Disable Game Canvas' ");
}
}
}
static async roll(formula, options = { showDice: false, rollMode: undefined }) {
const roll = new Roll(formula);
await roll.evaluate({ async: true });
if (!options.hideDice) {
roll.showDice = options.showDice;
await RdDDice.show(roll, options.rollMode ?? game.settings.get("core", "rollMode"));
}
return roll;
}
static async rollTotal(formula, options = { showDice: false, hideDice: false }) {
const roll = await RdDDice.roll(formula, options);
return roll.total;
}
static async rollOneOf(array) {
const roll = await RdDDice.rollTotal(`1d${array.length}`);
return array[roll - 1];
}
static diceSoNiceReady(dice3d) { static diceSoNiceReady(dice3d) {
for (const system of Object.keys(dice3d.DiceFactory.systems)) { for (const system of Object.keys(dice3d.DiceFactory.systems)) {
@ -160,7 +133,7 @@ export class RdDDice {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async show(roll, rollMode) { static async show(roll, rollMode = undefined) {
if (roll.showDice || game.settings.get(SYSTEM_RDD, "dice-so-nice") == true) { if (roll.showDice || game.settings.get(SYSTEM_RDD, "dice-so-nice") == true) {
await this.showDiceSoNice(roll, rollMode); await this.showDiceSoNice(roll, rollMode);
} }
@ -168,9 +141,8 @@ export class RdDDice {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async showDiceSoNice(roll, rollMode) { static async showDiceSoNice(roll, rollMode = undefined) {
if (game.modules.get("dice-so-nice")?.active) { if (game.modules.get("dice-so-nice") && game.modules.get("dice-so-nice").active) {
if (game.dice3d) {
let whisper = null; let whisper = null;
let blind = false; let blind = false;
rollMode = rollMode ?? game.settings.get("core", "rollMode"); rollMode = rollMode ?? game.settings.get("core", "rollMode");
@ -184,11 +156,10 @@ export class RdDDice {
whisper = ChatUtility.getUsers(user => user.active); whisper = ChatUtility.getUsers(user => user.active);
break; break;
case "selfroll": case "selfroll":
whisper = [game.user.id]; whisper = [game.user._id];
break; break;
} }
await game.dice3d.showForRoll(roll, game.user, true, whisper, blind); await game.dice3d.showForRoll(roll, game.user, true, whisper, blind);
} }
} }
}
} }

View File

@ -1,76 +0,0 @@
/* -------------------------------------------- */
import { RdDUtility } from "./rdd-utility.js";
import { Misc } from "./misc.js";
import { RdDCalendrier } from "./rdd-calendrier.js";
/* -------------------------------------------- */
export class RdDHerbes extends Item {
/* -------------------------------------------- */
static isHerbeSoin( botaniqueItem ) {
return Misc.templateData(botaniqueItem).categorie == 'Soin';
}
/* -------------------------------------------- */
static isHerbeRepos( botaniqueItem ) {
return Misc.templateData(botaniqueItem).categorie == 'Repos';
}
/* -------------------------------------------- */
static async initializeHerbes( ) {
this.herbesSoins = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.botanique', item => this.isHerbeSoin(item));
this.herbesRepos = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.botanique', item => this.isHerbeRepos(item));
}
/* -------------------------------------------- */
static buildHerbesList(listHerbes, max) {
let list = {}
for ( let herbe of listHerbes) {
let herbeData = Misc.templateData(herbe);
let brins = max - herbeData.niveau;
list[herbe.data.name] = `${herbe.data.name} (Bonus: ${herbeData.niveau}, Brins: ${brins})`;
}
list['Autre'] = 'Autre (Bonus: variable, Brins: variable)'
return list;
}
/* -------------------------------------------- */
static updatePotionData( formData ) {
formData.herbesSoins = this.buildHerbesList(this.herbesSoins, 12);
formData.herbesRepos = this.buildHerbesList(this.herbesRepos, 7);
formData.jourMoisOptions = Array(28).fill().map((item, index) => 1 + index);
formData.dateActuelle = game.system.rdd.calendrier.getDateFromIndex();
formData.splitDate = game.system.rdd.calendrier.getNumericDateFromIndex(formData.data.prdate);
if (formData.data.categorie.includes('Soin') ) {
formData.isHerbe = true;
this.computeHerbeBonus(formData, this.herbesSoins, 12);
} else if (formData.data.categorie.includes('Repos')) {
formData.isRepos = true;
this.computeHerbeBonus(formData, this.herbesRepos, 7);
}
}
/* -------------------------------------------- */
static calculePointsRepos( data ) {
return data.herbebonus * data.pr;
}
/* -------------------------------------------- */
static calculePointsGuerison( data ){
return data.herbebonus * data.pr;
}
/* -------------------------------------------- */
static computeHerbeBonus( formData, herbesList, max) {
if ( Number(formData.data.herbebrins) ) {
let herbe = herbesList.find(item => item.name.toLowerCase() == formData.data.herbe.toLowerCase() );
if( herbe ) {
let herbeData = Misc.templateData(herbe);
let brinsBase = max - herbeData.niveau;
//console.log(herbeData, brinsBase, formData.data.herbebrins);
formData.data.herbebonus = Math.max(herbeData.niveau - Math.max(brinsBase - formData.data.herbebrins, 0), 0);
}
}
}
}

View File

@ -9,12 +9,12 @@ export class RdDHotbar {
*/ */
static initDropbar( ) { static initDropbar( ) {
Hooks.on("hotbarDrop", async (bar, documentData, slot) => { Hooks.on("hotbarDrop", async (bar, data, slot) => {
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill // Create item macro if rollable item - weapon, spell, prayer, trait, or skill
if (documentData.type == "Item") { if (data.type == "Item") {
if (documentData.data.type != "arme" && documentData.data.type != "competence" ) if (data.data.type != "arme" && data.data.type != "competence" )
return return
let item = documentData.data let item = data.data
let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}");`; let command = `game.system.rdd.RdDHotbar.rollMacro("${item.name}", "${item.type}");`;
let macro = game.macros.entities.find(m => (m.name === item.name) && (m.command === command)); let macro = game.macros.entities.find(m => (m.name === item.name) && (m.command === command));
if (!macro) { if (!macro) {
@ -28,9 +28,9 @@ export class RdDHotbar {
game.user.assignHotbarMacro(macro, slot); game.user.assignHotbarMacro(macro, slot);
} }
// Create a macro to open the actor sheet of the actor dropped on the hotbar // Create a macro to open the actor sheet of the actor dropped on the hotbar
else if (documentData.type == "Actor") { else if (data.type == "Actor") {
let actor = game.actors.get(documentData.id); let actor = game.actors.get(data.id);
let command = `game.actors.get("${documentData.id}").sheet.render(true)` let command = `game.actors.get("${data.id}").sheet.render(true)`
let macro = game.macros.entities.find(m => (m.name === actor.name) && (m.command === command)); let macro = game.macros.entities.find(m => (m.name === actor.name) && (m.command === command));
if (!macro) { if (!macro) {
macro = await Macro.create({ macro = await Macro.create({
@ -43,15 +43,15 @@ export class RdDHotbar {
} }
} }
// Create a macro to open the journal sheet of the journal dropped on the hotbar // Create a macro to open the journal sheet of the journal dropped on the hotbar
else if (documentData.type == "JournalEntry") { else if (data.type == "JournalEntry") {
let journal = game.journal.get(documentData.id); let journal = game.journal.get(data.id);
let command = `game.journal.get("${documentData.id}").sheet.render(true)` let command = `game.journal.get("${data.id}").sheet.render(true)`
let macro = game.macros.entities.find(m => (m.name === journal.name) && (m.command === command)); let macro = game.macros.entities.find(m => (m.name === journal.name) && (m.command === command));
if (!macro) { if (!macro) {
macro = await Macro.create({ macro = await Macro.create({
name: journal.data.name, name: journal.data.name,
type: "script", type: "script",
img: "systems/foundryvtt-reve-de-dragon/icons/templates/icone_parchement_vierge.png", img: "systems/wfrp4e/icons/buildings/scroll.png",
command: command command: command
}, { displaySheet: false }) }, { displaySheet: false })
game.user.assignHotbarMacro(macro, slot); game.user.assignHotbarMacro(macro, slot);

View File

@ -28,10 +28,7 @@ import { ReglesOptionelles } from "./regles-optionelles.js";
import { TMRRencontres } from "./tmr-rencontres.js"; import { TMRRencontres } from "./tmr-rencontres.js";
import { RdDHotbar } from "./rdd-hotbar-drop.js" import { RdDHotbar } from "./rdd-hotbar-drop.js"
import { EffetsDraconiques } from "./tmr/effets-draconiques.js"; import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { RdDHerbes } from "./rdd-herbes.js";
import { RdDItem } from "./item.js";
import { RdDDice } from "./rdd-dice.js"; import { RdDDice } from "./rdd-dice.js";
import { RdDSigneDraconiqueItemSheet } from "./item-signedraconique-sheet.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
@ -49,7 +46,8 @@ Hooks.once("init", async function () {
game.system.rdd = { game.system.rdd = {
TMRUtility, TMRUtility,
RdDUtility, RdDUtility,
RdDHotbar RdDHotbar,
RdDResolutionTable
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -72,7 +70,6 @@ Hooks.once("init", async function () {
name: "calendrier", name: "calendrier",
scope: "world", scope: "world",
config: false, config: false,
default: RdDCalendrier.getCalendrier(0),
type: Object type: Object
}); });
@ -81,16 +78,14 @@ Hooks.once("init", async function () {
name: "liste-nombre-astral", name: "liste-nombre-astral",
scope: "world", scope: "world",
config: false, config: false,
default: [],
type: Object type: Object
}); });
/* -------------------------------------------- */ /* -------------------------------------------- */
game.settings.register("foundryvtt-reve-de-dragon", "calendrier-pos", { game.settings.register("foundryvtt-reve-de-dragon", "calendrier-pos", {
name: "calendrierPos", name: "calendrierPos",
scope: "client", scope: "world",
config: false, config: false,
default: RdDCalendrier.createCalendrierPos(),
type: Object type: Object
}); });
@ -122,20 +117,6 @@ Hooks.once("init", async function () {
default: true, default: true,
type: Boolean type: Boolean
}); });
/* -------------------------------------------- */
game.settings.register("foundryvtt-reve-de-dragon", "appliquer-famine-soif", {
name: "Notifier de la famine et la soif pour",
hint: "Indique si les cas de famine et de soif seront indiqués durant Château Dormant",
scope: "world",
config: true,
type: String,
choices: {
"aucun": "ni la famine, ni la soif",
"famine": "seulement la famine",
"famine-soif": "la famine et la soif",
},
default: "aucun"
});
/* -------------------------------------------- */ /* -------------------------------------------- */
// Set an initiative formula for the system // Set an initiative formula for the system
@ -145,19 +126,15 @@ Hooks.once("init", async function () {
}; };
/* -------------------------------------------- */ /* -------------------------------------------- */
game.socket.on("system.foundryvtt-reve-de-dragon", sockmsg => { game.socket.on("system.foundryvtt-reve-de-dragon", data => {
console.log(">>>>> MSG RECV", sockmsg); RdDUtility.onSocketMesssage(data);
RdDCombat.onSocketMessage(data);
RdDUtility.onSocketMesssage(sockmsg); ChatUtility.onSocketMessage(data);
RdDCombat.onSocketMessage(sockmsg);
ChatUtility.onSocketMessage(sockmsg);
RdDActor.onSocketMessage(sockmsg);
}); });
/* -------------------------------------------- */ /* -------------------------------------------- */
// Define custom Entity classes // Define custom Entity classes
CONFIG.Actor.documentClass = RdDActor; CONFIG.Actor.entityClass = RdDActor;
CONFIG.Item.documentClass = RdDItem;
CONFIG.RDD = { CONFIG.RDD = {
resolutionTable: RdDResolutionTable.resolutionTable, resolutionTable: RdDResolutionTable.resolutionTable,
carac_array: RdDUtility.getCaracArray(), carac_array: RdDUtility.getCaracArray(),
@ -173,24 +150,18 @@ Hooks.once("init", async function () {
Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true }); Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true });
Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorEntiteSheet, { types: ["entite"], makeDefault: true }); Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorEntiteSheet, { types: ["entite"], makeDefault: true });
Items.unregisterSheet("core", ItemSheet); Items.unregisterSheet("core", ItemSheet);
Items.registerSheet("foundryvtt-reve-de-dragon", RdDSigneDraconiqueItemSheet, {
label: "Signe draconique",
types: ["signedraconique"],
makeDefault: true
});
Items.registerSheet("foundryvtt-reve-de-dragon", RdDItemSheet, { makeDefault: true }); Items.registerSheet("foundryvtt-reve-de-dragon", RdDItemSheet, { makeDefault: true });
CONFIG.Combat.documentClass = RdDCombatManager; CONFIG.Combat.entityClass = RdDCombatManager;
// préparation des différents modules // préparation des différents modules
ReglesOptionelles.init();
RdDUtility.init();
RdDDice.init(); RdDDice.init();
RdDCommands.init(); RdDCommands.init();
RdDCombat.init(); RdDCombat.init();
RdDCombatManager.init(); RdDCombatManager.init(),
RdDTokenHud.init(); RdDTokenHud.init();
RdDActor.init(); RdDActor.init();
RddCompendiumOrganiser.init(); RddCompendiumOrganiser.init();
ReglesOptionelles.init();
EffetsDraconiques.init() EffetsDraconiques.init()
TMRUtility.init(); TMRUtility.init();
TMRRencontres.init(); TMRRencontres.init();
@ -202,7 +173,7 @@ function messageDeBienvenue() {
if (game.user.isGM) { if (game.user.isGM) {
ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">'); ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">');
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user._id,
content: `<div id="message-bienvenue-rdd"><span class="rdd-roll-part">Bienvenue dans le Rêve des Dragons !</span> content: `<div id="message-bienvenue-rdd"><span class="rdd-roll-part">Bienvenue dans le Rêve des Dragons !</span>
<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>
@ -210,18 +181,17 @@ function messageDeBienvenue() {
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Foundry VTT Initialization */ /* Foundry VTT Initialization */
/* -------------------------------------------- */ /* -------------------------------------------- */
Hooks.once("ready", async function () { Hooks.once("ready", function () {
StatusEffects.onReady(); StatusEffects.onReady();
RdDHerbes.initializeHerbes();
RdDDice.onReady();
/* -------------------------------------------- */ /* -------------------------------------------- */
/* Affiche/Init le calendrier */ /* Affiche/Init le calendrier */
let calendrier = new RdDCalendrier(); let calendrier = new RdDCalendrier();
await calendrier.initCalendrier(); calendrier.initCalendrier();
let templatePath = "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html"; let templatePath = "systems/foundryvtt-reve-de-dragon/templates/calendar-template.html";
let templateData = {}; let templateData = {};
renderTemplate(templatePath, templateData).then(html => { renderTemplate(templatePath, templateData).then(html => {
@ -234,7 +204,7 @@ Hooks.once("ready", async function () {
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !"); ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !");
ChatMessage.create({ ChatMessage.create({
content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !", content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !",
user: game.user.id user: game.user._id
}); });
//whisper: [ ChatMessage.getWhisperRecipients("GM") ] } ); //whisper: [ ChatMessage.getWhisperRecipients("GM") ] } );
} }
@ -261,3 +231,8 @@ Hooks.on("chatMessage", (html, content, msg) => {
return true; return true;
}); });
/* -------------------------------------------- */
Hooks.on("renderChatMessage", async (app, html, msg) => {
RdDUtility.onRenderChatMessage(app, html, msg);
});

View File

@ -1,17 +1,14 @@
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
const words = [ 'pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i', 'onse', 'iane', 'ane', 'zach', 'arri', 'ba', 'bo', 'bi', const words = [ 'pore', 'pre', 'flor', 'lane', 'turlu', 'pin', 'a', 'alph', 'i', 'onse', 'iane', 'ane', 'zach', 'arri', 'ba', 'bo', 'bi',
'alta', 'par', 'pir', 'zor', 'zir', 'de', 'pol', 'tran', 'no', 'la', 'al' , 'pul', 'one', 'ner', 'nur', 'mac', 'mery', 'alta', 'par', 'pir', 'zor', 'zir', 'de', 'pol', 'tran', 'no', 'la','al' , 'pul', 'one', 'ner', 'nur' ];
'cat', 'do', 'di', 'der', 'er', 'el', 'far', 'fer', 'go', 'guer', 'hot', 'jor', 'jar', 'ji', 'kri', 'ket', 'lor', 'hur',
'lar', 'lir', 'lu', 'pot', 'pro', 'pra', 'pit', 'qua', 'qui', 're', 'ral', 'sal', 'sen', 'ted', 'to', 'ta', 'lars', 'ver',
'vin', 'ov', 'wal', 'ry', 'ly', '' ];
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDNameGen { export class RdDNameGen {
static async getName( msg, params ) { static getName( msg, params ) {
let name = Misc.upperFirst( await RdDDice.rollOneOf(words) + await RdDDice.rollOneOf(words) ) let name = Misc.upperFirst( Misc.rollOneOf(words) + Misc.rollOneOf(words) )
//console.log(name); //console.log(name);
ChatMessage.create( { content: `Nom : ${name}`, whisper: ChatMessage.getWhisperRecipients("GM") } ); ChatMessage.create( { content: `Nom : ${name}`, whisper: ChatMessage.getWhisperRecipients("GM") } );
} }

View File

@ -102,38 +102,25 @@ export class RdDResolutionTable {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async rollData(rollData) { static async rollData(rollData) {
rollData.rolled = await this.roll(rollData.caracValue, rollData.finalLevel, rollData); rollData.rolled = await this.roll(rollData.caracValue, rollData.finalLevel, rollData.bonus, rollData.diviseurSignificative, rollData.showDice);
return rollData; return rollData;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async roll(caracValue, finalLevel, rollData = {}){ static async roll(caracValue, finalLevel, bonus = undefined, diviseur = undefined, showDice = true) {
let chances = this.computeChances(caracValue, finalLevel); let chances = this.computeChances(caracValue, finalLevel);
this._updateChancesWithBonus(chances, rollData.bonus); this._updateChancesWithBonus(chances, bonus);
this._updateChancesFactor(chances, rollData.diviseurSignificative); this._updateChancesFactor(chances, diviseur);
chances.showDice = rollData.showDice; chances.showDice = showDice;
chances.rollMode = rollData.rollMode;
let rolled = await this.rollChances(chances, rollData.diviseurSignificative); let rolled = await this.rollChances(chances, diviseur);
rolled.caracValue = caracValue; rolled.caracValue = caracValue;
rolled.finalLevel = finalLevel; rolled.finalLevel = finalLevel;
rolled.bonus = rollData.bonus; rolled.bonus = bonus;
rolled.factorHtml = Misc.getFractionHtml(rollData.diviseurSignificative); rolled.factorHtml = Misc.getFractionHtml(diviseur);
rolled.niveauNecessaire = this.findNiveauNecessaire(caracValue, rolled.roll );
rolled.ajustementNecessaire = rolled.niveauNecessaire - finalLevel;
return rolled; return rolled;
} }
/* -------------------------------------------- */
static findNiveauNecessaire(caracValue, rollValue) {
for (let cell of this.resolutionTable[caracValue]) {
if ( rollValue <= cell.norm) {
return cell.niveau;
}
}
return 16; // Dummy default
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static _updateChancesFactor(chances, diviseur) { static _updateChancesFactor(chances, diviseur) {
if (chances.level > -11 && diviseur && diviseur > 1) { if (chances.level > -11 && diviseur && diviseur > 1) {
@ -150,13 +137,11 @@ export class RdDResolutionTable {
} }
} }
/* -------------------------------------------- */
static significativeRequise(chances) { static significativeRequise(chances) {
chances.roll = Math.floor(chances.score / 2); chances.roll = Math.floor(chances.score / 2);
mergeObject(chances, reussites.find(x => x.code == 'sign'), { overwrite: true }); mergeObject(chances, reussites.find(x => x.code == 'sign'), { overwrite: true });
} }
/* -------------------------------------------- */
static succesRequis(chances) { static succesRequis(chances) {
chances.roll = chances.score; chances.roll = chances.score;
mergeObject(chances, reussites.find(x => x.code == 'norm'), { overwrite: true }); mergeObject(chances, reussites.find(x => x.code == 'norm'), { overwrite: true });
@ -164,7 +149,10 @@ export class RdDResolutionTable {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async rollChances(chances, diviseur) { static async rollChances(chances, diviseur) {
chances.roll = await RdDDice.rollTotal("1d100", chances); let myRoll = new Roll("1d100").roll();
myRoll.showDice = chances.showDice;
await RdDDice.show(myRoll);
chances.roll = myRoll.total;
mergeObject(chances, this.computeReussite(chances, chances.roll, diviseur), { overwrite: true }); mergeObject(chances, this.computeReussite(chances, chances.roll, diviseur), { overwrite: true });
return chances; return chances;
} }
@ -177,7 +165,8 @@ export class RdDResolutionTable {
if (difficulte < -10) { if (difficulte < -10) {
return duplicate(levelDown.find(levelData => levelData.level == difficulte)); return duplicate(levelDown.find(levelData => levelData.level == difficulte));
} }
return duplicate(RdDResolutionTable.resolutionTable[caracValue][difficulte + 10]); const chances = RdDResolutionTable.resolutionTable[caracValue][difficulte + 10];
return chances ? duplicate(chances) : RdDResolutionTable._computeCell(difficulte, RdDResolutionTable.computeChances(caracValue, difficulte));
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -236,16 +225,26 @@ export class RdDResolutionTable {
/* -------------------------------------------- */ /* -------------------------------------------- */
static _computeRow(caracValue) { static _computeRow(caracValue) {
let dataRow = [ let dataRow = [];
this._computeCell(-10, Math.max(Math.floor(caracValue / 4), 1)), for (var diff = -10; diff <= 22; diff++) {
this._computeCell(-9, Math.max(Math.floor(caracValue / 2), 1)) dataRow[diff + 10] = this._computeCell(diff, RdDResolutionTable._computePercentage(caracValue, diff));
]
for (var diff = -8; diff <= 22; diff++) {
dataRow[diff + 10] = this._computeCell(diff, Math.max(Math.floor(caracValue * (diff + 10) / 2), 1));
} }
return dataRow; return dataRow;
} }
static _computePercentage(caracValue, diff) {
if (diff <-10) {
return 1;
}
if (diff == -10){
return Math.max(Math.floor(caracValue / 4), 1);
}
if (diff == -9) {
return Math.max(Math.floor(caracValue / 2), 1)
}
return Math.max(Math.floor(caracValue * (diff + 10) / 2), 1);
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static _computeCell(niveau, percentage) { static _computeCell(niveau, percentage) {
return { return {

View File

@ -7,23 +7,17 @@ export class RdDEncaisser extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
constructor(html, actor) { constructor(html, actor) {
// Common conf // Common conf
const buttonsCreatures = {
"mortel": { label: "mortel", callback: html => this.performEncaisser("mortel") },
"non-mortel": { label: "non-mortel", callback: html => this.performEncaisser("non-mortel") },
};
const buttonsEntitesCauchemar = {
"cauchemar": { label: "cauchemar", callback: html => this.performEncaisser("cauchemar") }
};
const buttons = actor.isEntiteCauchemar() ? buttonsEntitesCauchemar : buttonsCreatures;
let dialogConf = { let dialogConf = {
title: "Jet d'Encaissement", title: "Jet d'Encaissement",
content: html, content: html,
buttons: buttons, buttons: {
"mortel": { label: "mortel", callback: html => this.performEncaisser(html, "mortel") },
"non-mortel": { label: "non-mortel", callback: html => this.performEncaisser(html, "non-mortel") },
"cauchemar": { label: "cauchemar", callback: html => this.performEncaisser(html, "cauchemar") }
},
default: "coupMortel" default: "coupMortel"
} }
let dialogOptions = { let dialogOptions = {
classes: ["rdddialog"], classes: ["rdddialog"],
width: 320, width: 320,
@ -38,15 +32,13 @@ export class RdDEncaisser extends Dialog {
this.encaisserSpecial = "aucun"; this.encaisserSpecial = "aucun";
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
performEncaisser(mortalite) { performEncaisser(html, mortalite = "mortel") {
this.actor.encaisserDommages({ this.actor.encaisserDommages({
dmg: { dmg:{
total: Number(this.modifier), total: Number(this.modifier),
encaisserSpecial: this.encaisserSpecial, encaisserSpecial: this.encaisserSpecial,
loc: { result: 0, label: "" }, loc: { result: 0, label: "Corps" },
mortalite: mortalite mortalite: mortalite
} }
}); });

View File

@ -1,3 +1,4 @@
import { RdDResolutionTable } from "./rdd-resolution-table.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
/** /**
@ -7,27 +8,22 @@ import { Misc } from "./misc.js";
export class RdDRollDialogEthylisme extends Dialog { export class RdDRollDialogEthylisme extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
constructor(html, rollData, actor, onRoll) { constructor(html, rollData, actor) {
// Common conf
let dialogConf = { let myButtons = {
title: "Test d'éthylisme", rollButton: { label: "Test d'éthylisme", callback: html => this.actor.performEthylisme(this.rollData) }
content: html,
default: "rollButton",
buttons: { "rollButton": { label: "Test d'éthylisme", callback: html => this.onButton(html) } }
}; };
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 270, 'z-index': 99999 }
// Common conf
let dialogConf = { content: html, title: "Test d'éthylisme", buttons: myButtons, default: "rollButton" };
let dialogOptions = { classes: ["rdddialog"], width: 400, height: 220, 'z-index': 99999 }
super(dialogConf, dialogOptions) super(dialogConf, dialogOptions)
//console.log("ETH", rollData); //console.log("ETH", rollData);
this.onRoll = onRoll;
this.rollData = rollData; this.rollData = rollData;
this.actor = actor; this.actor = actor;
} }
async onButton(html) {
this.onRoll(this.rollData);
}
/* -------------------------------------------- */ /* -------------------------------------------- */
activateListeners(html) { activateListeners(html) {
super.activateListeners(html); super.activateListeners(html);
@ -35,25 +31,28 @@ export class RdDRollDialogEthylisme extends Dialog {
this.bringToTop(); // Ensure top level this.bringToTop(); // Ensure top level
// Get the rollData stuff // Get the rollData stuff
var rollData = this.rollData; var rollData = this.rollData;
var dialog = this;
function updateRollResult(rollData) {
rollData.finalLevel = Number(rollData.etat) + Number(rollData.forceAlcool) + rollData.diffNbDoses;
// Mise à jour valeurs
$("#roll-param").text(rollData.vieValue + " / " + Misc.toSignedString(rollData.finalLevel));
$(".table-resolution").remove();
$("#resolutionTable").append(RdDResolutionTable.buildHTMLTableExtract(rollData.vieValue, rollData.finalLevel));
}
// Setup everything onload // Setup everything onload
$(function () { $(function () {
$("#forceAlcool").val(Misc.toInt(rollData.forceAlcool)); $("#forceAlcool").val(Misc.toInt(rollData.forceAlcool));
dialog.updateRollResult(); updateRollResult(rollData);
}); });
// Update ! // Update !
html.find('#forceAlcool').change((event) => { html.find('#forceAlcool').change((event) => {
rollData.forceAlcool = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus rollData.forceAlcool = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus
dialog.updateRollResult(); updateRollResult(rollData);
}); });
} }
async updateRollResult() {
// Mise à jour valeurs
$("#roll-param").text(this.rollData.vie + " / " + Misc.toSignedString(Number(this.rollData.etat) + Number(this.rollData.forceAlcool) + this.rollData.diffNbDoses));
$(".table-resolution").remove();
}
} }

View File

@ -29,7 +29,6 @@ export class RdDRollResolutionTable extends Dialog {
finalLevel: 0, finalLevel: 0,
diffConditions: 0, diffConditions: 0,
diffLibre: 0, diffLibre: 0,
use: { conditions:true, libre:true }
} }
mergeObject(rollData, defRollData, { overwrite: false }); mergeObject(rollData, defRollData, { overwrite: false });
for (let i = 1; i < 21; i++) { for (let i = 1; i < 21; i++) {
@ -106,8 +105,6 @@ export class RdDRollResolutionTable extends Dialog {
this.updateRollResult(); this.updateRollResult();
}); });
} }
/* -------------------------------------------- */
async updateRollResult() { async updateRollResult() {
let rollData = this.rollData; let rollData = this.rollData;
rollData.caracValue = parseInt(rollData.selectedCarac.value) rollData.caracValue = parseInt(rollData.selectedCarac.value)
@ -130,7 +127,6 @@ export class RdDRollResolutionTable extends Dialog {
return diffLibre + diffConditions; return diffLibre + diffConditions;
} }
/* -------------------------------------------- */
_computeDiffLibre(rollData) { _computeDiffLibre(rollData) {
return Misc.toInt(rollData.diffLibre); return Misc.toInt(rollData.diffLibre);
} }

View File

@ -1,6 +1,7 @@
import { RollDataAjustements } from "./rolldata-ajustements.js"; import { RollDataAjustements } from "./rolldata-ajustements.js";
import { HtmlUtility } from "./html-utility.js"; import { HtmlUtility } from "./html-utility.js";
import { RdDItemCompetence } from "./item-competence.js"; import { RdDItemCompetence } from "./item-competence.js";
import { RdDItemMeditation } from "./item-meditation.js";
import { RdDItemSort } from "./item-sort.js"; import { RdDItemSort } from "./item-sort.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js"; import { RdDBonus } from "./rdd-bonus.js";
@ -159,17 +160,14 @@ export class RdDRoll extends Dialog {
function onLoad() { function onLoad() {
let rollData = dialog.rollData; let rollData = dialog.rollData;
console.log(rollData);
// Update html, according to data // Update html, according to data
if (rollData.competence) { if (rollData.competence) {
const defaut_carac = Misc.templateData(rollData.competence).defaut_carac;
// Set the default carac from the competence item // Set the default carac from the competence item
rollData.selectedCarac = rollData.carac[defaut_carac]; rollData.selectedCarac = rollData.carac[rollData.competence.data.defaut_carac];
$("#carac").val(defaut_carac); $("#carac").val(rollData.competence.data.defaut_carac);
} }
if (rollData.selectedSort) { if (rollData.selectedSort) {
dialog.setSelectedSort(rollData.selectedSort); $("#draconic").val(rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
$(".draconic").val(rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
} }
RdDItemSort.setCoutReveReel(rollData.selectedSort); RdDItemSort.setCoutReveReel(rollData.selectedSort);
$("#diffLibre").val(Misc.toInt(rollData.diffLibre)); $("#diffLibre").val(Misc.toInt(rollData.diffLibre));
@ -194,20 +192,17 @@ export class RdDRoll extends Dialog {
this.rollData.selectedCarac = this.rollData.carac[caracKey]; // Update the selectedCarac this.rollData.selectedCarac = this.rollData.carac[caracKey]; // Update the selectedCarac
this.updateRollResult(); this.updateRollResult();
}); });
html.find('.roll-draconic').change((event) => { html.find('#draconic').change((event) => {
let draconicKey = Misc.toInt(event.currentTarget.value); let draconicKey = Misc.toInt(event.currentTarget.value);
this.rollData.competence = this.rollData.draconicList[draconicKey]; // Update the selectedCarac this.rollData.competence = this.rollData.draconicList[draconicKey]; // Update the selectedCarac
this.updateRollResult(); this.updateRollResult();
}); });
html.find('.roll-sort').change((event) => { html.find('#sort').change((event) => {
let sortKey = Misc.toInt(event.currentTarget.value); let sortKey = Misc.toInt(event.currentTarget.value);
this.setSelectedSort(this.rollData.sortList[sortKey]); this.rollData.selectedSort = this.rollData.sortList[sortKey]; // Update the selectedCarac
this.updateRollResult(); this.rollData.bonus = RdDItemSort.getCaseBonus(this.rollData.selectedSort, this.rollData.tmr.coord);
$("#diffLibre").val(this.rollData.diffLibre); RdDItemSort.setCoutReveReel(this.rollData.selectedSort);
}); $("#draconic").val(this.rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
html.find('.roll-signedraconique').change((event) => {
let sortKey = Misc.toInt(event.currentTarget.value);
this.setSelectedSigneDraconique(this.rollData.signes[sortKey]);
this.updateRollResult(); this.updateRollResult();
}); });
html.find('#ptreve-variable').change((event) => { html.find('#ptreve-variable').change((event) => {
@ -220,35 +215,31 @@ export class RdDRoll extends Dialog {
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel"; this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
this.updateRollResult(); this.updateRollResult();
}); });
html.find('.cuisine-proportions').change((event) => { html.find('#tactique-combat').change((event) => {
this.rollData.proportions = Number(event.currentTarget.value); this.rollData.tactique = event.currentTarget.value;
this.updateRollResult(); this.updateRollResult();
}); });
html.find('.select-by-name').change((event) => { html.find('#useMalusSurenc').change((event) => {
const attribute = event.currentTarget.attributes['name'].value; this.rollData.useMalusSurenc = event.currentTarget.checked;
this.rollData[attribute] = event.currentTarget.value;
this.updateRollResult(); this.updateRollResult();
}); });
html.find('.checkbox-by-name').change((event) => { html.find('#useMalusEncTotal').change((event) => {
const attribute = event.currentTarget.attributes['name'].value; this.rollData.useMalusEncTotal = event.currentTarget.checked;
this.rollData[attribute] = event.currentTarget.checked;
this.updateRollResult(); this.updateRollResult();
}); });
html.find('.appel-moral').click((event) => { /* l'appel au moral, qui donne un bonus de +1 */ html.find('.imgAppelAuMoral').click((event) => { /* l'appel au moral, qui donne un bonus de +1 */
this.rollData.useMoral = !this.rollData.useMoral; this.rollData.useMoral = !this.rollData.useMoral;
const appelMoral = html.find('.icon-appel-moral')[0];
const tooltip = html.find('.tooltipAppelAuMoralText')[0];
if (this.rollData.useMoral) { if (this.rollData.useMoral) {
if (this.rollData.moral > 0) { if (this.rollData.moral > 0) {
tooltip.innerHTML = "Appel au moral"; html.find('.imgAppelAuMoral')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-heureux.svg";
appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-heureux.svg"; html.find('.tooltipAppelAuMoralText')[0].innerHTML = "Appel au moral";
} else { } else {
tooltip.innerHTML = "Appel à l'énergie du désespoir"; html.find('.imgAppelAuMoral')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-malheureux.svg";
appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-malheureux.svg"; html.find('.tooltipAppelAuMoralText')[0].innerHTML = "Appel à l'énergie du désespoir";
} }
} else { } else {
tooltip.innerHTML = "Sans appel au moral"; html.find('.imgAppelAuMoral')[0].src = "/systems/foundryvtt-reve-de-dragon/icons/moral-neutre.svg";
appelMoral.src = "/systems/foundryvtt-reve-de-dragon/icons/moral-neutre.svg"; html.find('.tooltipAppelAuMoralText')[0].innerHTML = "Sans appel au moral";
} }
this.updateRollResult(); this.updateRollResult();
}); });
@ -260,35 +251,6 @@ export class RdDRoll extends Dialog {
}); });
} }
async setSelectedSort(sort) {
this.rollData.selectedSort = sort; // Update the selectedCarac
this.rollData.competence = RdDItemCompetence.getVoieDraconic(this.rollData.draconicList, sort.data.draconic);
this.rollData.bonus = RdDItemSort.getCaseBonus(sort, this.rollData.tmr.coord);
this.rollData.diffLibre = RdDItemSort.getDifficulte(sort, -7);
RdDItemSort.setCoutReveReel(sort);
const htmlSortDescription = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html", { sort: sort });
$(".sort-ou-rituel").text(sort.data.isrituel ? "rituel" : "sort");
$(".bonus-case").text(`${this.rollData.bonus}%`);
$(".details-sort").remove();
$(".description-sort").append(htmlSortDescription);
$(".roll-draconic").val(sort.data.listIndex);
$(".div-sort-difficulte-fixe").text(Misc.toSignedString(sort.data.difficulte));
$(".div-sort-ptreve-fixe").text(sort.data.ptreve);
const diffVariable = RdDItemSort.isDifficulteVariable(sort);
const coutVariable = RdDItemSort.isCoutVariable(sort);
HtmlUtility._showControlWhen($(".div-sort-non-rituel"), !sort.data.isrituel);
HtmlUtility._showControlWhen($(".div-sort-difficulte-var"), diffVariable);
HtmlUtility._showControlWhen($(".div-sort-difficulte-fixe"), !diffVariable);
HtmlUtility._showControlWhen($(".div-sort-ptreve-var"), coutVariable);
HtmlUtility._showControlWhen($(".div-sort-ptreve-fixe"), !coutVariable);
}
async setSelectedSigneDraconique(signe){
this.rollData.signe = signe;
this.rollData.diffLibre = Misc.data(signe).data.difficulte,
$(".signe-difficulte").text(Misc.toSignedString(this.rollData.diffLibre));
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async updateRollResult() { async updateRollResult() {
let rollData = this.rollData; let rollData = this.rollData;
@ -300,7 +262,12 @@ export class RdDRoll extends Dialog {
let dmgText = Misc.toSignedString(rollData.dmg.total); let dmgText = Misc.toSignedString(rollData.dmg.total);
if (rollData.coupsNonMortels) { if (rollData.coupsNonMortels) {
dmgText = `(${dmgText}) non-mortel` dmgText = '(' + dmgText + ')';
}
if (rollData.selectedSort) {
rollData.bonus = RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.tmr.coord);
HtmlUtility._showControlWhen($("#div-sort-difficulte"), RdDItemSort.isDifficulteVariable(rollData.selectedSort))
HtmlUtility._showControlWhen($("#div-sort-ptreve"), RdDItemSort.isCoutVariable(rollData.selectedSort))
} }
RollDataAjustements.calcul(rollData, this.actor); RollDataAjustements.calcul(rollData, this.actor);
@ -308,13 +275,13 @@ export class RdDRoll extends Dialog {
HtmlUtility._showControlWhen($(".diffMoral"), rollData.ajustements.moralTotal.used); HtmlUtility._showControlWhen($(".diffMoral"), rollData.ajustements.moralTotal.used);
HtmlUtility._showControlWhen($(".divAppelAuMoral"), rollData.use.appelAuMoral); HtmlUtility._showControlWhen($(".divAppelAuMoral"), rollData.use.appelAuMoral);
HtmlUtility._showControlWhen($("#etat-general"), !RdDCarac.isIgnoreEtatGeneral(rollData)); HtmlUtility._showControlWhen($("#etat-general"), !RdDCarac.isIgnoreEtatGeneral(rollData.selectedCarac, rollData.competence));
HtmlUtility._showControlWhen($("#ajust-astrologique"), RdDResolutionTable.isAjustementAstrologique(rollData)); HtmlUtility._showControlWhen($("#ajust-astrologique"), RdDResolutionTable.isAjustementAstrologique(rollData));
// Mise à jour valeurs // Mise à jour valeurs
$(".dialog-roll-title").text(this._getTitle(rollData)); $("#compdialogTitle").text(this._getTitle(rollData));
$('#coupsNonMortels').prop('checked', rollData.coupsNonMortels); $('#coupsNonMortels').prop('checked', rollData.coupsNonMortels);
$(".dmg-arme-actor").text(dmgText); $("#dmg-arme-actor").text(dmgText);
$('.table-ajustement').remove(); $('.table-ajustement').remove();
$(".table-resolution").remove(); $(".table-resolution").remove();
$(".table-proba-reussite").remove(); $(".table-proba-reussite").remove();
@ -326,7 +293,7 @@ export class RdDRoll extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
async buildAjustements(rollData) { async buildAjustements(rollData) {
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html`, rollData); const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-roll-ajustements.html`, rollData);
return html; return html;
} }
@ -380,9 +347,9 @@ export class RdDRoll extends Dialog {
const niveau = Misc.toSignedString(rollData.competence.data.niveau); const niveau = Misc.toSignedString(rollData.competence.data.niveau);
if (compName == carac) { if (compName == carac) {
// cas des créatures // cas des créatures
return carac + " Niveau " + niveau return carac + " " + niveau
} }
const armeTitle = (rollData.arme) ? " (" + rollData.arme.name + ") " : ""; const armeTitle = (rollData.arme) ? " (" + rollData.arme.name + ") " : "";
return carac + "/" + compName + armeTitle + " Niveau " + niveau return carac + "/" + compName + armeTitle + " " + niveau
} }
} }

View File

@ -5,23 +5,33 @@ export class RdDRollTables {
const pack = game.packs.get("foundryvtt-reve-de-dragon.tables-diverses"); const pack = game.packs.get("foundryvtt-reve-de-dragon.tables-diverses");
const index = await pack.getIndex(); const index = await pack.getIndex();
const entry = index.find(e => e.name === tableName); const entry = index.find(e => e.name === tableName);
const table = await pack.getDocument(entry._id); const table = await pack.getEntity(entry._id);
const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll"}); const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll"});
console.log("RdDRollTables", tableName, toChat, ":", draw); console.log("RdDRollTables", tableName, toChat, ":", draw);
return draw.results.length > 0 ? draw.results[0] : undefined; return draw;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async drawItemFromRollTable(tableName, toChat = false) { static async drawItemFromRollTable(tableName, toChat) {
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat); const draw = await RdDRollTables.genericGetTableResult(tableName, toChat);
const pack = game.packs.get(drawResult.data.collection); const drawnItemRef = draw.results.length > 0 ? draw.results[0] : undefined;
return await pack.getDocument(drawResult.data.resultId); if (drawnItemRef.collection) {
const pack = game.packs.get(drawnItemRef.collection);
return await pack.getEntity(drawnItemRef.resultId);
}
ui.notifications.warn("le tirage ne correspond pas à une entrée d'un Compendium")
return drawnItemRef.text;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async drawTextFromRollTable(tableName, toChat) { static async drawTextFromRollTable(tableName, toChat) {
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat); const draw = await RdDRollTables.genericGetTableResult(tableName, toChat);
return drawResult.data.text; const drawnItemRef = draw.results.length > 0 ? draw.results[0] : undefined;
if (drawnItemRef.collection) {
ui.notifications.warn("le tirage correspond à une entrée d'un Compendium, on attendait un texte")
return await pack.getEntity(drawnItemRef.resultId);
}
return drawnItemRef.text;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */

View File

@ -10,10 +10,8 @@ import { Poetique } from "./poetique.js";
import { EffetsDraconiques } from "./tmr/effets-draconiques.js"; import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
import { PixiTMR } from "./tmr/pixi-tmr.js"; import { PixiTMR } from "./tmr/pixi-tmr.js";
import { Draconique } from "./tmr/draconique.js"; import { Draconique } from "./tmr/draconique.js";
import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { HtmlUtility } from "./html-utility.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { RdDDice } from "./rdd-dice.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDTMRDialog extends Dialog { export class RdDTMRDialog extends Dialog {
@ -42,7 +40,7 @@ export class RdDTMRDialog extends Dialog {
const dialogOptions = { const dialogOptions = {
classes: ["tmrdialog"], classes: ["tmrdialog"],
width: 920, height: 980, width: 920, height: 980,
'z-index': 40 'z-index': 20
} }
super(dialogConf, dialogOptions); super(dialogConf, dialogOptions);
@ -50,7 +48,7 @@ export class RdDTMRDialog extends Dialog {
this.actor = actor; this.actor = actor;
this.actor.tmrApp = this; // reference this app in the actor structure this.actor.tmrApp = this; // reference this app in the actor structure
this.viewOnly = tmrData.mode == "visu" this.viewOnly = tmrData.mode == "visu"
this.fatigueParCase = this.viewOnly || !ReglesOptionelles.isUsing("appliquer-fatigue") ? 0 : this.actor.getTMRFatigue(); this.fatigueParCase = this.viewOnly ? 0 : this.actor.getTMRFatigue();
this.cumulFatigue = 0; this.cumulFatigue = 0;
this.loadRencontres(); this.loadRencontres();
this.loadSortsReserve(); this.loadSortsReserve();
@ -60,28 +58,24 @@ export class RdDTMRDialog extends Dialog {
this.pixiApp = new PIXI.Application({ width: 720, height: 860 }); this.pixiApp = new PIXI.Application({ width: 720, height: 860 });
this.pixiTMR = new PixiTMR(this, this.pixiApp); this.pixiTMR = new PixiTMR(this, this.pixiApp);
this.cacheTMR = (game.user.isGM) ? false : actor.isTMRCache();
this.callbacksOnAnimate = []; this.callbacksOnAnimate = [];
if (!this.viewOnly) { if (!this.viewOnly) {
this.actor.setStatusDemiReve(true);
this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")"); this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")");
} }
// load the texture we need // load the texture we need
this.pixiTMR.load((loader, resources) => this.createPixiSprites()); this.pixiTMR.load((loader, resources) => this.createPixiSprites());
} }
/* -------------------------------------------- */
loadCasesSpeciales() { loadCasesSpeciales() {
this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item)); this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item));
} }
/* -------------------------------------------- */
loadSortsReserve() { loadSortsReserve() {
this.sortsReserves = Misc.data(this.actor).data.reve.reserve.list; this.sortsReserves = Misc.data(this.actor).data.reve.reserve.list;
} }
/* -------------------------------------------- */
loadRencontres() { loadRencontres() {
this.rencontresExistantes = this.actor.getTMRRencontres(); this.rencontresExistantes = this.actor.getTMRRencontres();
} }
@ -89,7 +83,9 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
createPixiSprites() { createPixiSprites() {
EffetsDraconiques.carteTmr.createSprite(this.pixiTMR); EffetsDraconiques.carteTmr.createSprite(this.pixiTMR);
this.updateTokens(); this.updateTokens();
this.demiReve = this._tokenDemiReve(); this.demiReve = this._tokenDemiReve();
this._updateDemiReve(); this._updateDemiReve();
} }
@ -105,7 +101,6 @@ export class RdDTMRDialog extends Dialog {
} }
} }
/* -------------------------------------------- */
updateTokens() { updateTokens() {
this._removeTokens(t => true); this._removeTokens(t => true);
this.loadRencontres(); this.loadRencontres();
@ -114,7 +109,6 @@ export class RdDTMRDialog extends Dialog {
this._createTokens(); this._createTokens();
} }
/* -------------------------------------------- */
removeToken(tmr, casetmr) { removeToken(tmr, casetmr) {
this._removeTokens(t => t.coordTMR() == tmr.coord && t.caseSpeciale?._id == casetmr._id); this._removeTokens(t => t.coordTMR() == tmr.coord && t.caseSpeciale?._id == casetmr._id);
this.updateTokens() this.updateTokens()
@ -136,51 +130,19 @@ export class RdDTMRDialog extends Dialog {
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord); return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord);
} }
_tokenCaseSpeciale(casetmr) { _tokenCaseSpeciale(casetmr) {
const caseData = Misc.data(casetmr); const draconique = Draconique.get(casetmr.data.specific);
const draconique = Draconique.get(caseData.data.specific); return draconique?.token(this.pixiTMR, casetmr, () => casetmr.data.coord);
return draconique?.token(this.pixiTMR, caseData, () => caseData.data.coord);
} }
_tokenSortEnReserve(sortEnReserve) { _tokenSortEnReserve(sortEnReserve) {
return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortEnReserve.sort, () => sortEnReserve.coord); return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortEnReserve.sort, () => sortEnReserve.coord);
} }
_tokenDemiReve() { _tokenDemiReve() {
const actorData = Misc.data(this.actor); return EffetsDraconiques.demiReve.token(this.pixiTMR, this.actor, () => Misc.data(this.actor).data.reve.tmrpos.coord);
return EffetsDraconiques.demiReve.token(this.pixiTMR, actorData, () => actorData.data.reve.tmrpos.coord);
} }
_updateDemiReve() { _updateDemiReve() {
this.notifierResonanceSigneDraconique(this._getActorCoord());
if (!this.cacheTMR) {
this._setTokenPosition(this.demiReve); this._setTokenPosition(this.demiReve);
} }
}
_getActorCoord() {
return Misc.data(this.actor).data.reve.tmrpos.coord;
}
/* -------------------------------------------- */
async moveFromKey(move) {
let pos = TMRUtility.convertToCellPos(this._getActorCoord());
if (move == 'top') pos.y -= 1;
if (move == 'bottom') pos.y += 1;
if (move.includes('left')) pos.x -= 1;
if (move.includes('right')) pos.x += 1;
if (pos.x % 2 == 1) {
if (move == 'top-left') pos.y -= 1;
if (move == 'top-right') pos.y -= 1;
} else {
if (move == 'bottom-left') pos.y += 1;
if (move == 'bottom-right') pos.y += 1;
}
let targetCoord = TMRUtility.convertToTMRCoord(pos);
await this._deplacerDemiReve(targetCoord, 'normal');
this.checkQuitterTMR();
}
/* -------------------------------------------- */ /* -------------------------------------------- */
async activateListeners(html) { async activateListeners(html) {
@ -189,72 +151,41 @@ export class RdDTMRDialog extends Dialog {
document.getElementById("tmrrow1").insertCell(0).append(this.pixiApp.view); document.getElementById("tmrrow1").insertCell(0).append(this.pixiApp.view);
if (this.viewOnly) { if (this.viewOnly) {
html.find('.lancer-sort').remove(); html.find('#lancer-sort').remove();
html.find('.lire-signe-draconique').remove(); }
else {
// Roll Sort
html.find('#lancer-sort').click((event) => {
this.actor.rollUnSort(Misc.data(this.actor).data.reve.tmrpos.coord);
});
}
if (this.viewOnly) {
return; return;
} }
HtmlUtility._showControlWhen($(".appliquerFatigue"), ReglesOptionelles.isUsing("appliquer-fatigue"));
HtmlUtility._showControlWhen($(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(this._getActorCoord()));
// Roll Sort
html.find('.lancer-sort').click((event) => {
this.actor.rollUnSort(this._getActorCoord());
});
html.find('.lire-signe-draconique').click((event) => {
this.actor.rollLireSigneDraconique(this._getActorCoord());
});
html.find('#dir-top').click((event) => {
this.moveFromKey("top");
});
html.find('#dir-top-left').click((event) => {
this.moveFromKey("top-left");
});
html.find('#dir-top-right').click((event) => {
this.moveFromKey("top-right");
});
html.find('#dir-bottom-left').click((event) => {
this.moveFromKey("bottom-left");
});
html.find('#dir-bottom-right').click((event) => {
this.moveFromKey("bottom-right");
});
html.find('#dir-bottom').click((event) => {
this.moveFromKey("bottom");
});
// Gestion du cout de montée en points de rêve // Gestion du cout de montée en points de rêve
let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse(); let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1)
if (ReglesOptionelles.isUsing("appliquer-fatigue")) { - this.actor.countMonteeLaborieuse();
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
}
await this.actor.reveActuelIncDec(reveCout); await this.actor.reveActuelIncDec(reveCout);
// Le reste... // Le reste...
this.updateValuesDisplay(); this.updateValuesDisplay();
let tmr = TMRUtility.getTMR(this._getActorCoord()); let tmr = TMRUtility.getTMR(Misc.data(this.actor).data.reve.tmrpos.coord);
await this.manageRencontre(tmr, () => { await this.manageRencontre(tmr, () => {
this.postRencontre(tmr); this.postRencontre(tmr);
}); });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async updateValuesDisplay() { updateValuesDisplay() {
const coord = this._getActorCoord();
const actorData = Misc.data(this.actor);
HtmlUtility._showControlWhen($(".lire-signe-draconique"), this.actor.isResonanceSigneDraconique(coord));
let ptsreve = document.getElementById("tmr-pointsreve-value"); let ptsreve = document.getElementById("tmr-pointsreve-value");
const actorData = Misc.data(this.actor);
ptsreve.innerHTML = actorData.data.reve.reve.value; ptsreve.innerHTML = actorData.data.reve.reve.value;
let tmrpos = document.getElementById("tmr-pos"); let tmrpos = document.getElementById("tmr-pos");
if (this.cacheTMR) { let tmr = TMRUtility.getTMR(actorData.data.reve.tmrpos.coord);
tmrpos.innerHTML = '?? (' + TMRUtility.getTMRType(coord) + ')'; tmrpos.innerHTML = actorData.data.reve.tmrpos.coord + " (" + tmr.label + ")";
} else {
tmrpos.innerHTML = coord + " (" + TMRUtility.getTMRLabel(coord) + ")";
}
let etat = document.getElementById("tmr-etatgeneral-value"); let etat = document.getElementById("tmr-etatgeneral-value");
etat.innerHTML = this.actor.getEtatGeneral(); etat.innerHTML = this.actor.getEtatGeneral();
@ -262,23 +193,19 @@ export class RdDTMRDialog extends Dialog {
let refoulement = document.getElementById("tmr-refoulement-value"); let refoulement = document.getElementById("tmr-refoulement-value");
refoulement.innerHTML = actorData.data.reve.refoulement.value; refoulement.innerHTML = actorData.data.reve.refoulement.value;
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
let fatigueItem = document.getElementById("tmr-fatigue-table"); let fatigueItem = document.getElementById("tmr-fatigue-table");
//console.log("Refresh : ", actorData.data.sante.fatigue.value); //console.log("Refresh : ", actorData.data.sante.fatigue.value);
fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(actorData.data.sante.fatigue.value, actorData.data.sante.endurance.max).html() + "</table>"; fatigueItem.innerHTML = "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(actorData.data.sante.fatigue.value, actorData.data.sante.endurance.max).html() + "</table>";
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
close() { close() {
if ( this.actor.tmrApp ) { this.actor.santeIncDec("fatigue", this.cumulFatigue).then(super.close()); // moving 1 cell costs 1 fatigue
this.actor.tmrApp = undefined; // Cleanup reference this.actor.tmrApp = undefined; // Cleanup reference
if ( !this.viewOnly ) { if (!this.viewOnly) {
this.actor.setStatusDemiReve(false); this.actor.setStatusDemiReve(false);
this._tellToGM(this.actor.name + " a quitté les terres médianes"); this._tellToGM(this.actor.name + " a quitté les terres médianes");
} }
this.actor.santeIncDec("fatigue", this.cumulFatigue).then(super.close()); // moving 1 cell costs 1 fatigue
}
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -288,7 +215,6 @@ export class RdDTMRDialog extends Dialog {
this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR."); this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR.");
this.close(); this.close();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async refouler() { async refouler() {
this._tellToGM(this.actor.name + " a refoulé : " + this.currentRencontre.name); this._tellToGM(this.actor.name + " a refoulé : " + this.currentRencontre.name);
@ -332,14 +258,12 @@ export class RdDTMRDialog extends Dialog {
this.rencontreState = state; this.rencontreState = state;
} }
/* -------------------------------------------- */
async choisirCasePortee(coord, portee) { async choisirCasePortee(coord, portee) {
// Récupère la liste des cases à portées // Récupère la liste des cases à portées
let locList = TMRUtility.getTMRPortee(coord, portee); let locList = TMRUtility.getTMRPortee(coord, portee);
this.colorierZoneRencontre(locList); this.colorierZoneRencontre(locList);
} }
/* -------------------------------------------- */
async choisirCaseType(type) { async choisirCaseType(type) {
const locList = TMRUtility.filterTMR(it => it.type == type).map(it => it.coord); const locList = TMRUtility.filterTMR(it => it.type == type).map(it => it.coord);
this.colorierZoneRencontre(locList); this.colorierZoneRencontre(locList);
@ -354,7 +278,7 @@ export class RdDTMRDialog extends Dialog {
return true; return true;
} }
const resteAvantInconscience = this.actor.getFatigueMax() - this.actor.getFatigueActuelle() - this.cumulFatigue; const resteAvantInconscience = this.actor.getFatigueMax() - this.actor.getFatigueActuelle() - this.cumulFatigue;
if (ReglesOptionelles.isUsing("appliquer-fatigue") && resteAvantInconscience <= 0) { if (resteAvantInconscience <= 0) {
this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !"); this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !");
this.quitterLesTMRInconscient(); this.quitterLesTMRInconscient();
return true; return true;
@ -388,36 +312,35 @@ export class RdDTMRDialog extends Dialog {
rencontre: this.currentRencontre, rencontre: this.currentRencontre,
nbRounds: 1, nbRounds: 1,
canClose: false, canClose: false,
selectedCarac: {label: "reve-actuel"}, tmr: TMRUtility.getTMR(Misc.data(this.actor).data.reve.tmrpos.coord)
tmr: TMRUtility.getTMR(this._getActorCoord())
} }
await this._tentativeMaitrise(rencontreData); await this._tentativeMaitrise(rencontreData);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
async _tentativeMaitrise(rencData) { async _tentativeMaitrise(rencontreData, presentCite) {
console.log("-> matriser", rencData); console.log("-> matriser", rencontreData);
rencData.reve = this.actor.getReveActuel(); rencontreData.reve = this.actor.getReveActuel();
rencData.etat = this.actor.getEtatGeneral(); rencontreData.etat = this.actor.getEtatGeneral();
RollDataAjustements.calcul(rencData, this.actor); RollDataAjustements.calcul(rencontreData, this.actor);
rencData.rolled = rencData.presentCite rencontreData.rolled = rencontreData.presentCite
? this._rollPresentCite(rencData) ? this._rollPresentCite(rencontreData)
: await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements)); : await RdDResolutionTable.roll(rencontreData.reve, RollDataAjustements.sum(rencontreData.ajustements));
let postProcess = await TMRRencontres.gererRencontre(this, rencData); let postProcess = await TMRRencontres.gererRencontre(this, rencontreData);
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencData) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencontreData)
}); });
if (postProcess) { if (postProcess) {
/** Gère les rencontres avec du post-processing (passeur, messagers, tourbillons, ...) */ /** Gère les rencontres avec du post-processing (passeur, messagers, tourbillons, ...) */
await postProcess(this, rencData); await postProcess(this, rencontreData);
} }
else { else {
this.currentRencontre = undefined; this.currentRencontre = undefined;
@ -427,14 +350,12 @@ export class RdDTMRDialog extends Dialog {
if (this.checkQuitterTMR()) { if (this.checkQuitterTMR()) {
return; return;
} }
else if (rencData.rolled.isEchec && rencData.rencontre.isPersistant) { else if (rencontreData.rolled.isEchec && rencontreData.rencontre.isPersistant) {
setTimeout(() => { setTimeout(() => {
rencData.nbRounds++; rencontreData.nbRounds++;
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
} this._tentativeMaitrise(rencontreData);
this._tentativeMaitrise(rencData); this._deleteTmrMessages(rencontreData.actor, rencontreData.nbRounds);
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
}, 2000); }, 2000);
} }
} }
@ -463,17 +384,17 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
_tellToUser(message) { _tellToUser(message) {
ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id] }); ChatMessage.create({ content: message, user: game.user._id, whisper: [game.user._id] });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_tellToGM(message) { _tellToGM(message) {
ChatMessage.create({ content: message, user: game.user.id, whisper: ChatMessage.getWhisperRecipients("GM") }); ChatMessage.create({ content: message, user: game.user._id, whisper: ChatMessage.getWhisperRecipients("GM") });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
_tellToUserAndGM(message) { _tellToUserAndGM(message) {
ChatMessage.create({ content: message, user: game.user.id, whisper: [game.user.id].concat(ChatMessage.getWhisperRecipients("GM")) }); ChatMessage.create({ content: message, user: game.user._id, whisper: [game.user._id].concat(ChatMessage.getWhisperRecipients("GM")) });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -539,15 +460,11 @@ export class RdDTMRDialog extends Dialog {
if (rencontre) { if (rencontre) {
return rencontre; return rencontre;
} }
let locTMR = (this.cacheTMR) ? Misc.upperFirst(tmr.type) + " ??" : tmr.label + " (" + tmr.coord + ")"; let myRoll = new Roll("1d7").evaluate().total;
let myRoll = await RdDDice.rollTotal("1d7");
if (TMRUtility.isForceRencontre() || myRoll == 7) { if (TMRUtility.isForceRencontre() || myRoll == 7) {
this._tellToUser(myRoll + ": Rencontre en " + locTMR);
return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale()); return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale());
} else {
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
} }
this._tellToUser(myRoll + ": Pas de rencontre en " + tmr.label + " (" + tmr.coord + ")");
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -603,7 +520,7 @@ export class RdDTMRDialog extends Dialog {
await this._rollMaitriseCaseHumide(rollData); await this._rollMaitriseCaseHumide(rollData);
return; return;
} }
rollData.poesie = await Poetique.getExtrait(); rollData.poesie = Poetique.getExtrait();
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
@ -613,7 +530,6 @@ export class RdDTMRDialog extends Dialog {
} }
} }
/* -------------------------------------------- */
async souffleSiEchecTotal(rollData) { async souffleSiEchecTotal(rollData) {
if (rollData.rolled.isETotal) { if (rollData.rolled.isETotal) {
rollData.souffle = await this.actor.ajouterSouffle({ chat: false }); rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
@ -714,14 +630,13 @@ export class RdDTMRDialog extends Dialog {
await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options)); await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options));
} }
/* -------------------------------------------- */
async _onResultatConquerir(rollData, options) { async _onResultatConquerir(rollData, options) {
if (rollData.rolled.isETotal) { if (rollData.rolled.isETotal) {
rollData.souffle = await this.actor.ajouterSouffle({ chat: false }); rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
} }
this.toclose = rollData.rolled.isEchec; this.toclose = rollData.rolled.isEchec;
rollData.poesie = await Poetique.getExtrait(); rollData.poesie = Poetique.getExtrait();
ChatMessage.create({ ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name), whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData) content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
@ -741,7 +656,7 @@ export class RdDTMRDialog extends Dialog {
const dialog = await RdDRoll.create(this.actor, rollData, const dialog = await RdDRoll.create(this.actor, rollData,
{ {
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html', html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
options: { height: 420 }, options: { height: 350 },
close: html => { this.maximize(); } // Re-display TMR close: html => { this.maximize(); } // Re-display TMR
}, },
{ {
@ -755,7 +670,6 @@ export class RdDTMRDialog extends Dialog {
dialog.render(true); dialog.render(true);
} }
/* -------------------------------------------- */
async validerVisite(tmr) { async validerVisite(tmr) {
await EffetsDraconiques.pelerinage.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)); await EffetsDraconiques.pelerinage.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr));
await EffetsDraconiques.urgenceDraconique.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr)); await EffetsDraconiques.urgenceDraconique.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr));
@ -870,9 +784,8 @@ export class RdDTMRDialog extends Dialog {
await tmrObject._onClickTMRPos(eventPos); // Vérifier l'état des compteurs reve/fatigue/vie await tmrObject._onClickTMRPos(eventPos); // Vérifier l'état des compteurs reve/fatigue/vie
} }
/* -------------------------------------------- */
async _onClickTMRPos(eventPos) { async _onClickTMRPos(eventPos) {
let currentPos = TMRUtility.convertToCellPos(this._getActorCoord()); let currentPos = TMRUtility.convertToCellPos(Misc.data(this.actor).data.reve.tmrpos.coord);
console.log("deplacerDemiReve >>>>", currentPos, eventPos); console.log("deplacerDemiReve >>>>", currentPos, eventPos);
@ -916,37 +829,24 @@ export class RdDTMRDialog extends Dialog {
Si la case est le demi-rêve, ne pas lancer de sort. Si la case est le demi-rêve, ne pas lancer de sort.
Si un lancement de sort est en cours, trouver un moyen de réafficher cette fenêtre si on essaie de lancer un sort (ou bloquer le lancer de sort) Si un lancement de sort est en cours, trouver un moyen de réafficher cette fenêtre si on essaie de lancer un sort (ou bloquer le lancer de sort)
*/ */
this.notifierResonanceSigneDraconique(targetCoord);
await this.actor.rollUnSort(targetCoord); await this.actor.rollUnSort(targetCoord);
this.nettoyerRencontre(); this.nettoyerRencontre();
} }
/* -------------------------------------------- */
externalRefresh(tmrData) {
this.cacheTMR = (game.user.isGM) ? false : this.actor.isTMRCache();
this.createPixiSprites();
this.forceDemiRevePositionView();
this.updateValuesDisplay();
this.updateTokens();
console.log("TMR REFRESHED !!!");
}
/* -------------------------------------------- */
async _deplacerDemiReve(targetCoord, deplacementType) { async _deplacerDemiReve(targetCoord, deplacementType) {
if (this.currentRencontre != 'normal') { if (this.currentRencontre != 'normal') {
this.nettoyerRencontre(); this.nettoyerRencontre();
} }
let tmr = TMRUtility.getTMR(targetCoord); let tmr = TMRUtility.getTMR(targetCoord);
//console.log("deplacerDemiReve", tmr, this); console.log("deplacerDemiReve", tmr, this);
// Gestion cases spéciales type Trou noir, etc // Gestion cases spéciales type Trou noir, etc
tmr = await this.manageTmrInnaccessible(tmr); tmr = await this.manageTmrInnaccessible(tmr);
this.actor.updateCoordTMR(tmr.coord);
await this.actor.updateCoordTMR(tmr.coord); await this.actor.updateCoordTMR(tmr.coord);
this._updateDemiReve(); this._updateDemiReve();
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
this.cumulFatigue += this.fatigueParCase; this.cumulFatigue += this.fatigueParCase;
}
this.updateValuesDisplay(); this.updateValuesDisplay();
game.socket.emit("system.foundryvtt-reve-de-dragon", { game.socket.emit("system.foundryvtt-reve-de-dragon", {
msg: "msg_tmr_move", data: { msg: "msg_tmr_move", data: {
@ -963,16 +863,6 @@ export class RdDTMRDialog extends Dialog {
} }
} }
async notifierResonanceSigneDraconique(coord) {
if (this.actor.isResonanceSigneDraconique(coord)) {
ChatMessage.create({
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-resonance.html`, { alias: this.actor.name, typeTMR: TMRUtility.getTMRType(coord) })
});
}
}
/* -------------------------------------------- */
async postRencontre(tmr) { async postRencontre(tmr) {
if (!(this.viewOnly || this.currentRencontre)) { if (!(this.viewOnly || this.currentRencontre)) {
await this.manageCaseHumide(tmr); await this.manageCaseHumide(tmr);
@ -1027,10 +917,8 @@ export class RdDTMRDialog extends Dialog {
/* -------------------------------------------- */ /* -------------------------------------------- */
_setTokenPosition(token) { _setTokenPosition(token) {
if (!this.cacheTMR) {
this.pixiTMR.setPosition(token.sprite, TMRUtility.convertToCellPos(token.coordTMR())); this.pixiTMR.setPosition(token.sprite, TMRUtility.convertToCellPos(token.coordTMR()));
} }
}
/* -------------------------------------------- */ /* -------------------------------------------- */
_removeTokens(filter) { _removeTokens(filter) {

View File

@ -20,7 +20,7 @@ export class RdDTMRRencontreDialog extends Dialog {
const dialogOptions = { const dialogOptions = {
classes: ["tmrrencdialog"], classes: ["tmrrencdialog"],
width: 320, height: 240, width: 320, height: 240,
'z-index': 50 'z-index': 20
} }
super(dialogConf, dialogOptions); super(dialogConf, dialogOptions);

View File

@ -1,56 +1,54 @@
/* -------------------------------------------- */ /* -------------------------------------------- */
import { HtmlUtility } from "./html-utility.js"; import { HtmlUtility } from "./html-utility.js";
import { Misc } from "./misc.js";
import { RdDCombatManager } from "./rdd-combat.js"; import { RdDCombatManager } from "./rdd-combat.js";
import { RdDUtility } from "./rdd-utility.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDTokenHud { export class RdDTokenHud {
static init() { static init(){
// Integration du TokenHUD // Integration du TokenHUD
Hooks.on('renderTokenHUD', (app, html, data) => { RdDTokenHud.addTokenHudExtensions(app, html, data._id) }); Hooks.on('renderTokenHUD', (app, html, data) => { RdDTokenHud.addTokenHudExtensions(app, html, data._id) });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async removeExtensionHud(app, html, tokenId) { static async removeExtensionHud( app, html, tokenId) {
html.find('.control-icon.rdd-combat').remove(); let combat = html.find('.control-icon.rdd-combat');
html.find('.control-icon.rdd-initiative').remove(); combat.remove();
let initiative = html.find('.control-icon.rdd-initiative');
initiative.remove();
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async addExtensionHud(app, html, tokenId) { static async addExtensionHud( app, html, tokenId ) {
let token = canvas.tokens.get(tokenId); let token = canvas.tokens.get(tokenId);
let actor = token.actor; let actor = token.actor;
let combatant = game.combat.combatants.find(c => Misc.data(c).tokenId == tokenId); let combatant = game.combat.data.combatants.find(c => c.tokenId == token.data._id);
app.hasExtension = true; app.hasExtension = true;
let armesList = RdDCombatManager.buildListeActionsCombat(combatant); let armesList = RdDCombatManager.buildListeActionsCombat(combatant) ;
const hudData = { const hudData = { combatant: combatant, armes: armesList,
combatant: combatant, armes: armesList, commandes: [{ name: 'Initiative +1', command: 'inc', value: 0.01}, { name: 'Initiative -1',command: 'dec', value: -0.01}] };
commandes: [{ name: 'Initiative +1', command: 'inc', value: 0.01 }, { name: 'Initiative -1', command: 'dec', value: -0.01 }]
};
const controlIconCombat = html.find('.control-icon[data-action=combat]');
// initiative // initiative
await RdDTokenHud._configureSubMenu(controlIconCombat, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', hudData, await RdDTokenHud._configureSubMenu(html.find('.control-icon.combat'), 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', hudData,
(event) => { (event) => {
let initCommand = event.currentTarget.attributes['data-command'].value; let initCommand = event.currentTarget.attributes['data-command'].value;
let combatantId = event.currentTarget.attributes['data-combatant-id'].value; let combatantId = event.currentTarget.attributes['data-combatant-id'].value;
if (!initCommand) { if ( !initCommand ) {
let armeIndex = event.currentTarget.attributes['data-arme-id'].value; let armeIndex = event.currentTarget.attributes['data-arme-id'].value;
let arme = armesList[armeIndex]; let arme = armesList[armeIndex];
RdDCombatManager.rollInitiativeCompetence(combatantId, arme); RdDCombatManager.rollInitiativeCompetence(combatantId, arme);
} else if (initCommand == 'inc') { } else if (initCommand == 'inc') {
RdDCombatManager.incDecInit(combatantId, 0.01); RdDCombatManager.incDecInit( combatantId, 0.01 );
} else if (initCommand == 'dec') { } else if ( initCommand == 'dec') {
RdDCombatManager.incDecInit(combatantId, -0.01); RdDCombatManager.incDecInit( combatantId, -0.01 );
} }
}); });
const controlIconTarget = html.find('.control-icon[data-action=target]');
// combat // combat
await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData, await RdDTokenHud._configureSubMenu(html.find('.control-icon.target'), 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData,
(event) => { (event) => {
let armeIndex = event.currentTarget.attributes['data-arme-id'].value; let armeIndex = event.currentTarget.attributes['data-arme-id'].value;
let arme = armesList[armeIndex]; let arme = armesList[armeIndex];
@ -60,35 +58,38 @@ export class RdDTokenHud {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async addTokenHudExtensions(app, html, tokenId) { static async addTokenHudExtensions(app, html, tokenId) {
const controlIconCombat = html.find('.control-icon[data-action=combat]');
controlIconCombat.click(event => {
if (event.currentTarget.className.includes('active')) {
RdDTokenHud.removeExtensionHud(app, html, tokenId);
} else {
setTimeout(function () { RdDTokenHud.addExtensionHud(app, html, tokenId) }, 200);
}
});
if (controlIconCombat.length>0 && controlIconCombat[0].className.includes('active')) { html.find('.control-icon.combat').click(event => {
RdDTokenHud.addExtensionHud(app, html, tokenId); if ( event.currentTarget.className.includes('active')) {
RdDTokenHud.removeExtensionHud( app, html, tokenId);
} else {
setTimeout( function() { RdDTokenHud.addExtensionHud( app, html, tokenId) } , 200 );
}
} );
let combatIcon = html.find('.control-icon.combat');
if ( combatIcon[0].className.includes('active') ) {
RdDTokenHud.addExtensionHud( app, html, tokenId);
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async _configureSubMenu(insertionPoint, template, hudData, onMenuItem) { static async _configureSubMenu(insertionPoint, template, hudData, onMenuItem) {
const hud = $(await renderTemplate(template, hudData)); const hud = $(await renderTemplate(template, hudData));
const imgHud = hud.find('img.rdd-hud-togglebutton');
const list = hud.find('div.rdd-hud-list'); const list = hud.find('div.rdd-hud-list');
RdDTokenHud._toggleHudListActive(hud, list); hud.toggleClass('active');
HtmlUtility._showControlWhen(list, hud.hasClass('active'));
imgHud.click(event => {
hud.toggleClass('active');
HtmlUtility._showControlWhen(list, hud.hasClass('active'));
});
hud.find('img.rdd-hud-togglebutton').click(event => RdDTokenHud._toggleHudListActive(hud, list));
list.find('.rdd-hud-menu').click(onMenuItem); list.find('.rdd-hud-menu').click(onMenuItem);
insertionPoint.after(hud); insertionPoint.after(hud);
} }
static _toggleHudListActive(hud, list) {
hud.toggleClass('active');
HtmlUtility._showControlWhen(list, hud.hasClass('active'));
}
} }

View File

@ -4,12 +4,6 @@ import { ChatUtility } from "./chat-utility.js";
import { RdDCombat } from "./rdd-combat.js"; import { RdDCombat } from "./rdd-combat.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { TMRUtility } from "./tmr-utility.js";
import { DialogItemAchat } from "./dialog-item-achat.js";
import { ReglesOptionelles } from "./regles-optionelles.js";
import { RdDDice } from "./rdd-dice.js";
import { RdDItem } from "./item.js";
import { Monnaie } from "./item-monnaie.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
// This table starts at 0 -> niveau -10 // This table starts at 0 -> niveau -10
@ -98,13 +92,6 @@ const definitionsEncaissement = {
/* -------------------------------------------- */ /* -------------------------------------------- */
export class RdDUtility { export class RdDUtility {
/* -------------------------------------------- */
static async init() {
Hooks.on("renderChatMessage", async (app, html, msg) => RdDUtility.onRenderChatMessage(app, html, msg));
Hooks.on('renderChatLog', (log, html, data) => RdDUtility.chatListeners(html));
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async preloadHandlebarsTemplates() { static async preloadHandlebarsTemplates() {
const templatePaths = [ const templatePaths = [
@ -114,14 +101,8 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-entite-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-vehicule-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-competence-partial.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-competence-partial.html',
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-categorie-competences-partial.html',
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-oeuvre-partial.html',
'systems/foundryvtt-reve-de-dragon/templates/actor-liste-blessures-partial.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-liste-blessures-partial.html',
'systems/foundryvtt-reve-de-dragon/templates/actor-blessure-partial.html', 'systems/foundryvtt-reve-de-dragon/templates/actor-blessure-partial.html',
// Conteneur/item in Actor sheet
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-conteneur.html',
"systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-monnaie.html",
'systems/foundryvtt-reve-de-dragon/templates/actor-sheet-editor-notes-mj.html',
//Items //Items
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html',
@ -143,8 +124,6 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/item-ombre-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-ombre-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-monnaie-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-monnaie-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-meditation-sheet.html', 'systems/foundryvtt-reve-de-dragon/templates/item-meditation-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-nourritureboisson-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/item-signedraconique-sheet.html',
'systems/foundryvtt-reve-de-dragon/templates/competence-carac-defaut.html', 'systems/foundryvtt-reve-de-dragon/templates/competence-carac-defaut.html',
'systems/foundryvtt-reve-de-dragon/templates/competence-base.html', 'systems/foundryvtt-reve-de-dragon/templates/competence-base.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html',
@ -153,8 +132,6 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-parade.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-vehicule.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-competence.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-herbesoin-ingredient.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-categorie-potion.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-initpremierround.html',
'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html', 'systems/foundryvtt-reve-de-dragon/templates/enum-rarete.html',
'systems/foundryvtt-reve-de-dragon/templates/sort-draconic.html', 'systems/foundryvtt-reve-de-dragon/templates/sort-draconic.html',
@ -162,6 +139,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/niveau-ethylisme.html', 'systems/foundryvtt-reve-de-dragon/templates/niveau-ethylisme.html',
'systems/foundryvtt-reve-de-dragon/templates/casetmr-specific-list.html', 'systems/foundryvtt-reve-de-dragon/templates/casetmr-specific-list.html',
// Dialogs // Dialogs
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-ajustements.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-resolution.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-competence.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html',
@ -169,22 +147,17 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-encaisser.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-meditation.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-tmr.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-surenc.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-enctotal.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-alchimie.html',
'systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html', 'systems/foundryvtt-reve-de-dragon/templates/dialog-astrologie-joueur.html',
// Partials
'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffLibre.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-diffCondition.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-surenc.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-enctotal.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-moral.html',
'systems/foundryvtt-reve-de-dragon/templates/partial-select-carac.html',
// Calendrier // Calendrier
'systems/foundryvtt-reve-de-dragon/templates/calendar-template.html', 'systems/foundryvtt-reve-de-dragon/templates/calendar-template.html',
'systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html', 'systems/foundryvtt-reve-de-dragon/templates/calendar-editor-template.html',
'systems/foundryvtt-reve-de-dragon/templates/heures-select-option.html', 'systems/foundryvtt-reve-de-dragon/templates/heures-select-option.html',
// Conteneur/item in Actor sheet
'systems/foundryvtt-reve-de-dragon/templates/actor-inventaire-conteneur.html',
'systems/foundryvtt-reve-de-dragon/templates/editor-notes-mj.html',
// HUD // HUD
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html',
@ -207,10 +180,7 @@ export class RdDUtility {
'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-alchimie.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-resultat-alchimie.html',
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-turn-summary.html',
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-competence-xp.html',
'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html', 'systems/foundryvtt-reve-de-dragon/templates/chat-actor-carac-xp.html'
'systems/foundryvtt-reve-de-dragon/templates/chat-potionenchantee-chateaudormant.html',
'systems/foundryvtt-reve-de-dragon/templates/chat-fabriquer-potion-base.html',
'systems/foundryvtt-reve-de-dragon/templates/chat-signe-draconique-actor.html'
]; ];
Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null')); Handlebars.registerHelper('upperFirst', str => Misc.upperFirst(str ?? 'Null'));
@ -219,103 +189,10 @@ export class RdDUtility {
Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str)); Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str));
Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args)); Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args));
Handlebars.registerHelper('buildConteneur', (objet) => { return RdDUtility.buildConteneur(objet); }); Handlebars.registerHelper('buildConteneur', (objet) => { return RdDUtility.buildConteneur(objet); });
Handlebars.registerHelper('caseTmr-label', coord => TMRUtility.getTMRLabel(coord));
Handlebars.registerHelper('caseTmr-type', coord => TMRUtility.getTMRType(coord));
Handlebars.registerHelper('typeTmr-name', coord => TMRUtility.typeTmrName(coord));
Handlebars.registerHelper('min', (...args) => Math.min(...args.slice(0, -1)));
Handlebars.registerHelper('sortCompetence', competences => competences.sort((a, b) => {
if (a.name.startsWith("Survie") && b.name.startsWith("Survie")) {
if (a.name.includes("Cité")) return -1;
if (b.name.includes("Cité")) return 1;
if (a.name.includes("Extérieur")) return -1;
if (b.name.includes("Extérieur")) return 1;
return a.name.localeCompare(b.name);
}
if (a.data.categorie.startsWith("melee") && b.data.categorie.startsWith("melee")) {
if (a.name.includes("Corps")) return -1;
if (b.name.includes("Corps")) return 1;
if (a.name.includes("Dague")) return -1;
if (b.name.includes("Dague")) return 1;
if (a.name.includes("Esquive")) return -1;
if (b.name.includes("Esquive")) return 1;
return a.name.localeCompare(b.name);
}
if (a.name.startsWith("Voie") && b.name.startsWith("Voie")) {
if (a.name.includes("Oniros")) return -1;
if (b.name.includes("Oniros")) return 1;
if (a.name.includes("Hypnos")) return -1;
if (b.name.includes("Hypnos")) return 1;
if (a.name.includes("Narcos")) return -1;
if (b.name.includes("Narcos")) return 1;
if (a.name.includes("Thanatos")) return -1;
if (b.name.includes("Thanatos")) return 1;
return a.name.localeCompare(b.name);
}
return a.name.localeCompare(b.name);
}));
return loadTemplates(templatePaths); return loadTemplates(templatePaths);
} }
/* -------------------------------------------- */
static async creerObjet(actorSheet) {
let itemType = $(".item-type").val();
await actorSheet.createItem('Nouveau ' + itemType, itemType);
}
/* -------------------------------------------- */
static async selectObjetType( actorSheet) {
let typeObjets = RdDItem.getTypeObjetsEquipement();
let options = `<span class="competence-label">Selectionnez le type d'équipement</span><select class="item-type">`;
for (let typeName of typeObjets) {
options += `<option value="${typeName}">${typeName}</option>`
}
options += '</select>';
let d = new Dialog({
title: "Créer un équipement",
content: options,
buttons: {
one: {
icon: '<i class="fas fa-check"></i>',
label: "Créer l'objet",
callback: () => this.creerObjet(actorSheet)
}
}
});
d.render(true);
}
/* -------------------------------------------- */
static async selectTypeOeuvre( actorSheet) {
let typeObjets = RdDItem.getTypesOeuvres();
let options = `<span class="competence-label">Selectionnez le type d'oeuvre</span><select class="item-type">`;
for (let typeName of typeObjets) {
options += `<option value="${typeName}">${typeName}</option>`
}
options += '</select>';
let d = new Dialog({
title: "Créer un équipement",
content: options,
buttons: {
one: {
icon: '<i class="fas fa-check"></i>',
label: "Créer l'objet",
callback: () => this.creerObjet(actorSheet)
}
}
});
d.render(true);
}
/* -------------------------------------------- */
static buildListOptions(min, max) {
let options = ""
for (let i = min; i <= max; i++) {
options += `<option value="${i}">${i}</option>`
}
return options;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static checkNull(items) { static checkNull(items) {
@ -349,87 +226,93 @@ export class RdDUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static filterItemsPerTypeForSheet(formData) { static filterItemsPerTypeForSheet(formData) {
formData.materiel = this.checkNull(formData.itemsByType['objet']); formData.data.materiel = this.checkNull(formData.itemsByType['objet']);
formData.conteneurs = this.checkNull(formData.itemsByType['conteneur']); formData.data.conteneurs = this.checkNull(formData.itemsByType['conteneur']);
formData.armes = this.checkNull(formData.itemsByType['arme']); formData.data.armes = this.checkNull(formData.itemsByType['arme']);
formData.armures = this.checkNull(formData.itemsByType['armure']); formData.data.armures = this.checkNull(formData.itemsByType['armure']);
formData.livres = this.checkNull(formData.itemsByType['livre']); formData.data.livres = this.checkNull(formData.itemsByType['livre']);
formData.potions = this.checkNull(formData.itemsByType['potion']); formData.data.potions = this.checkNull(formData.itemsByType['potion']);
formData.ingredients = this.checkNull(formData.itemsByType['ingredient']); formData.data.ingredients = this.checkNull(formData.itemsByType['ingredient']);
formData.munitions = this.checkNull(formData.itemsByType['munition']); formData.data.munitions = this.checkNull(formData.itemsByType['munition']);
formData.herbes = this.checkNull(formData.itemsByType['herbe']); formData.data.herbes = this.checkNull(formData.itemsByType['herbe']);
formData.sorts = this.checkNull(formData.itemsByType['sort']); formData.data.sorts = this.checkNull(formData.itemsByType['sort']);
formData.signesdraconiques = this.checkNull(formData.itemsByType['signedraconique']); formData.data.queues = this.checkNull(formData.itemsByType['queue']);
formData.queues = this.checkNull(formData.itemsByType['queue']); formData.data.souffles = this.checkNull(formData.itemsByType['souffle']);
formData.souffles = this.checkNull(formData.itemsByType['souffle']); formData.data.ombres = this.checkNull(formData.itemsByType['ombre']);
formData.ombres = this.checkNull(formData.itemsByType['ombre']); formData.data.tetes = this.checkNull(formData.itemsByType['tete']);
formData.tetes = this.checkNull(formData.itemsByType['tete']); formData.data.taches = this.checkNull(formData.itemsByType['tache']);
formData.taches = this.checkNull(formData.itemsByType['tache']); formData.data.monnaie = this.checkNull(formData.itemsByType['monnaie']);
formData.monnaie = this.checkNull(formData.itemsByType['monnaie']); formData.data.meditations = this.checkNull(formData.itemsByType['meditation']);
formData.nourritureboissons = this.checkNull(formData.itemsByType['nourritureboisson']); formData.data.chants = this.checkNull(formData.itemsByType['chant']);
formData.meditations = this.checkNull(formData.itemsByType['meditation']); formData.data.danses = this.checkNull(formData.itemsByType['danse']);
formData.chants = this.checkNull(formData.itemsByType['chant']); formData.data.musiques = this.checkNull(formData.itemsByType['musique']);
formData.danses = this.checkNull(formData.itemsByType['danse']); formData.data.oeuvres = this.checkNull(formData.itemsByType['oeuvre']);
formData.musiques = this.checkNull(formData.itemsByType['musique']); formData.data.jeux = this.checkNull(formData.itemsByType['jeu']);
formData.oeuvres = this.checkNull(formData.itemsByType['oeuvre']); formData.data.recettescuisine = this.checkNull(formData.itemsByType['recettecuisine']);
formData.jeux = this.checkNull(formData.itemsByType['jeu']); formData.data.recettesAlchimiques = this.checkNull(formData.itemsByType['recettealchimique']);
formData.recettescuisine = this.checkNull(formData.itemsByType['recettecuisine']); formData.data.objets = formData.data.conteneurs.concat(formData.data.materiel)
formData.recettesAlchimiques = this.checkNull(formData.itemsByType['recettealchimique']); .concat(formData.data.armes)
formData.objets = formData.conteneurs.concat(formData.materiel) .concat(formData.data.armures)
.concat(formData.armes) .concat(formData.data.munitions)
.concat(formData.armures) .concat(formData.data.livres)
.concat(formData.munitions) .concat(formData.data.potions)
.concat(formData.livres) .concat(formData.data.herbes)
.concat(formData.potions) .concat(formData.data.ingredients);
.concat(formData.herbes) formData.data.competences = (formData.itemsByType.competence??[]).concat(formData.itemsByType.competencecreature??[]);
.concat(formData.ingredients)
.concat(formData.nourritureboissons)
.concat(formData.monnaie);
formData.competences = (formData.itemsByType.competence ?? []).concat(formData.itemsByType.competencecreature ?? []);
formData.monnaie.sort(Monnaie.triValeurDenier());
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static buildArbreDeConteneurs(conteneurs, objets) { static async processItemDropEvent(actorSheet, event) {
let objetVersConteneur = {}; let dragData = JSON.parse(event.dataTransfer.getData("text/plain"));
console.log(dragData, actorSheet.actor._id);
let dropID = $(event.target).parents(".item").attr("data-item-id"); // Only relevant if container drop
let objetId = dragData.id || dragData.data._id;
if (dragData.type == 'Item') {
if (dropID) { // Dropped over an item !!!
if (actorSheet.objetVersConteneur[objetId] != dropID && objetId != dropID) {
if (actorSheet.actor.validateConteneur(objetId, dropID) && actorSheet.actor.testConteneurCapacite(objetId, dropID)) {
await actorSheet.actor.enleverDeConteneur(objetId, actorSheet.objetVersConteneur[objetId]);
await actorSheet.actor.ajouterAConteneur(objetId, dropID);
}
}
}
if (dragData.actorId && dragData.actorId != actorSheet.actor._id) { // Un acteur est à l'origine de l'item -> deplacement
console.log("Moving objects");
actorSheet.actor.moveItemsBetweenActors(objetId, dragData.actorId);
return false;
}
actorSheet.actor.computeEncombrementTotalEtMalusArmure();
} else if (dragData.type == "Actor") {
actorSheet.actor.addSubacteur(objetId);
}
return true;
}
/* -------------------------------------------- */
static buildArbreDeConteneur(actorSheet, data) {
actorSheet.objetVersConteneur = {}; // Table de hash locale pour recupération rapide du conteneur parent (si existant)
// Attribution des objets aux conteneurs // Attribution des objets aux conteneurs
for (let conteneur of conteneurs) { for (let conteneur of data.data.conteneurs) {
conteneur.subItems = []; conteneur.subItems = [];
for (let id of conteneur.data.contenu ?? []) { if (!conteneur.data.encTotal) conteneur.data.encTotal = 0;
let objet = objets.find(objet => (id == objet._id)); //conteneur.data.encTotal = ; Deja calculé
if (conteneur.data.contenu) {
for (let id of conteneur.data.contenu) {
let objet = data.data.objets.find(objet => (id == objet._id));
if (objet) { if (objet) {
objet.estContenu = true; // Permet de filtrer ce qui est porté dans le template if (!objet.data.encombrement) objet.data.encombrement = 0; // Auto-fix
objetVersConteneur[id] = conteneur._id; objet.estContenu = true; // Permet de filtrer ce qifui est porté dans le template
actorSheet.objetVersConteneur[id] = conteneur._id;
conteneur.data.encTotal += Number(objet.data.encombrement) * Number(((objet.data.quantite) ? objet.data.quantite : 1));
conteneur.subItems.push(objet); conteneur.subItems.push(objet);
} }
} }
} }
for (let conteneur of conteneurs) {
conteneur.data.encTotal = RdDUtility.calculEncContenu(conteneur, objets);
} }
return objetVersConteneur;
}
static calculEncContenu(conteneur, objets) {
const itemData = Misc.data(conteneur);
const contenuDatas = (itemData.data.contenu ?? []).filter(id => id != undefined)
.map(id => Misc.data(objets.find(it => (id == it._id))))
.filter(it => it);
let enc = Number(itemData.data.encombrement ?? 0) * Number(itemData.data.quantite ?? 1);
for (let itemData of contenuDatas){
if (itemData.type == 'conteneur') {
enc += RdDUtility.calculEncContenu(itemData, objets);
}
else{
enc += Number(itemData.data.encombrement ?? 0) * Number(itemData.data.quantite ?? 1);
}
}
return enc;
}
// Construit la liste des conteneurs de niveau 1 (c'est à dire non contenu eux-même dans un conteneur) // Construit la liste des conteneurs de niveau 1 (c'est à dire non contenu eux-même dans un conteneur)
static conteneursRacine(conteneurs) { let newConteneurs = data.data.conteneurs.filter(function (conteneur, index, arr) { return !conteneur.estContenu });
return conteneurs.filter((conteneur, index, arr) => !conteneur.estContenu); data.data.conteneurs = newConteneurs;
//console.log(newConteneurs);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -440,7 +323,7 @@ export class RdDUtility {
if (!niveau) niveau = 1; if (!niveau) niveau = 1;
objet.niveau = niveau; objet.niveau = niveau;
//console.log("OBJ:", objet); //console.log("OBJ:", objet);
let str = Handlebars.partials['systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-conteneur.html']({ item: objet }); let str = Handlebars.partials['systems/foundryvtt-reve-de-dragon/templates/actor-inventaire-conteneur.html']({ item: objet });
if (objet.type == 'conteneur') { if (objet.type == 'conteneur') {
//console.log("ITEM DISPLAYED", objet ); //console.log("ITEM DISPLAYED", objet );
if (this.getAfficheContenu(objet._id)) { if (this.getAfficheContenu(objet._id)) {
@ -493,14 +376,6 @@ export class RdDUtility {
} }
return -7; return -7;
} }
static calculFatigueHtml(fatigue, endurance) {
return ReglesOptionelles.isUsing("appliquer-fatigue") ? {
malus: RdDUtility.calculMalusFatigue(fatigue, endurance),
html: "<table class='table-fatigue'>" + RdDUtility.makeHTMLfatigueMatrix(fatigue, endurance).html() + "</table>"
} : { malus: 0, html: '' };
}
/* -------------------------------------------- */ /* -------------------------------------------- */
// Build the nice (?) html table used to manage fatigue. // Build the nice (?) html table used to manage fatigue.
// max should be the endurance max value // max should be the endurance max value
@ -544,8 +419,8 @@ export class RdDUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getLocalisation(type = 'personnage') { static getLocalisation(type = 'personnage') {
let result = await RdDDice.rollTotal("1d20"); let result = new Roll("1d20").roll().total;
let txt = "" let txt = ""
if (type == 'personnage') { if (type == 'personnage') {
if (result <= 3) txt = "Jambe, genou, pied, jarret"; if (result <= 3) txt = "Jambe, genou, pied, jarret";
@ -577,9 +452,17 @@ export class RdDUtility {
return duplicate(table[0]); return duplicate(table[0]);
} }
/* -------------------------------------------- */
static _evaluatePerte(formula, over20) {
console.log("_evaluatePerte", formula, over20);
let perte = new Roll(formula, { over20: over20 });
perte.evaluate();
return perte.total;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static currentFatigueMalus(value, max) { static currentFatigueMalus(value, max) {
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
max = Math.max(1, Math.min(max, 60)); max = Math.max(1, Math.min(max, 60));
value = Math.min(max * 2, Math.max(0, value)); value = Math.min(max * 2, Math.max(0, value));
@ -593,19 +476,32 @@ export class RdDUtility {
} }
return -7; // This is the max ! return -7; // This is the max !
} }
return 0;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static async loadCompendiumData(compendium) { static async loadCompendiumNames(compendium) {
const pack = game.packs.get(compendium); const pack = game.packs.get(compendium);
return await pack?.getDocuments() ?? []; let competences;
await pack.getIndex().then(index => competences = index);
return competences;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async loadCompendium(compendium, filter = item => true) { static async loadCompendium(compendium, filter = item => true) {
let compendiumData = await RdDUtility.loadCompendiumData(compendium); if (!compendium){
return compendiumData.filter(filter); return [];
}
let compendiumItems = await RdDUtility.loadCompendiumNames(compendium);
const pack = game.packs.get(compendium);
let list = [];
for (let compendiumItem of compendiumItems) {
await pack.getEntity(compendiumItem._id).then(it => {
const item = it.data;
if (filter(item)) {
list.push(item);
}
});
};
return list;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -616,6 +512,7 @@ export class RdDUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static onSocketMesssage(sockmsg) { static onSocketMesssage(sockmsg) {
console.log(">>>>> MSG RECV", sockmsg);
switch (sockmsg.msg) { switch (sockmsg.msg) {
case "msg_gm_chat_message": case "msg_gm_chat_message":
return ChatUtility.handleGMChatMessage(sockmsg.data); return ChatUtility.handleGMChatMessage(sockmsg.data);
@ -626,14 +523,16 @@ export class RdDUtility {
case "msg_response_nombre_astral": case "msg_response_nombre_astral":
return RdDUtility.responseNombreAstral(sockmsg.data); return RdDUtility.responseNombreAstral(sockmsg.data);
case "msg_tmr_move": case "msg_tmr_move":
if (game.user.isGM) {
let actor = game.actors.get(sockmsg.data.actorId); let actor = game.actors.get(sockmsg.data.actorId);
if (actor.isOwner || game.user.isGM) {
actor.refreshTMRView(sockmsg.data.tmrPos); actor.refreshTMRView(sockmsg.data.tmrPos);
} }
break;
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async chatListeners(html) { static async chatListeners(html) {
RdDCombat.registerChatCallbacks(html); RdDCombat.registerChatCallbacks(html);
@ -653,72 +552,27 @@ export class RdDUtility {
let actor = game.actors.get(actorId); let actor = game.actors.get(actorId);
actor.tmrApp.lancerSortEnReserve(coord, sortId); actor.tmrApp.lancerSortEnReserve(coord, sortId);
}); });
// gestion bouton tchat Acheter
html.on("click", '.button-acheter', event => DialogItemAchat.onButtonAcheter(event));
// Gestion du bouton payer // Gestion du bouton payer
html.on("click", '.payer-button', event => { html.on("click", '#payer-button', event => {
let sumdenier = event.currentTarget.attributes['data-somme-denier']?.value ?? 0; let sumdenier = event.currentTarget.attributes['data-somme-denier'].value;
let quantite = event.currentTarget.attributes['data-quantite']?.value ?? 1; let quantite = 1;
let fromActorId = event.currentTarget.attributes['data-actor-id']?.value; if ( event.currentTarget.attributes['data-quantite'] ) {
quantite = event.currentTarget.attributes['data-quantite'].value;
}
let jsondata = event.currentTarget.attributes['data-jsondata'] let jsondata = event.currentTarget.attributes['data-jsondata']
let objData let objData
if (jsondata) { if (jsondata) {
objData = JSON.parse(jsondata.value) objData = JSON.parse(jsondata.value)
} }
let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:"); if (game.user.character) {
if (actor) { game.user.character.payerDenier(sumdenier, objData, quantite);
actor.depenserDeniers(sumdenier, objData, quantite, fromActorId); } else {
ChatUtility.removeChatMessageId(RdDUtility.findChatMessageId(event.currentTarget)); let msgPayer = "Vous devez avoir un acteur relié pour effectuer le paiement";
ChatMessage.create({ content: msgPayer, whisper: [game.user] });
} }
}); });
} }
static findChatMessageId(current) {
return RdDUtility.getChatMessageId(RdDUtility.findChatMessage(current));
}
static getChatMessageId(node) {
return node?.attributes.getNamedItem('data-message-id')?.value;
}
static findChatMessage(current) {
return RdDUtility.findNodeMatching(current, it => it.classList.contains('chat-message') && it.attributes.getNamedItem('data-message-id'));
}
static findNodeMatching(current, predicate) {
if (current) {
if (predicate(current)) {
return current;
}
return RdDUtility.findNodeMatching(current.parentElement, predicate);
}
return undefined;
}
static getSelectedActor(msgPlayer = undefined) {
if (canvas.tokens.controlled.length == 1) {
let token = canvas.tokens.controlled[0];
if (token.actor && token.data.actorLink) {
return token.actor;
}
if (msgPlayer != undefined) {
msgPlayer += "<br>le token sélectionné doit être lié à un personnage";
}
}
if (game.user.character) {
return game.user.character;
}
if (msgPlayer != undefined) {
msgPlayer += "<br>vous pouvez sélectionner un seul token lié à un personnage";
msgPlayer += "<br>vous devez être connecté comme joueur avec un personnage sélectionné";
ui.notifications.warn(msgPlayer);
ChatMessage.create({ content: msgPlayer, whisper: [game.user] });
}
return undefined;
}
/* -------------------------------------------- */ /* -------------------------------------------- */
static createMonnaie(name, valeur_deniers, img = "", enc = 0.01) { static createMonnaie(name, valeur_deniers, img = "", enc = 0.01) {
let piece = { let piece = {
@ -750,14 +604,14 @@ export class RdDUtility {
let sumtotald = sumd + (sums * 100); let sumtotald = sumd + (sums * 100);
let msgPayer = "La somme de " + sums + " Sols et " + sumd + " Deniers est à payer, cliquer sur le lien ci-dessous si besoin.<br>"; let msgPayer = "La somme de " + sums + " Sols et " + sumd + " Deniers est à payer, cliquer sur le lien ci-dessous si besoin.<br>";
msgPayer += "<a class='payer-button chat-card-button' data-somme-denier='" + sumtotald + "'>Payer</a>" msgPayer += "<a id='payer-button' class='chat-card-button' data-somme-denier='" + sumtotald + "'>Payer</a>"
ChatMessage.create({ content: msgPayer }); ChatMessage.create({ content: msgPayer });
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static chatDataSetup(content, modeOverride, isRoll = false, forceWhisper) { static chatDataSetup(content, modeOverride, isRoll = false, forceWhisper) {
let chatData = { let chatData = {
user: game.user.id, user: game.user._id,
rollMode: modeOverride || game.settings.get("core", "rollMode"), rollMode: modeOverride || game.settings.get("core", "rollMode"),
content: content content: content
}; };
@ -805,13 +659,7 @@ export class RdDUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async confirmerSuppression(actorSheet, li) { static async confirmerSuppression(actorSheet, li) {
let itemId = li.data("item-id"); let itemId = li.data("item-id");
let objet = actorSheet.actor.getObjet(itemId); let objet = actorSheet.actor.items.find(item => item._id == itemId);
if ( objet.type == 'monnaie' && Monnaie.isSystemMonnaie(objet) ) {
ui.notifications.warn("Suppression des monnaies de base impossible");
return;
}
let msgTxt = "<p>Etes vous certain de vouloir supprimer cet objet ?"; let msgTxt = "<p>Etes vous certain de vouloir supprimer cet objet ?";
let buttons = { let buttons = {
delete: { delete: {
@ -819,7 +667,7 @@ export class RdDUtility {
label: "Supprimer l'objet", label: "Supprimer l'objet",
callback: () => { callback: () => {
console.log("Delete : ", itemId); console.log("Delete : ", itemId);
actorSheet.actor.deleteEmbeddedDocuments('Item', [itemId]); actorSheet.actor.deleteOwnedItem(itemId);
li.slideUp(200, () => actorSheet.render(false)); li.slideUp(200, () => actorSheet.render(false));
} }
}, },
@ -828,9 +676,8 @@ export class RdDUtility {
label: "Annuler" label: "Annuler"
} }
} }
const docData = Misc.data(objet); if (objet.data.type == 'conteneur' && objet.data.data.contenu.length > 0) {
if (docData.type == 'conteneur' && docData.data.contenu.length > 0) { msgTxt += "<br>Cet objet est aussi un conteneur avec du contenu : choisissez l'option de suppression";
msgTxt += "<br>Ce conteneur n'est pas vide. Choisissez l'option de suppression";
buttons['deleteall'] = { buttons['deleteall'] = {
icon: '<i class="fas fa-check"></i>', icon: '<i class="fas fa-check"></i>',
label: "Supprimer le conteneur et tout son contenu", label: "Supprimer le conteneur et tout son contenu",
@ -854,23 +701,18 @@ export class RdDUtility {
/* -------------------------------------------- */ /* -------------------------------------------- */
static afficherHeuresChanceMalchance(heureNaissance) { static afficherHeuresChanceMalchance(heureNaissance) {
if ( game.user.isGM) { if ( game.user.isGM) {
let heure = game.system.rdd.calendrier.findHeure(heureNaissance); if (heureNaissance) {
if (heureNaissance && heure) {
let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance); let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance);
const current = game.system.rdd.calendrier.findHeure(game.system.rdd.calendrier.getCurrentHeure());
ChatMessage.create({ ChatMessage.create({
content: `A l'heure de <strong>${current.label}</strong>, le modificateur de Chance/Malchance est de <strong>${Misc.toSignedString(ajustement)}</strong> pour l'heure de naissance <strong>${heure.label}</strong>.`, content: `A l'heure ${game.system.rdd.calendrier.getCurrentHeure()}, le modificateur de Chance/Malchance pour l'heure de naissance ${heureNaissance} est de : ${ajustement}.`,
whisper: ChatMessage.getWhisperRecipients("GM") whisper: ChatMessage.getWhisperRecipients("GM")
}); });
} }
else if (heureNaissance) {
ui.notifications.warn(heureNaissance+" ne correspond pas à une heure de naissance");
}
else { else {
ui.notifications.warn("Pas d'heure de naissance selectionnée"); ui.notifications.warn("Pas d'heure de naissance selectionnée")
} }
} else { } else {
ui.notifications.warn("Vous n'avez pas accès à cette commande"); ui.notifications.warn("Vous n'avez pas accès à cette commande")
} }
} }
@ -885,32 +727,6 @@ export class RdDUtility {
} }
} }
/*-------------------------------------------- */
static distribuerStress(stressValue, raison = 'Inconnu', nomJoueur = undefined) {
if (game.user.isGM) {
if (stressValue == undefined){
ui.notifications.warn("Pas de valeuir de stress à distribuer!");
return;
}
if (nomJoueur == undefined) {
for (let actor of game.actors) {
if (actor.hasPlayerOwner && actor.isPersonnage() ) {
actor.addCompteurValue('stress', stressValue, raison);
ui.notifications.info(`${actor.name} a reçu ${stressValue} points de Stress (raison : ${raison})`);
}
}
} else {
//console.log(stressValue, nomJoueur);
let joueur = game.users.find(user => user.name.toLowerCase() == nomJoueur.toLowerCase());
//console.log("Player", joueur, joueur.character );
joueur.character.addCompteurValue('stress', stressValue, raison);
ui.notifications.info(`${joueur.character.name} a reçu ${stressValue} points de Stress (raison : ${raison})`);
}
} else {
ui.notifications.warn("Seul le MJ est autorisé à utiliser la commande /stress");
}
}
/*-------------------------------------------- */ /*-------------------------------------------- */
static async onRenderChatMessage(app, html, msg) { static async onRenderChatMessage(app, html, msg) {
// TODO // TODO

View File

@ -1,15 +1,12 @@
import { Misc } from "./misc.js";
const listeReglesOptionelles = [ const listeReglesOptionelles = [
{ name: 'recul', group: 'Règles de combat', descr: "Appliquer le recul en cas de particulière en force ou de charge" }, {name:'recul', group:'combat', descr:"Appliquer le recul en cas de particulière en force ou de charge"},
{ name: 'resistanceArmeParade', group: 'Règles de combat', descr: "Faire le jet de résistance des armes lors de parades pouvant les endommager" }, {name:'resistanceArmeParade', group:'combat', descr:"Faire le jet de résistance des armes lors de parades pouvant les endommager"},
{ name: 'deteriorationArmure', group: 'Règles de combat', descr: "Tenir compte de la détérioration des armures" }, {name:'deteriorationArmure', group:'combat', descr:"Tenir compte de la détérioration des armures"},
{ name: 'defenseurDesarme', group: 'Règles de combat', descr: "Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier" }, {name:'defenseurDesarme', group:'combat', descr:"Le défenseur peut être désarmé en parant une particulière en force ou une charge avec une arme autre qu'un bouclier"},
{ name: 'categorieParade', group: 'Règles de combat', descr: "Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes" }, {name:'categorieParade', group:'combat', descr:"Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes"},
{ name: 'tripleSignificative', group: 'Règles de combat', descr: "En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès" }, {name:'tripleSignificative', group:'combat', descr:"En cas de demi-surprise, d'attaque particulière en finesse, et de catégories d'armes différentes, le défenseur doit obtenir 1/8 des chances de succès"},
{ name: 'astrologie', group: 'Règles de générales', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels", default: true }, {name:'astrologie', group:'generale', descr:"Appliquer les ajustements astrologiques aux jets de chance et aux rituels"}
{ name: 'afficher-prix-joueurs', group: 'Règles de générales', descr: "Afficher le prix de l'équipement des joueurs", default: true },
{ name: 'appliquer-fatigue', group: 'Règles de générales', descr: "Appliquer les règles de fatigue", default: true },
]; ];
export class ReglesOptionelles extends FormApplication { export class ReglesOptionelles extends FormApplication {
@ -17,7 +14,7 @@ export class ReglesOptionelles extends FormApplication {
for (const regle of listeReglesOptionelles) { for (const regle of listeReglesOptionelles) {
const name = regle.name; const name = regle.name;
const id = ReglesOptionelles._getIdRegle(name); const id = ReglesOptionelles._getIdRegle(name);
game.settings.register("foundryvtt-reve-de-dragon", id, { name: id, scope: "world", config: false, default: regle.default == undefined ? true : regle.default, type: Boolean }); game.settings.register("foundryvtt-reve-de-dragon", id, { name: id, scope: "world", config: false, default: regle.default??true, type: Boolean });
} }
game.settings.registerMenu("foundryvtt-reve-de-dragon", "rdd-options-regles", { game.settings.registerMenu("foundryvtt-reve-de-dragon", "rdd-options-regles", {
@ -41,27 +38,25 @@ export class ReglesOptionelles extends FormApplication {
static get defaultOptions() { static get defaultOptions() {
const options = super.defaultOptions; const options = super.defaultOptions;
mergeObject(options, { mergeObject(options, {
id: "optional-settings", id: "combat-settings",
template: "systems/foundryvtt-reve-de-dragon/templates/regles-optionelles.html", template: "systems/foundryvtt-reve-de-dragon/templates/regles-optionelles.html",
height: 600, height: 600,
width: 350, width: 350,
minimizable: false, minimizable: false,
closeOnSubmit: true, closeOnSubmit: true,
title: "Règles optionnelles" title: "Options de combat"
}); });
return options; return options;
} }
getData() { getData() {
let formData = super.getData(); let formData = super.getData();
const regles = listeReglesOptionelles.map(it => { formData.regles = listeReglesOptionelles.map(it => {
it = duplicate(it); let r = duplicate(it);
it.id = ReglesOptionelles._getIdRegle(it.name); r.id = ReglesOptionelles._getIdRegle(r.name);
it.active = ReglesOptionelles.isUsing(it.name); r.active = ReglesOptionelles.isUsing(r.name);
return it; return r;
}); })
formData.regles = regles;
formData.groups = Misc.classify(regles, it => it.group);
return formData; return formData;
} }

View File

@ -5,7 +5,6 @@ import { RdDItemSort } from "./item-sort.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDBonus } from "./rdd-bonus.js"; import { RdDBonus } from "./rdd-bonus.js";
import { RdDCarac } from "./rdd-carac.js"; import { RdDCarac } from "./rdd-carac.js";
import { RdDUtility } from "./rdd-utility.js";
import { ReglesOptionelles } from "./regles-optionelles.js"; import { ReglesOptionelles } from "./regles-optionelles.js";
/** /**
@ -51,12 +50,12 @@ export const referenceAjustements = {
getValue: (rollData, actor) => RdDBonus.find(rollData.surpriseDefenseur).attaque, getValue: (rollData, actor) => RdDBonus.find(rollData.surpriseDefenseur).attaque,
}, },
etat: { etat: {
isUsed: (rollData, actor) => !RdDCarac.isIgnoreEtatGeneral(rollData), isUsed: (rollData, actor) => !RdDCarac.isIgnoreEtatGeneral(rollData.selectedCarac, rollData.competence),
getLabel: (rollData, actor) => 'Etat général', getLabel: (rollData, actor) => 'Etat général',
getValue: (rollData, actor) => actor.getEtatGeneral({ ethylisme: rollData.forceAlcool != undefined }) getValue: (rollData, actor) => actor.getEtatGeneral()
}, },
malusArmure: { malusArmure: {
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac), isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.competence),
isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac), isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac),
getLabel: (rollData, actor) => 'Malus armure', getLabel: (rollData, actor) => 'Malus armure',
getValue: (rollData, actor) => actor.getMalusArmure() getValue: (rollData, actor) => actor.getMalusArmure()
@ -121,24 +120,6 @@ export const referenceAjustements = {
isUsed: (rollData, actor) => rollData.tmr && rollData.rencontre?.name, isUsed: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
getLabel: (rollData, actor) => rollData.rencontre?.name, getLabel: (rollData, actor) => rollData.rencontre?.name,
getValue: (rollData, actor) => - (rollData.rencontre?.force ?? 0) getValue: (rollData, actor) => - (rollData.rencontre?.force ?? 0)
},
ethylismeAlcool: {
isVisible: (rollData, actor) => rollData.nbDoses != undefined,
isUsed: (rollData, actor) => rollData.nbDoses != undefined,
getLabel: (rollData, actor) => "Doses déjà bues: ",
getValue: (rollData, actor) => - rollData.nbDoses,
},
ethylismeDoses: {
isVisible: (rollData, actor) => rollData.nbDoses != undefined,
isUsed: (rollData, actor) => rollData.nbDoses != undefined,
getLabel: (rollData, actor) => "Force de l'alcool: ",
getValue: (rollData, actor) => rollData.forceAlcool,
},
ethylisme:{
isVisible: (rollData, actor) => rollData.ethylisme != undefined,
isUsed: (rollData, actor) => rollData.ethylisme != undefined,
getLabel: (rollData, actor) => "Ethylisme - " + RdDUtility.getNomEthylisme(rollData.ethylisme),
getValue: (rollData, actor) => rollData.ethylisme,
} }
} }
@ -150,7 +131,6 @@ export class RollDataAjustements {
for (var key in referenceAjustements) { for (var key in referenceAjustements) {
const reference = referenceAjustements[key]; const reference = referenceAjustements[key];
rollData.ajustements[key] = { rollData.ajustements[key] = {
visible: reference.isVisible && reference.isVisible(rollData, actor),
used: reference.isUsed(rollData, actor), used: reference.isUsed(rollData, actor),
label: reference.getLabel && reference.getLabel(rollData, actor), label: reference.getLabel && reference.getLabel(rollData, actor),
value: reference.getValue && reference.getValue(rollData, actor), value: reference.getValue && reference.getValue(rollData, actor),

View File

@ -1,6 +1,5 @@
import { Grammar } from "./grammar.js"; import { Grammar } from "./grammar.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { RdDDice } from "./rdd-dice.js";
import { TMRUtility } from "./tmr-utility.js"; import { TMRUtility } from "./tmr-utility.js";
import { TMRType } from "./tmr-utility.js"; import { TMRType } from "./tmr-utility.js";
@ -8,11 +7,11 @@ import { TMRType } from "./tmr-utility.js";
const typeRencontres = { const typeRencontres = {
messager: { messager: {
msgSucces: (rencData) => `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases ${rencData.tmr.label}.`, msgSucces: (data) => `Le ${data.rencontre.name} vous propose d'emmener le message de votre un sort à ${data.rencontre.force} cases ${data.tmr.label}.`,
msgEchec: (rencData) => `Le ${rencData.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`, msgEchec: (data) => `Le ${data.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`,
postSucces: (tmrDialog, rencData) => { postSucces: (tmrDialog, data) => {
tmrDialog.setStateRencontre(rencData.rencontre.type); tmrDialog.setStateRencontre(data.rencontre.type);
tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force); tmrDialog.choisirCasePortee(data.tmr.coord, data.rencontre.force);
}, },
poesieSucces: { poesieSucces: {
reference: "La chevelure, Charles Baudelaire", reference: "La chevelure, Charles Baudelaire",
@ -28,11 +27,11 @@ const typeRencontres = {
}, },
passeur: { passeur: {
msgSucces: (rencData) => `Le ${rencData.rencontre.name} vous propose de vous transporter à ${rencData.rencontre.force} cases des ${rencData.tmr.label}.`, msgSucces: (data) => `Le ${data.rencontre.name} vous propose de vous transporter à ${data.rencontre.force} cases des ${data.tmr.label}.`,
msgEchec: (rencData) => `Le prix que demande le ${rencData.rencontre.name} est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.`, msgEchec: (data) => `Le prix que demande le ${data.rencontre.name} est trop élevé, vous êtes réduit à poursuivre votre chemin par vos propres moyens.`,
postSucces: (tmrDialog, rencData) => { postSucces: (tmrDialog, data) => {
tmrDialog.setStateRencontre(rencData.rencontre.type); tmrDialog.setStateRencontre(data.rencontre.type);
tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force); tmrDialog.choisirCasePortee(data.tmr.coord, data.rencontre.force);
}, },
poesieSucces: { poesieSucces: {
reference: "Femmes damnées (2), Charles Baudelaire", reference: "Femmes damnées (2), Charles Baudelaire",
@ -49,9 +48,9 @@ const typeRencontres = {
}, },
fleur: { fleur: {
msgSucces: (rencData) => `Vous cueillez la ${rencData.rencontre.name}, son parfum vous apporte ${rencData.rencontre.force} points de Rêve.`, msgSucces: (data) => `Vous cueillez la ${data.rencontre.name}, son parfum vous apporte ${data.rencontre.force} points de Rêve.`,
msgEchec: (rencData) => `La ${rencData.rencontre.name} se fâne et disparaît entre vos doigts.`, msgEchec: (data) => `La ${data.rencontre.name} se fâne et disparaît entre vos doigts.`,
postSucces: (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(rencData.rencontre.force), postSucces: (tmrDialog, data) => tmrDialog.actor.reveActuelIncDec(data.rencontre.force),
poesieSucces: { poesieSucces: {
reference: "L'Ennemi, Charles Baudelaire", reference: "L'Ennemi, Charles Baudelaire",
extrait: `Et qui sait si les fleurs nouvelles que je rêve extrait: `Et qui sait si les fleurs nouvelles que je rêve
@ -66,9 +65,9 @@ const typeRencontres = {
}, },
mangeur: { mangeur: {
msgSucces: (rencData) => `Le ${rencData.rencontre.name} claque de sa machoire dans le vide avant de fuir.`, msgSucces: (data) => `Le ${data.rencontre.name} claque de sa machoire dans le vide avant de fuir.`,
msgEchec: (rencData) => `Le ${rencData.rencontre.name} croque votre Rêve ! Il emporte ${rencData.rencontre.force} de vos points de rêve actuels`, msgEchec: (data) => `Le ${data.rencontre.name} croque votre Rêve ! Il emporte ${data.rencontre.force} de vos points de rêve actuels`,
postEchec: (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(-rencData.rencontre.force), postEchec: (tmrDialog, data) => tmrDialog.actor.reveActuelIncDec(-data.rencontre.force),
poesieSucces: { poesieSucces: {
reference: "Conseil, Victor Hugo", reference: "Conseil, Victor Hugo",
extrait: `Rois ! la bure est souvent jalouse du velours. extrait: `Rois ! la bure est souvent jalouse du velours.
@ -85,16 +84,16 @@ const typeRencontres = {
}, },
changeur: { changeur: {
msgSucces: (rencData) => `Le ${rencData.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[rencData.tmr.type].name} de votre choix en échange de sa liberté.`, msgSucces: (data) => `Le ${data.rencontre.name} vaincu accepte de vous déplacer sur une autre ${TMRType[data.tmr.type].name} de votre choix en échange de sa liberté.`,
msgEchec: (rencData) => { msgEchec: (data) => {
rencData.newTMR = TMRUtility.getTMRAleatoire(it => it.type = rencData.tmr.type); data.newTMR = TMRUtility.getTMRAleatoire(it => it.type = data.tmr.type);
return `Le ${rencData.rencontre.name} vous embobine avec des promesses, et vous transporte en ${rencData.newTMR.label} sans attendre votre avis.`; return `Le ${data.rencontre.name} vous embobine avec des promesses, et vous transporte en ${data.newTMR.label} sans attendre votre avis.`;
}, },
postSucces: (tmrDialog, rencData) => { postSucces: (tmrDialog, data) => {
tmrDialog.setStateRencontre(rencData.rencontre.type); tmrDialog.setStateRencontre(data.rencontre.type);
tmrDialog.choisirCaseType(rencData.tmr.type); tmrDialog.choisirCaseType(data.tmr.type);
}, },
postEchec: (tmrDialog, rencData) => tmrDialog.forceDemiRevePosition(rencData.newTMR.coord), postEchec: (tmrDialog, data) => tmrDialog.forceDemiRevePosition(data.newTMR.coord),
poesieSucces: { poesieSucces: {
reference: "Caligula - IIIème chant, Gérard de Nerval", reference: "Caligula - IIIème chant, Gérard de Nerval",
extrait: `Allez, que le caprice emporte extrait: `Allez, que le caprice emporte
@ -111,9 +110,9 @@ const typeRencontres = {
}, },
briseur: { briseur: {
msgSucces: (rencData) => `Le ${rencData.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`, msgSucces: (data) => `Le ${data.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`,
msgEchec: (rencData) => `Le ${rencData.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`, msgEchec: (data) => `Le ${data.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`,
postEchec: (tmrDialog, rencData) => tmrDialog.close(), postEchec: (tmrDialog, data) => tmrDialog.close(),
poesieSucces: { poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud", reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `La légende affirme que ce sont les Gnomes qui furent extrait: `La légende affirme que ce sont les Gnomes qui furent
@ -134,8 +133,8 @@ const typeRencontres = {
}, },
reflet: { reflet: {
msgSucces: (rencData) => `Le ${rencData.rencontre.name} s'estompe dans l'oubli.`, msgSucces: (data) => `Le ${data.rencontre.name} s'estompe dans l'oubli.`,
msgEchec: (rencData) => `Vous êtes submergé par un ${rencData.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`, msgEchec: (data) => `Vous êtes submergé par un ${data.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`,
poesieSucces: { poesieSucces: {
reference: "Une charogne, Charles Baudelaire", reference: "Une charogne, Charles Baudelaire",
extrait: `Les formes s'effaçaient et n'étaient plus qu'un rêve, extrait: `Les formes s'effaçaient et n'étaient plus qu'un rêve,
@ -152,9 +151,9 @@ const typeRencontres = {
}, },
passeurfou: { passeurfou: {
msgSucces: (rencData) => `Le ${rencData.rencontre.name} tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.`, msgSucces: (data) => `Le ${data.rencontre.name} tente vainement de découvrir où vous avez caché vos réserves. Vous le chassez, et en déroute il part harceler un autre voyageur du rêve.`,
msgEchec: (rencData) => TMRRencontres.msgEchecPasseurFou(rencData), msgEchec: (data) => TMRRencontres.msgEchecPasseurFou(data),
postEchec: (tmrDialog, rencData) => TMRRencontres.postEchecPasseurFou(tmrDialog, rencData), postEchec: (tmrDialog, data) => TMRRencontres.postEchecPasseurFou(tmrDialog, data),
poesieSucces: { poesieSucces: {
reference: "Un Fou et un Sage, Jean de La Fontaine", reference: "Un Fou et un Sage, Jean de La Fontaine",
extrait: `Certain Fou poursuivait à coups de pierre un Sage. extrait: `Certain Fou poursuivait à coups de pierre un Sage.
@ -174,9 +173,9 @@ const typeRencontres = {
}, },
tbblanc: { tbblanc: {
msgSucces: (rencData) => `Le ${rencData.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`, msgSucces: (data) => `Le ${data.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`,
msgEchec: (rencData) => `Le souffle du ${rencData.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`, msgEchec: (data) => `Le souffle du ${data.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`,
postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 1), postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecTourbillon(tmrDialog, data, 1),
poesieSucces: { poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud", reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement extrait: `Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement
@ -191,9 +190,9 @@ const typeRencontres = {
}, },
tbnoir: { tbnoir: {
msgSucces: (rencData) => `Le ${rencData.rencontre.name} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.`, msgSucces: (data) => `Le ${data.rencontre.name} orageux vous enveloppe de fureur et d'éclairs, vous tenez bon face à la tempête qui s'éloigne sans vous éloigner de votre chemin.`,
msgEchec: (rencData) => `Le ${rencData.rencontre.name} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.`, msgEchec: (data) => `Le ${data.rencontre.name} furieux vous secoue tel un fichu de paille malmené par les vents, et vous emporte dans la tourmente.`,
postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 2), postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecTourbillon(tmrDialog, data, 2),
poesieSucces: { poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud", reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les extrait: `Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les
@ -207,9 +206,9 @@ const typeRencontres = {
}, },
tbrouge: { tbrouge: {
msgSucces: (rencData) => `Le ${rencData.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`, msgSucces: (data) => `Le ${data.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`,
msgEchec: (rencData) => `Le ${rencData.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`, msgEchec: (data) => `Le ${data.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`,
postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, rencData), postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, data),
poesieSucces: { poesieSucces: {
reference: "Qu'est-ce de votre vie ? une bouteille molle, Jean-Baptiste Chassignet", reference: "Qu'est-ce de votre vie ? une bouteille molle, Jean-Baptiste Chassignet",
extrait: `Qu'est-ce de votre vie ? un tourbillon rouant extrait: `Qu'est-ce de votre vie ? un tourbillon rouant
@ -228,10 +227,10 @@ const typeRencontres = {
}, },
rdd: { rdd: {
msgSucces: (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${rencData.rencontre.force} points de rêve`, msgSucces: (data) => `A tout seigneur, tout honneur, vous faites face à un ${data.rencontre.name}. Vous le maîtrisez et récupérez ses rêves. Vous gagnez ses ${data.rencontre.force} points de rêve`,
msgEchec: (rencData) => `A tout seigneur, tout honneur, vous faites face à un ${rencData.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${rencData.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`, msgEchec: (data) => `A tout seigneur, tout honneur, vous faites face à un ${data.rencontre.name}. La rencontre tourne au cauchemar, dans la lutte épique, vous subissez ${data.rolled.isETotal ? 'deux queues' : 'une queue'} de dragon!`,
postSucces: (tmrDialog, rencData) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, rencData), postSucces: (tmrDialog, data) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, data),
postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, rencData), postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, data),
poesieSucces: { poesieSucces: {
reference: "Rêve de Dragon, Denis Gerfaud", reference: "Rêve de Dragon, Denis Gerfaud",
extrait: `Le monde est Rêve de Dragons, mais nous ne savons extrait: `Le monde est Rêve de Dragons, mais nous ne savons
@ -325,12 +324,12 @@ export class TMRRencontres {
return false; return false;
} }
if (!roll || roll <= 0 || roll > 100) { if (!roll || roll <= 0 || roll > 100) {
roll = await RdDDice.rollTotal("1d100"); roll = new Roll("1d100").evaluate().total;
} }
let rencontre = await TMRRencontres.getRencontreAleatoire(terrain, roll); let rencontre = await TMRRencontres.getRencontreAleatoire(terrain, roll);
ChatMessage.create({ ChatMessage.create({
user: game.user.id, user: game.user._id,
whisper: [game.user.id], whisper: [game.user._id],
content: `Rencontre en ${terrain} (jet : ${roll}%)<br>Vous rencontrez un ${rencontre.name} de ${rencontre.force} Points de Rêve` content: `Rencontre en ${terrain} (jet : ${roll}%)<br>Vous rencontrez un ${rencontre.name} de ${rencontre.force} Points de Rêve`
}); });
return false; return false;
@ -357,13 +356,15 @@ export class TMRRencontres {
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getRencontreAleatoire(terrain, roll = undefined) { static async getRencontreAleatoire(terrain, roll = undefined) {
if (!roll || roll <= 0 || roll > 100) { if (!roll || roll <= 0 || roll > 100) {
roll = await RdDDice.rollTotal("1d100"); roll = new Roll("1d100").evaluate().total;
} }
terrain = Grammar.toLowerCaseNoAccent(terrain); terrain = Grammar.toLowerCaseNoAccent(terrain);
//console.log("getRencontreAleatoire", terrain, roll);
const code = tableRencontres[terrain].find(it => it.range[0] <= roll && roll <= it.range[1]).code; const code = tableRencontres[terrain].find(it => it.range[0] <= roll && roll <= it.range[1]).code;
const rencontre = duplicate(rencontresStandard.find(it => it.code == code)); const rencontre = duplicate(rencontresStandard.find(it => it.code == code));
rencontre.roll = roll; rencontre.roll = roll;
await TMRRencontres.evaluerForceRencontre(rencontre); await TMRRencontres.evaluerForceRencontre(rencontre);
//console.log(rencontre);
return rencontre; return rencontre;
} }
@ -372,14 +373,14 @@ export class TMRRencontres {
const rencontre = duplicate( const rencontre = duplicate(
(index && index >= 0 && index < mauvaisesRencontres.length) (index && index >= 0 && index < mauvaisesRencontres.length)
? mauvaisesRencontres[index] ? mauvaisesRencontres[index]
: await RdDDice.rollOneOf(mauvaisesRencontres)); : Misc.rollOneOf(mauvaisesRencontres));
await TMRRencontres.evaluerForceRencontre(rencontre); await TMRRencontres.evaluerForceRencontre(rencontre);
return rencontre; return rencontre;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async evaluerForceRencontre(rencontre) { static async evaluerForceRencontre(rencontre) {
rencontre.force = await new Roll(rencontre.force).evaluate().total; rencontre.force = new Roll(rencontre.force).evaluate().total;
return rencontre.force; return rencontre.force;
} }
@ -399,59 +400,58 @@ export class TMRRencontres {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async gererRencontre(tmrDialog, rencData) { static async gererRencontre(tmrDialog, data) {
let gestion = TMRRencontres.getGestionRencontre(rencData.rencontre.type); let gestion = TMRRencontres.getGestionRencontre(data.rencontre.type);
if (rencData.rolled.isSuccess) { if (data.rolled.isSuccess) {
rencData.message = gestion.msgSucces(rencData); data.message = gestion.msgSucces(data);
if (rencData.nbRounds > 1) { if (data.nbRounds > 1) {
rencData.message += ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`; data.message += ` Au total, vous avez passé ${data.nbRounds} rounds à vous battre!`;
} }
rencData.poesie = gestion.poesieSucces; data.poesie = gestion.poesieSucces;
return gestion.postSucces; return gestion.postSucces;
} }
rencData.message = gestion.msgEchec(rencData); data.message = gestion.msgEchec(data);
if (rencData.nbRounds > 1) { if (data.nbRounds > 1) {
rencData.message += ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`; data.message += ` Vous avez passé ${data.nbRounds} rounds à lutter!`;
} }
rencData.poesie = gestion.poesieEchec; data.poesie = gestion.poesieEchec;
return gestion.postEchec; return gestion.postEchec;
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async msgEchecPasseurFou(tmrData) { static msgEchecPasseurFou(data) {
tmrData.sortReserve = Misc.templateData(tmrData.actor).reve.reserve.list[0]; data.sortReserve = data.actor.data.data.reve.reserve.list[0];
if (tmrData.sortReserve) { if (data.sortReserve) {
// Passeur fou positionne sur la case d'un ort en réserve // TODO : Choisir le sort le plus loin ou au hasard // Passeur fou positionne sur la case d'un ort en réserve // TODO : Choisir le sort le plus loin ou au hasard
tmrData.newTMR = TMRUtility.getTMR(tmrData.sortReserve.coord); data.newTMR = TMRUtility.getTMR(data.sortReserve.coord);
} else { } else {
// Déplacement aléatoire de la force du Passeur Fou // Déplacement aléatoire de la force du Passeur Fou
const newCoord = await RdDDice.rollOneOf(TMRUtility.getTMRPortee(tmrData.tmr.coord, tmrData.rencontre.force)); const newCoord = Misc.rollOneOf(TMRUtility.getTMRPortee(data.tmr.coord, data.rencontre.force));
tmrData.newTMR = TMRUtility.getTMR(newCoord); data.newTMR = TMRUtility.getTMR(newCoord);
} }
if (tmrData.sortReserve) { if (data.sortReserve) {
return `Le ${tmrData.rencontre.name} vous dérobe la clé de vos sorts. Vous vous saisissez de lui, mais dans un nuage violet, il vous emporte en ${tmrData.newTMR.label} déclencher votre sort en réserve de ${tmrData.sortReserve.name}.`; return `Le ${data.rencontre.name} vous dérobe la clé de vos sorts. Vous vous saisissez de lui, mais dans un nuage violet, il vous emporte en ${data.newTMR.label} déclencher votre sort en réserve de ${data.sortReserve.name}.`;
} }
else { else {
return `Le ${tmrData.rencontre.name} tente de vous dérober la clé de vos sorts. Ne la trouvant pas, il déclenche un nuage violet et vous emporte en ${tmrData.newTMR.label}`; return `Le ${data.rencontre.name} tente de vous dérober la clé de vos sorts. Ne la trouvant pas, il déclenche un nuage violet et vous emporte en ${data.newTMR.label}`;
} }
} }
/* -------------------------------------------- */ static async postEchecPasseurFou(tmrDialog, data) {
static async postEchecPasseurFou(tmrDialog, tmrData) { if (data.sortReserve) {
if (tmrData.sortReserve) { await tmrDialog.processSortReserve(data.sortReserve);
await tmrDialog.processSortReserve(tmrData.sortReserve);
} }
await tmrDialog.forceDemiRevePosition(tmrData.newTMR.coord); await tmrDialog.forceDemiRevePosition(data.newTMR.coord);
if (tmrData.sortReserve) { if (data.sortReserve) {
tmrDialog.close(); tmrDialog.close();
} }
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async onPostEchecTourbillon(tmrDialog, tmrData, cases) { static async onPostEchecTourbillon(tmrDialog, data, cases) {
await tmrData.actor.reveActuelIncDec(-cases); await data.actor.reveActuelIncDec(-cases);
await TMRRencontres._toubillonner(tmrDialog, tmrData.actor, cases); await TMRRencontres._toubillonner(tmrDialog, data.actor, cases);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -461,26 +461,23 @@ export class TMRRencontres {
await data.actor.santeIncDec("vie", -1); // Et -1 PV await data.actor.santeIncDec("vie", -1); // Et -1 PV
} }
/* -------------------------------------------- */
static async _toubillonner(tmrDialog, actor, cases) { static async _toubillonner(tmrDialog, actor, cases) {
let coord = Misc.templateData(actor).reve.tmrpos.coord; let coord = actor.data.data.reve.tmrpos.coord;
for (let i = 0; i < cases; i++) { for (let i = 0; i < cases; i++) {
coord = await TMRUtility.deplaceTMRAleatoire(actor, coord).coord; coord = TMRUtility.deplaceTMRAleatoire(actor, coord).coord;
} }
await tmrDialog.forceDemiRevePosition(coord) await tmrDialog.forceDemiRevePosition(coord)
} }
/* -------------------------------------------- */ static async onPostSuccessReveDeDragon(tmrDialog, data) {
static async onPostSuccessReveDeDragon(tmrDialog, tmrData) { if (data.rolled.isPart) {
if (tmrData.rolled.isPart) { await data.actor.appliquerExperience(data.rolled, 'reve', data.competence);
await tmrData.actor.appliquerAjoutExperience(tmrData, true);
} }
await tmrData.actor.resultCombatReveDeDragon(tmrData); await data.actor.resultCombatReveDeDragon(data);
} }
/* -------------------------------------------- */ static async onPostEchecReveDeDragon(tmrDialog, data) {
static async onPostEchecReveDeDragon(tmrDialog, tmrData) { await data.actor.resultCombatReveDeDragon(data);
await tmrData.actor.resultCombatReveDeDragon(tmrData);
tmrDialog.close(); tmrDialog.close();
} }
} }

View File

@ -1,7 +1,5 @@
import { TMRRencontres } from "./tmr-rencontres.js"; import { TMRRencontres } from "./tmr-rencontres.js";
import { Misc } from "./misc.js"; import { Misc } from "./misc.js";
import { Grammar } from "./grammar.js";
import { RdDDice } from "./rdd-dice.js";
/* -------------------------------------------- */ /* -------------------------------------------- */
const TMRMapping = { const TMRMapping = {
@ -337,23 +335,9 @@ export class TMRUtility {
return TMRMapping[coord]?.label ?? (coord + ": case inconnue"); return TMRMapping[coord]?.label ?? (coord + ": case inconnue");
} }
static getTMRType(coord) {
const tmr = TMRMapping[coord];
return Misc.upperFirst(TMRType[tmr.type].name);
}
static getTMRDescr(coord) { static getTMRDescr(coord) {
const tmr = TMRMapping[coord]; const tmr = TMRMapping[coord];
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label; return Grammar.articleDetermine(tmr.genre) + ' ' + tmr.label;
}
static typeTmrName(type){
return Misc.upperFirst(TMRType[Grammar.toLowerCaseNoAccent(type)].name);
}
static listSelectedTMR(typesTMR) {
return Object.values(TMRType).map(value => Misc.upperFirst(value.name))
.sort()
.map(name => { return { name: name, selected: typesTMR.includes(name) } });
} }
static isCaseHumide(tmr) { static isCaseHumide(tmr) {
@ -390,13 +374,12 @@ export class TMRUtility {
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
static async getDirectionPattern() { static getDirectionPattern() {
return await RdDDice.rollOneOf(tmrRandomMovePatten); return Misc.rollOneOf(tmrRandomMovePatten);
} }
/* -------------------------------------------- */ static deplaceTMRAleatoire(actor, coord) {
static async deplaceTMRAleatoire(actor, coord) { return TMRUtility.deplaceTMRSelonPattern(actor, coord, TMRUtility.getDirectionPattern(), 1);
return TMRUtility.deplaceTMRSelonPattern(actor, coord, await TMRUtility.getDirectionPattern(), 1);
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -428,8 +411,8 @@ export class TMRUtility {
return TMRUtility.filterTMR(filter).map(it => it.coord); return TMRUtility.filterTMR(filter).map(it => it.coord);
} }
static async getTMRAleatoire(filter = it => true) { static getTMRAleatoire(filter = it => true) {
return await RdDDice.rollOneOf(TMRUtility.filterTMR(filter)) return Misc.rollOneOf(TMRUtility.filterTMR(filter))
} }
/* -------------------------------------------- */ /* -------------------------------------------- */
@ -482,14 +465,12 @@ export class TMRUtility {
return caseList; return caseList;
} }
/* -------------------------------------------- */
static distanceTMR(coord1, coord2) { static distanceTMR(coord1, coord2) {
let pos1 = this.convertToCellPos(coord1); let pos1 = this.convertToCellPos(coord1);
let pos2 = this.convertToCellPos(coord2); let pos2 = this.convertToCellPos(coord2);
return this.distancePosTMR(pos1, pos2); return this.distancePosTMR(pos1, pos2);
} }
/* -------------------------------------------- */
static distancePosTMR(pos1, pos2) { static distancePosTMR(pos1, pos2) {
const dx = pos2.x - pos1.x; const dx = pos2.x - pos1.x;
const dy = pos2.y - pos1.y; const dy = pos2.y - pos1.y;

View File

@ -1,6 +1,5 @@
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDDice } from "../rdd-dice.js";
import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js"; import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js";
import { Draconique } from "./draconique.js"; import { Draconique } from "./draconique.js";
@ -16,7 +15,7 @@ export class Conquete extends Draconique {
async onActorCreateOwned(actor, item) { await this._creerConquete(actor, item); } async onActorCreateOwned(actor, item) { await this._creerConquete(actor, item); }
code() { return 'conquete' } code() { return 'conquete' }
tooltip(linkData) { return `${this.tmrLabel(linkData)}: doit être conquis` } tooltip(linkData) { return `La ${this.tmrLabel(linkData)} doit être conquise` }
img() { return 'icons/svg/combat.svg' } img() { return 'icons/svg/combat.svg' }
createSprite(pixiTMR) { createSprite(pixiTMR) {
@ -30,14 +29,14 @@ export class Conquete extends Draconique {
} }
async _creerConquete(actor, queue) { async _creerConquete(actor, queue) {
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => Misc.data(it).data.coord); let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
let possibles = TMRUtility.filterTMR(tmr => !TMRUtility.isCaseHumide(tmr) && !existants.includes(tmr.coord)); let possibles = TMRUtility.filterTMR(tmr => !TMRUtility.isCaseHumide(tmr) && !existants.includes(tmr.coord));
let conquete = await RdDDice.rollOneOf(possibles); let conquete = Misc.rollOneOf(possibles);
await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue.id); await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue._id);
} }
async onActorDeleteCaseTmr(actor, casetmr) { async onActorDeleteCaseTmr(actor, casetmr) {
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]); await actor.deleteOwnedItem(casetmr.data.sourceid);
} }
} }

View File

@ -13,20 +13,20 @@ export class Debordement extends Draconique {
manualMessage() { return false } manualMessage() { return false }
async onActorCreateOwned(actor, souffle) { async onActorCreateOwned(actor, souffle) {
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
const tmr = await TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord))); const tmr = TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord)));
await this.createCaseTmr(actor, 'Debordement: ' + tmr.label, tmr, souffle.id); await this.createCaseTmr(actor, 'Debordement: ' + tmr.label, tmr, souffle._id);
} }
code() { return 'debordement' } code() { return 'debordement' }
tooltip(linkData) { return `Débordement en ${this.tmrLabel(linkData)}` } tooltip(linkData) { return `Débordement en ${this.tmrLabel(linkData)}` }
img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/wave.webp' } img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/wave.svg' }
createSprite(pixiTMR) { createSprite(pixiTMR) {
return pixiTMR.sprite(this.code(), { return pixiTMR.sprite(this.code(), {
color: tmrColors.casehumide,
zIndex: tmrTokenZIndex.casehumide, zIndex: tmrTokenZIndex.casehumide,
alpha: 0.6, taille: tmrConstants.twoThird,
taille: tmrConstants.full, decallage: tmrConstants.bottom
decallage: tmrConstants.center
}); });
} }

View File

@ -1,6 +1,5 @@
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { Misc } from "../misc.js"; import { Misc } from "../misc.js";
import { RdDDice } from "../rdd-dice.js";
import { tmrColors, tmrConstants, tmrTokenZIndex, TMRType, TMRUtility } from "../tmr-utility.js"; import { tmrColors, tmrConstants, tmrTokenZIndex, TMRType, TMRUtility } from "../tmr-utility.js";
import { Draconique } from "./draconique.js"; import { Draconique } from "./draconique.js";
@ -14,7 +13,7 @@ export class Desorientation extends Draconique {
manualMessage() { return false } manualMessage() { return false }
async onActorCreateOwned(actor, souffle) { async onActorCreateOwned(actor, souffle) {
const type = await RdDDice.rollOneOf(this._typesPossibles(actor)); const type = Misc.rollOneOf(this._typesPossibles(actor));
console.log("désorientation", type); console.log("désorientation", type);
souffle.name += ": " + TMRType[type].name; souffle.name += ": " + TMRType[type].name;
await this._creerCasesTmr(actor, type, souffle); await this._creerCasesTmr(actor, type, souffle);
@ -44,7 +43,7 @@ export class Desorientation extends Draconique {
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
let tmrs = TMRUtility.filterTMR(it => it.type == type && !existants.includes(it.coord)); let tmrs = TMRUtility.filterTMR(it => it.type == type && !existants.includes(it.coord));
for (let tmr of tmrs) { for (let tmr of tmrs) {
await this.createCaseTmr(actor, 'Désorientation: ' + tmr.label, tmr, souffle.id); await this.createCaseTmr(actor, 'Désorientation: ' + tmr.label, tmr, souffle._id);
} }
} }

View File

@ -1,4 +1,3 @@
import { Misc } from "../misc.js";
import { TMRUtility } from "../tmr-utility.js"; import { TMRUtility } from "../tmr-utility.js";
import { PixiTMR } from "./pixi-tmr.js"; import { PixiTMR } from "./pixi-tmr.js";
@ -9,11 +8,11 @@ const registeredEffects = [
* Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR * Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR
*/ */
export class Draconique { export class Draconique {
static isCaseTMR(itemData) { return itemData.type == 'casetmr'; } static isCaseTMR(element) { return element.type == 'casetmr'; }
static isQueueDragon(itemData) { return itemData.type == 'queue' || itemData.type == 'ombre'; } static isQueueDragon(element) { return element.type == 'queue' || element.type == 'ombre'; }
static isSouffleDragon(itemData) { return itemData.type == 'souffle'; } static isSouffleDragon(element) { return element.type == 'souffle'; }
static isTeteDragon(itemData) { return itemData.type == 'tete'; } static isTeteDragon(element) { return element.type == 'tete'; }
static isQueueSouffle(itemData) { return Draconique.isQueueDragon(itemData) || Draconique.isSouffleDragon(itemData); } static isQueueSouffle(it) { return Draconique.isQueueDragon(it) || Draconique.isSouffleDragon(it); }
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.data.coord); } tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.data.coord); }
@ -38,8 +37,7 @@ export class Draconique {
* @returns true si l'item correspond * @returns true si l'item correspond
*/ */
match(item) { match(item) {
const itemData = Misc.data(item); return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item) || Draconique.isTeteDragon(item);
return Draconique.isQueueDragon(itemData) || Draconique.isSouffleDragon(itemData) || Draconique.isTeteDragon(itemData);
} }
/** /**
@ -112,40 +110,35 @@ export class Draconique {
/** /**
* *
* @param {*} item un item à tester * @param {*} it un item à tester
* @param {*} coord les coordonnées d'une case. Si undefined toute case du type correspondra, * @param {*} coord les coordonnées d'une case. Si undefined toute case du type correspondra,
*/ */
isCase(item, coord = undefined) { isCase(it, coord = undefined) {
const itemData = Misc.data(item); return Draconique.isCaseTMR(it) && it.data.specific == this.code() && (coord ? it.data.coord == coord : true);
return Draconique.isCaseTMR(itemData) && itemData.data.specific == this.code() && (coord ? itemData.data.coord == coord : true);
} }
find(list, coord = undefined) { find(list, coord = undefined) {
return list.find(c => this.isCase(Misc.data(c), coord)); return list.find(c => this.isCase(c, coord));
} }
async createCaseTmr(actor, label, tmr, sourceId = undefined) { async createCaseTmr(actor, label, tmr, sourceId = undefined) {
const casetmrData = { await actor.createOwnedItem({
name: label, type: 'casetmr', img: this.img(), name: label, type: 'casetmr', img: this.img(), _id: randomID(16),
data: { coord: tmr.coord, specific: this.code(), sourceid: sourceId } data: { coord: tmr.coord, specific: this.code(), sourceid: sourceId }
}; });
await actor.createEmbeddedDocuments('Item', [casetmrData]);
} }
async deleteCasesTmr(actor, draconique) { async deleteCasesTmr(actor, draconique) {
let caseTmrs = actor.data.items.filter(it => this.isCaseForSource(it, draconique)); let caseTmrs = actor.data.items.filter(it => this.isCase(it) && it.data.sourceid == draconique._id);
await actor.deleteEmbeddedDocuments('Item', caseTmrs.map(it => it.id)); for (let casetmr of caseTmrs) {
await actor.deleteOwnedItem(casetmr._id);
} }
isCaseForSource(item, draconique) {
const itemData = Misc.data(item);
return Draconique.isCaseTMR(itemData) && itemData.data.specific == this.code() && itemData.data.sourceid == draconique.id;
} }
async onVisiteSupprimer(actor, tmr, onRemoveToken) { async onVisiteSupprimer(actor, tmr, onRemoveToken) {
let existants = actor.data.items.filter(it => this.isCase(it, tmr.coord)); let existants = actor.data.items.filter(it => this.isCase(it, tmr.coord));
await actor.deleteEmbeddedDocuments('Item', existants.map(it => it.id));
for (let casetmr of existants) { for (let casetmr of existants) {
await actor.deleteOwnedItem(casetmr._id);
onRemoveToken(tmr, casetmr); onRemoveToken(tmr, casetmr);
} }
} }

View File

@ -186,7 +186,7 @@ export class EffetsDraconiques {
} }
static toItems(item) { static toItems(item) {
return (item?.documentName === 'Actor') ? item.data.items : (item?.documentName === 'Item') ? [Misc.data(item)] : []; return (item?.entity === 'Actor') ? item.data.items : (item?.entity === 'Item') ? [Misc.data(item)] : [];
} }
} }

View File

@ -32,7 +32,7 @@ export class FermetureCites extends Draconique {
let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord); let existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
let ouvertes = TMRUtility.filterTMR(it => it.type == 'cite' && !existants.includes(it.coord)); let ouvertes = TMRUtility.filterTMR(it => it.type == 'cite' && !existants.includes(it.coord));
for (let tmr of ouvertes) { for (let tmr of ouvertes) {
await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr, souffle.id); await this.createCaseTmr(actor, 'Fermeture: ' + tmr.label, tmr, souffle._id);
} }
} }
} }

View File

@ -13,26 +13,26 @@ export class Pelerinage extends Draconique {
manualMessage() { return false } manualMessage() { return false }
async onActorCreateOwned(actor, queue) { async onActorCreateOwned(actor, queue) {
let tmr = await TMRUtility.getTMRAleatoire(); let tmr = TMRUtility.getTMRAleatoire();
await this.createCaseTmr(actor, 'Pèlerinage: ' + tmr.label, tmr, queue.id); await this.createCaseTmr(actor, 'Pèlerinage: ' + tmr.label, tmr, queue._id);
} }
code() { return 'pelerinage' } code() { return 'pelerinage' }
tooltip(linkData) { return `Votre pèlerinage en ${this.tmrLabel(linkData)}` } tooltip(linkData) { return `Votre pèlerinage en ${this.tmrLabel(linkData)}` }
img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/pelerin.webp' } img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/pelerin.svg' }
createSprite(pixiTMR) { createSprite(pixiTMR) {
return pixiTMR.sprite(this.code(), { return pixiTMR.sprite(this.code(), {
zIndex: tmrTokenZIndex.conquete, zIndex: tmrTokenZIndex.conquete,
alpha: 1, alpha: 1,
taille: tmrConstants.full, taille: tmrConstants.twoThird,
decallage: tmrConstants.center decallage: tmrConstants.right
}); });
} }
async onActorDeleteCaseTmr(actor, casetmr) { async onActorDeleteCaseTmr(actor, casetmr) {
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]); await actor.deleteOwnedItem(casetmr.data.sourceid);
} }
} }

View File

@ -1,6 +1,5 @@
import { Grammar } from "../grammar.js"; import { Grammar } from "../grammar.js";
import { RdDDice } from "../rdd-dice.js"; import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js";
import { tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js";
import { Draconique } from "./draconique.js"; import { Draconique } from "./draconique.js";
export class Periple extends Draconique { export class Periple extends Draconique {
@ -14,24 +13,25 @@ export class Periple extends Draconique {
manualMessage() { return false } manualMessage() { return false }
async onActorCreateOwned(actor, souffle) { async onActorCreateOwned(actor, souffle) {
let terrain = (await RdDDice.rollTotal("1d2")) == 1 ? 'sanctuaire' : 'necropole'; let terrain = new Roll("1d2").evaluate().total == 1 ? 'sanctuaire' : 'necropole';
let tmrs = TMRUtility.getListTMR(terrain); let tmrs = TMRUtility.getListTMR(terrain);
for (let tmr of tmrs) { for (let tmr of tmrs) {
await this.createCaseTmr(actor, 'Périple: ' + tmr.label, tmr, souffle.id); await this.createCaseTmr(actor, 'Périple: ' + tmr.label, tmr, souffle._id);
} }
} }
code() { return 'periple' } code() { return 'periple' }
tooltip(linkData) { return `Votre Périple passe par ${this.tmrLabel(linkData)}` } tooltip(linkData) { return `Votre Périple passe par ${this.tmrLabel(linkData)}` }
img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/pelerin.webp' } img() { return 'icons/svg/acid.svg' }
createSprite(pixiTMR) { createSprite(pixiTMR) {
return pixiTMR.sprite(this.code(), { return pixiTMR.sprite(this.code(), {
zIndex: tmrTokenZIndex.conquete, zIndex: tmrTokenZIndex.conquete,
alpha: 1, alpha: 1,
taille: tmrConstants.full, color: tmrColors.souffle,
decallage: tmrConstants.center taille: tmrConstants.twoThird,
decallage: tmrConstants.right
}); });
} }
getDifficulte(tmr) { getDifficulte(tmr) {

View File

@ -20,13 +20,12 @@ export class PixiTMR {
this.callbacksOnAnimate = []; this.callbacksOnAnimate = [];
} }
load( onLoad = (loader, resources) => {} ) { load(onLoad = (loader, resources) => {}) {
let loader = this.pixiApp.loader; let loader = this.pixiApp.loader;
for (const [name, img] of Object.entries(PixiTMR.textures)) { for (const [name, img] of Object.entries(PixiTMR.textures)) {
loader = loader.add(name, img); loader = loader.add(name, img);
} }
loader.onLoad.add((error, resaon) => { console.log("ERROR", error, resaon) }); loader.load((loader, resources) => {
loader.load( (loader, resources) => {
onLoad(loader, resources); onLoad(loader, resources);
for (let onAnimate of this.callbacksOnAnimate) { for (let onAnimate of this.callbacksOnAnimate) {
onAnimate(); onAnimate();

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