Gestion des signes draconiques #455
2
.gitignore
vendored
@ -1,3 +1,5 @@
|
||||
.vscode/settings.json
|
||||
.idea
|
||||
todo.txt
|
||||
todo.md
|
||||
/.vscode
|
||||
|
61
dev-notes.md
Normal file
@ -0,0 +1,61 @@
|
||||
# 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 — Aujourd’hui à 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/heuresdraconiques2.ttf
Normal file
BIN
fonts/heuresdraconiques2.woff
Normal file
BIN
fonts/heuresdraconiques2.woff2
Normal file
BIN
icons/creatures/aligate_t.webp
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
icons/creatures/araflate_t.webp
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
icons/creatures/bandersnatch_t.webp
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
icons/creatures/bramart_t.webp
Normal file
After Width: | Height: | Size: 52 KiB |
BIN
icons/creatures/brolute_t.webp
Normal file
After Width: | Height: | Size: 8.5 KiB |
BIN
icons/creatures/chamule_t.webp
Normal file
After Width: | Height: | Size: 24 KiB |
BIN
icons/creatures/cheval_t.webp
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
icons/creatures/chiard_t.webp
Normal file
After Width: | Height: | Size: 13 KiB |
BIN
icons/creatures/chien_t.webp
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
icons/creatures/chrasme_t.webp
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
icons/creatures/cornicochon_t.webp
Normal file
After Width: | Height: | Size: 32 KiB |
BIN
icons/creatures/dong_t.webp
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
icons/creatures/drakkule_t.webp
Normal file
After Width: | Height: | Size: 7.8 KiB |
BIN
icons/creatures/felorn_t.webp
Normal file
After Width: | Height: | Size: 15 KiB |
BIN
icons/creatures/harpie_t.webp
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
icons/heures/de-heures.webp
Normal file
After Width: | Height: | Size: 4.3 KiB |
BIN
icons/heures/hd01.webp
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
icons/heures/hd02.webp
Normal file
After Width: | Height: | Size: 4.0 KiB |
BIN
icons/heures/hd03.webp
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
icons/heures/hd04.webp
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
icons/heures/hd05.webp
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
icons/heures/hd06.webp
Normal file
After Width: | Height: | Size: 3.1 KiB |
BIN
icons/heures/hd07.webp
Normal file
After Width: | Height: | Size: 3.2 KiB |
BIN
icons/heures/hd08.webp
Normal file
After Width: | Height: | Size: 2.6 KiB |
BIN
icons/heures/hd09.webp
Normal file
After Width: | Height: | Size: 2.9 KiB |
BIN
icons/heures/hd10.webp
Normal file
After Width: | Height: | Size: 3.3 KiB |
BIN
icons/heures/hd11.webp
Normal file
After Width: | Height: | Size: 2.1 KiB |
BIN
icons/heures/hd12.webp
Normal file
After Width: | Height: | Size: 3.2 KiB |
@ -1,130 +1,103 @@
|
||||
<?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">
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 24.1.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1"
|
||||
id="Capa_1" inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)" sodipodi:docname="gift.svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="512px" height="512px"
|
||||
viewBox="0 0 512 512" style="enable-background:new 0 0 512 512;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#FFFFFF;}
|
||||
</style>
|
||||
<sodipodi:namedview bordercolor="#666666" borderopacity="1" gridtolerance="10" guidetolerance="10" id="namedview47" inkscape:current-layer="g14" inkscape:cx="64" inkscape:cy="163.34211" inkscape:document-rotation="0" inkscape:pageopacity="0" inkscape:pageshadow="2" inkscape:window-height="2066" inkscape:window-maximized="1" inkscape:window-width="3840" inkscape:window-x="-11" inkscape:window-y="-11" inkscape:zoom="2.415894" objecttolerance="10" pagecolor="#ffffff" showgrid="false">
|
||||
</sodipodi:namedview>
|
||||
<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)">
|
||||
<path id="path2" class="st0" d="M81.2,212.4c-9.9,13.1-19.3,25.5-8.3,47.1c5,9.7,18.1,11.8,28.3,11.8c20.9,0,45.1-8.1,63-19.2
|
||||
c-3-3.7-6.1-8.2-6.1-13.9c0-6.6,4.1-11.6,7.5-15.6c1.6-1.9,3.4-4.1,3.9-5.6c0.5-1.6,0.4-4.4,0.2-7.2c-0.3-5.1-0.7-11.5,3.1-16.6
|
||||
c2.7-3.6,6.5-5.5,10.3-6.8c-3.6-8.1-8.4-16.5-14.2-24.5c-14.9-20.5-33-33.8-46.1-33.8c-2.8,0-5.4,0.6-7.8,1.8
|
||||
c-21.9,11.1-21.4,26.6-20.9,43c0.2,7.4,0.4,14.3-1.6,20.6C90.3,200.4,85.9,206.2,81.2,212.4L81.2,212.4z"/>
|
||||
<path id="path4" class="st0" d="M464.1,203.8c-7.6-14.8-27-17.9-41.9-17.9c-9.4,0-19.3,1.2-29.2,3.3c1.6,2.6,3.8,5.4,6,8.2
|
||||
c10.5,13.6,24.9,32.3,9.8,62c-5.7,11.3-17.5,17.8-34.1,19.1c4,3,7.5,6.3,10.4,9.6c7.7,9,11,18.9,9.4,28.7
|
||||
c-5.2,32.5-27.7,39.4-44.1,44.4c-2.6,0.8-5.2,1.6-7.5,2.4c17.1,17.5,35,27.8,49.4,27.8c4.4,0,8.5-1,12.2-2.9
|
||||
c32.1-16.4,31.4-40,30.6-62.8c-0.3-10-0.6-19.5,2.1-27.8c2.9-9,8.9-17,15.3-25.5C466.7,253.5,480.3,235.5,464.1,203.8L464.1,203.8
|
||||
z"/>
|
||||
<path id="path6" class="st0" d="M270.4,394.7c2.9,0.5,5.6,0.7,8.2,0.7c18.2,0,25.9-11.3,34-23.2c4.1-6.1,8.1-11.8,13.4-15.7
|
||||
c5.8-4.2,12.8-6.3,20.2-8.6c15.7-4.8,30.6-9.3,34.4-33.2c0.9-5.6-1.2-11.5-6.3-17.4c-8.1-9.5-23.1-18-40-23.7
|
||||
c-1.9-0.5-3.7-1.1-5.6-1.7c-9.6-2.8-19.7-4.6-29.2-5c0.3,5,0.5,11.2-3.1,16.2c-3.8,5.2-10,6.8-14.9,8.1c-2.6,0.7-5.3,1.4-6.7,2.4
|
||||
c-1.3,0.9-2.8,3.3-4.2,5.5c-2.8,4.4-6.2,9.8-12.4,11.8c-1.5,0.5-3.1,0.7-4.8,0.7c-1.8,0-3.6-0.3-5.4-0.8
|
||||
c-3.4,17.1-3.5,37,0.6,54.3C251.2,375.3,257.2,392.6,270.4,394.7L270.4,394.7z"/>
|
||||
<path id="path8" class="st0" d="M126.4,366c-16.5-4.8-39.1-11.4-44.4-44.4c-1.5-9.7,1.7-19.6,9.4-28.7c2.3-2.6,4.9-5.2,7.9-7.7
|
||||
c-19.2-0.4-32.7-7.1-38.9-19.4c-15-29.4-0.8-48.1,9.6-61.9c1.5-1.9,2.9-3.8,4.2-5.7c-8.4-1.5-16.8-2.4-24.8-2.4
|
||||
c-15.1,0-34.6,3.1-42.2,18c-16.3,32.2-1.9,50.8,12.1,68.8c6.2,7.9,12,15.4,14.7,23.7c2.9,9,2.8,19,2.6,29.6
|
||||
c-0.4,23.9-0.8,46.4,30.9,62.5c3.7,1.9,7.7,2.8,12.1,2.8c15.8,0,35.7-12.3,54.2-33.1C131.6,367.5,129,366.8,126.4,366L126.4,366z"
|
||||
/>
|
||||
<path id="path10" class="st0" d="M276.2,62.2c12.8,0,24.2,5.2,35,16c9.1,9.1,11.6,22.9,7.4,39.6c9.6-6.5,19.2-10,27.9-10
|
||||
c5,0,9.8,1.1,14.1,3.3c29.4,15,28.9,38.5,28.6,55.7c0,2-0.1,4-0.1,5.9c13.7-6.9,25.3-15.1,32.9-23.9c7.6-8.9,10.8-17.9,9.4-26.6
|
||||
C425.6,86.6,403,80,381.1,73.7c-9.6-2.8-18.7-5.4-25.8-10.5c-7.7-5.6-13.4-13.8-19.5-22.4C324.3,24.3,312.4,7.3,286,7.3
|
||||
c-3.7,0-7.8,0.3-11.9,1C254,11.5,245,37,241.5,51.8c-1.5,6.2-2.6,12.9-3.3,19.9c3.3-0.7,7-2,10.9-3.4
|
||||
C257.1,65.4,266.1,62.2,276.2,62.2z"/>
|
||||
<path id="path12" class="st0" d="M80.3,180.7c0-2.3,0-4.7-0.1-7.3c-0.5-17.2-1.2-40.8,28.6-55.9c4.3-2.2,9.1-3.3,14.1-3.3
|
||||
c8.3,0,17.5,3.2,26.6,9.1c-6.3-19.2-4.4-35.1,5.7-45.2c10.7-10.7,22.1-15.9,34.9-15.9c9.9,0,18.9,3.1,26.9,5.9
|
||||
c1.4,0.5,2.8,1,4.2,1.4c-0.7-5-1.6-9.8-2.7-14.4c-3.6-14.9-12.6-40.2-32.7-43.4c-4.1-0.6-8.1-1-11.8-1
|
||||
c-26.9,0-38.6,17.2-49.9,33.7c-5.6,8.3-11,16.2-18,21.3c-7.7,5.6-17.2,8.5-27.4,11.6c-22.8,7-44.4,13.6-49.9,48.7
|
||||
c-1.4,8.7,1.8,17.6,9.4,26.5C47.4,163.4,62.6,173.1,80.3,180.7z"/>
|
||||
<path id="path14" class="st0" d="M328.2,374.4c-1.3,1.8-2.6,3.7-3.9,5.6c-8.4,12.4-20,29.3-45.6,29.3c-3.3,0-6.8-0.3-10.4-0.9
|
||||
c-12.7-2-22.8-11.6-29.1-27.5c-6.2,18.7-17,30-30.9,32.2c-3.6,0.6-7.1,0.9-10.3,0.9c-25.2,0-36.5-16.1-45.5-29.1
|
||||
c-1.6-2.2-3.1-4.4-4.6-6.4c-2.5,4.7-4.8,9.3-6.6,13.9c-5.8,14.1-13.4,40,0.9,54.3c11.9,11.8,23.6,17.3,36.9,17.3
|
||||
c11.2,0,21.9-3.9,32.2-7.6c9.4-3.4,18.4-6.6,27.1-6.6c9.5,0,19,3.2,29,6.7c10.4,3.6,21.1,7.2,32.1,7.2h0
|
||||
c13.4,0,25.1-5.5,36.9-17.4c14.3-14.4,6.6-40.1,0.8-54.2C334.6,386.4,331.6,380.4,328.2,374.4L328.2,374.4z"/>
|
||||
<path id="path16" class="st0" d="M190.1,76.3c-9,0-16.9,3.7-25,11.8c-9.5,9.5-4.2,27-0.2,36.7c7.7,18.6,21.7,36.5,36.3,48.6
|
||||
c2.4-3.3,5.4-6.5,9.8-7.9c1.5-0.5,3.1-0.7,4.8-0.7c4.2,0,8.2,1.6,11.8,2.9c2.6,1,5.3,2.1,7.1,2.1s4.5-1.1,7.1-2.1
|
||||
c3.5-1.4,7.5-2.9,11.8-2.9c1.7,0,3.3,0.2,4.8,0.7c3.7,1.2,6.4,3.7,8.6,6.4c14-12,27.1-29.3,34.5-47.1c4-9.6,9.3-27.2-0.2-36.7
|
||||
c-8.1-8.1-16.1-11.9-25.1-11.9c-7.6,0-15.1,2.7-22.3,5.3c-6.9,2.5-13.5,4.8-20,4.8c-7.1,0-14-2.4-21.4-4.9
|
||||
C205.1,78.9,197.6,76.3,190.1,76.3z"/>
|
||||
<path id="path18" class="st0" d="M396.3,253.1c11.1-21.9,1.7-34.1-8.4-47.1c-4.5-5.8-8.8-11.3-10.8-17.6
|
||||
c-2.2-6.8-2.1-14.1-1.9-21.9c0.3-16.4,0.6-32-21-43c-2.4-1.2-4.9-1.8-7.8-1.8c-13.1,0-31.2,13.3-46.1,33.8
|
||||
c-7.2,9.9-12.8,20.3-16.5,30.2c4.5,1.2,9.5,3.1,12.7,7.5c3.7,5.1,3.4,11.5,3.1,16.6c-0.2,2.7-0.3,5.6,0.2,7.2
|
||||
c0.5,1.4,2.3,3.6,3.9,5.6c3.3,4,7.5,9,7.5,15.6c0,3.6-1.2,6.7-2.9,9.5c7,4,14.8,7.6,22.9,10.4c3,0.8,6,1.8,8.9,2.8
|
||||
c9.4,2.6,19,4.1,28,4.1C378.1,264.9,391.3,262.8,396.3,253.1L396.3,253.1z"/>
|
||||
<path id="path20" class="st0" d="M95.9,319.4c3.8,24.2,18.7,28.6,34.5,33.2c7.1,2.1,13.7,4,19.1,7.9c5.8,4.2,10,10.2,14.4,16.5
|
||||
c8.3,11.9,16.2,23.1,34.1,23.1c2.6,0,5.3-0.2,8.2-0.7c13.2-2.1,19.3-19.4,21.7-29.6c4.7-19.6,3.9-42.5-0.9-60.9
|
||||
c-3.4,1.3-7.1,2.7-11.1,2.7c-1.7,0-3.3-0.2-4.8-0.7c-6.2-2-9.6-7.4-12.4-11.8c-1.4-2.3-2.9-4.6-4.2-5.5c-1.3-1-4-1.7-6.7-2.4
|
||||
c-5-1.3-11.2-2.9-14.9-8.1c-2.4-3.3-3.1-7.2-3.2-10.9c-26.6,3-55,15.2-67.4,29.8C97.1,307.9,95,313.7,95.9,319.4L95.9,319.4z"/>
|
||||
<path id="path22" class="st0" d="M246.8,295.6c2.5,1,5.1,2,6.7,2c0.2,0,0.4,0,0.5-0.1c1.4-0.4,3.4-3.7,4.9-6
|
||||
c2-3.2,4.4-6.8,7.8-9.3c3.5-2.5,7.7-3.6,11.4-4.6c2.7-0.7,6.3-1.6,7.1-2.8c0.8-1.1,0.6-4.8,0.4-7.5c-0.2-3.8-0.5-8.2,0.9-12.3
|
||||
c1.3-4,4-7.3,6.4-10.2c1.9-2.3,4.2-5.1,4.2-6.7c0-1.5-2.4-4.4-4.2-6.7c-2.4-2.9-5.1-6.2-6.4-10.2c-1.3-4.1-1.1-8.5-0.9-12.3
|
||||
c0.2-2.7,0.4-6.5-0.4-7.5c-0.8-1.1-4.5-2.1-7.1-2.8c-3.7-1-7.9-2.1-11.4-4.6c-3.4-2.5-5.7-6.1-7.8-9.3c-1.5-2.3-3.5-5.6-4.9-6
|
||||
c-0.1,0-0.3-0.1-0.5-0.1c-1.6,0-4.2,1-6.7,2c-3.6,1.4-7.7,3-12.2,3s-8.5-1.6-12.2-3c-2.5-1-5.1-2-6.7-2c-0.2,0-0.4,0-0.5,0.1
|
||||
c-1.4,0.4-3.4,3.7-4.9,6c-2,3.2-4.4,6.9-7.8,9.3c-3.5,2.5-7.7,3.6-11.4,4.6c-2.7,0.7-6.3,1.6-7.1,2.8c-0.8,1.1-0.6,4.8-0.4,7.5
|
||||
c0.2,3.8,0.5,8.2-0.9,12.3c-1.3,4-4,7.3-6.4,10.2c-1.9,2.3-4.2,5.1-4.2,6.7c0,1.5,2.4,4.4,4.2,6.7c2.4,2.9,5.1,6.2,6.4,10.2
|
||||
c1.3,4.1,1.1,8.5,0.9,12.3c-0.2,2.7-0.4,6.5,0.4,7.5c0.8,1.1,4.5,2.1,7.1,2.8c3.7,1,7.9,2.1,11.4,4.6c3.4,2.5,5.7,6.1,7.8,9.3
|
||||
c1.5,2.3,3.5,5.6,4.9,6c0.1,0,0.3,0.1,0.5,0.1c1.6,0,4.2-1,6.7-2c3.6-1.4,7.7-3,12.2-3S243.2,294.2,246.8,295.6L246.8,295.6z"/>
|
||||
</g>
|
||||
</g>
|
||||
<g
|
||||
id="g18">
|
||||
<g id="g16">
|
||||
</g>
|
||||
<g
|
||||
id="g20">
|
||||
<g id="g18">
|
||||
</g>
|
||||
<g
|
||||
id="g22">
|
||||
<g id="g20">
|
||||
</g>
|
||||
<g
|
||||
id="g24">
|
||||
<g id="g22">
|
||||
</g>
|
||||
<g
|
||||
id="g26">
|
||||
<g id="g24">
|
||||
</g>
|
||||
<g
|
||||
id="g28">
|
||||
<g id="g26">
|
||||
</g>
|
||||
<g
|
||||
id="g30">
|
||||
<g id="g28">
|
||||
</g>
|
||||
<g
|
||||
id="g32">
|
||||
<g id="g30">
|
||||
</g>
|
||||
<g
|
||||
id="g34">
|
||||
<g id="g32">
|
||||
</g>
|
||||
<g
|
||||
id="g36">
|
||||
<g id="g34">
|
||||
</g>
|
||||
<g
|
||||
id="g38">
|
||||
<g id="g36">
|
||||
</g>
|
||||
<g
|
||||
id="g40">
|
||||
<g id="g38">
|
||||
</g>
|
||||
<g
|
||||
id="g42">
|
||||
<g id="g40">
|
||||
</g>
|
||||
<g
|
||||
id="g44">
|
||||
<g id="g42">
|
||||
</g>
|
||||
<g id="g44">
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 7.8 KiB |
BIN
icons/tmr/gift.webp
Normal file
After Width: | Height: | Size: 44 KiB |
BIN
icons/tmr/pelerin.webp
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
icons/tmr/scroll.webp
Normal file
After Width: | Height: | Size: 45 KiB |
BIN
icons/tmr/signe_draconique.webp
Normal file
After Width: | Height: | Size: 35 KiB |
BIN
icons/tmr/treasure-chest.webp
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
icons/tmr/wave.webp
Normal file
After Width: | Height: | Size: 13 KiB |
@ -35,12 +35,10 @@ export class RdDActorCreatureSheet extends RdDActorSheet {
|
||||
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
|
||||
}
|
||||
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.buildArbreDeConteneur(this, formData);
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||
|
||||
console.log("Creature : ", this.objetVersConteneur, formData);
|
||||
|
||||
@ -72,17 +70,6 @@ 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 */
|
||||
_updateObject(event, formData) {
|
||||
|
@ -5,6 +5,7 @@
|
||||
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDActorEntiteSheet extends ActorSheet {
|
||||
@ -31,14 +32,27 @@ export class RdDActorEntiteSheet extends ActorSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
let formData = super.getData();
|
||||
|
||||
formData.itemsByType = Misc.classify(formData.items);
|
||||
const objectData = Misc.data(this.object);
|
||||
let formData = {
|
||||
title: this.title,
|
||||
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.data.carac.taille.isTaille = true; // To avoid button link;
|
||||
formData.data.competencecreature = formData.itemsByType["competencecreature"];
|
||||
RdDUtility.filterItemsPerTypeForSheet(formData);
|
||||
|
||||
|
||||
return formData;
|
||||
@ -57,14 +71,14 @@ export class RdDActorEntiteSheet extends ActorSheet {
|
||||
// Update Inventory Item
|
||||
html.find('.item-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
const item = this.actor.getEmbeddedDocument('Item', li.data("itemId"));
|
||||
item.sheet.render(true);
|
||||
});
|
||||
|
||||
// Delete Inventory Item
|
||||
html.find('.item-delete').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
this.actor.deleteOwnedItem(li.data("itemId"));
|
||||
this.actor.deleteEmbeddedDocuments('Item', [li.data("itemId")]);
|
||||
li.slideUp(200, () => this.render(false));
|
||||
});
|
||||
|
||||
@ -103,7 +117,7 @@ export class RdDActorEntiteSheet extends ActorSheet {
|
||||
this.render(true);
|
||||
});
|
||||
|
||||
html.find('#encaisser-direct').click(ev => {
|
||||
html.find('.encaisser-direct').click(ev => {
|
||||
this.actor.encaisser();
|
||||
});
|
||||
|
||||
@ -118,10 +132,12 @@ export class RdDActorEntiteSheet extends ActorSheet {
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
setPosition(options={}) {
|
||||
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 bodyHeight = position.height - 192;
|
||||
const bodyHeight = position.height - sheetHeader[0].clientHeight - sheetTabs[0].clientHeight;
|
||||
sheetBody.css("height", bodyHeight);
|
||||
return position;
|
||||
}
|
||||
|
@ -11,6 +11,9 @@ import { RdDBonus } from "./rdd-bonus.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDCombatManager } from "./rdd-combat.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 {
|
||||
@ -33,54 +36,45 @@ export class RdDActorSheet extends ActorSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
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;
|
||||
const objectData = Misc.data(this.object);
|
||||
let formData = {
|
||||
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))),
|
||||
};
|
||||
|
||||
// // Owned items
|
||||
// formData.items = formData.actor.items;
|
||||
// formData.items.sort((a, b) => (a.sort || 0) - (b.sort || 0));
|
||||
|
||||
formData.itemsByType = Misc.classify(formData.items);
|
||||
RdDUtility.filterItemsPerTypeForSheet(formData);
|
||||
|
||||
formData.options.isGM = game.user.isGM;
|
||||
|
||||
// la taille est la taille: on ne peut pas l'utiliser pour un jet
|
||||
formData.data.carac.taille.isTaille = true;
|
||||
if (formData.type == 'creature') return formData; // Shortcut
|
||||
|
||||
if (this.actor.data.type == 'creature') return formData; // Shortcut
|
||||
|
||||
formData.competenceByCategory = Misc.classify(formData.data.competences, it => it.data.categorie);
|
||||
formData.competenceByCategory = Misc.classify(formData.competences, it => it.data.categorie);
|
||||
|
||||
formData.calc = {
|
||||
comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.data.competences),
|
||||
competenceXPTotal: RdDItemCompetence.computeTotalXP(formData.data.competences),
|
||||
comptageArchetype: RdDItemCompetence.computeResumeArchetype(formData.competences),
|
||||
competenceXPTotal: RdDItemCompetence.computeTotalXP(formData.competences),
|
||||
caracTotal: RdDCarac.computeTotal(formData.data.carac, formData.data.beaute),
|
||||
// Mise à jour de l'encombrement total et du prix de l'équipement
|
||||
encTotal: await this.actor.computeEncombrementTotalEtMalusArmure(),
|
||||
prixTotalEquipement: await this.actor.computePrixTotalEquipement(),
|
||||
prixTotalEquipement: this.actor.computePrixTotalEquipement(),
|
||||
surprise: RdDBonus.find(this.actor.getSurprise(false)).descr,
|
||||
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>"
|
||||
},
|
||||
fatigue: RdDUtility.calculFatigueHtml(formData.data.sante.fatigue.value, formData.data.sante.endurance.max),
|
||||
resumeBlessures: this.actor.computeResumeBlessure(formData.data.blessures),
|
||||
};
|
||||
formData.calc.surEncombrementMessage = (formData.data.compteurs.surenc.value < 0) ? "Sur-Encombrement!" : "";
|
||||
|
||||
formData.data.competences.forEach(item => {
|
||||
formData.competences.forEach(item => {
|
||||
item.visible = !this.options.showCompNiveauBase || !RdDItemCompetence.isNiveauBase(item);
|
||||
RdDItemCompetence.levelUp(item);
|
||||
});
|
||||
@ -91,41 +85,37 @@ export class RdDActorSheet extends ActorSheet {
|
||||
|
||||
|
||||
// toujours avoir une liste d'armes (pour mettre esquive et corps à corps)
|
||||
formData.data.combat = duplicate(formData.itemsByType.arme ?? []);
|
||||
RdDItemArme.computeNiveauArmes(formData.data.combat, formData.data.competences);
|
||||
RdDItemArme.ajoutCorpsACorps(formData.data.combat, formData.data.competences, formData.data.carac );
|
||||
formData.esquive = RdDItemCompetence.getEsquive(formData.data.competences);
|
||||
formData.data.combat = RdDCombatManager.finalizeArmeList(formData.data.combat, formData.itemsByType.competence, formData.data.carac);
|
||||
formData.combat = duplicate(formData.armes ?? []);
|
||||
RdDItemArme.computeNiveauArmes(formData.combat, formData.competences);
|
||||
RdDItemArme.ajoutCorpsACorps(formData.combat, formData.competences, formData.data.carac);
|
||||
formData.esquive = RdDItemCompetence.getEsquive(formData.competences);
|
||||
formData.combat = RdDCombatManager.finalizeArmeList(formData.combat, formData.competences, formData.data.carac);
|
||||
|
||||
|
||||
this.armesList = formData.data.combat;
|
||||
|
||||
// Mise à jour de l'encombrement total et du prix de l'équipement
|
||||
this.armesList = formData.combat;
|
||||
|
||||
// Common data
|
||||
formData.data.competenceByCategory = formData.competenceByCategory;
|
||||
formData.data.isGM = game.user.isGM;
|
||||
formData.ajustementsConditions = CONFIG.RDD.ajustementsConditions;
|
||||
formData.difficultesLibres = CONFIG.RDD.difficultesLibres;
|
||||
|
||||
// low is normal, this the base used to compute the grid.
|
||||
formData.data.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>"
|
||||
}
|
||||
|
||||
formData.hautreve = {
|
||||
sortsReserve: formData.data.reve.reserve.list,
|
||||
rencontres: duplicate(formData.data.reve.rencontre.list),
|
||||
casesTmr: formData.itemsByType.casetmr
|
||||
casesTmr: formData.itemsByType.casetmr,
|
||||
cacheTMR: this.actor.isTMRCache()
|
||||
}
|
||||
|
||||
RdDUtility.buildArbreDeConteneur(this, formData);
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||
|
||||
formData.subacteurs = {
|
||||
vehicules: this.actor.listeVehicules(),
|
||||
montures: this.actor.listeMontures(),
|
||||
suivants: this.actor.listeSuivants()
|
||||
}
|
||||
if (this.actor.getBestDraconic().data.niveau > -11 && !this.actor.isHautRevant()) {
|
||||
ui.notifications.error(`${this.actor.name} a des compétences draconiques, mais pas le don de Haut-Rêve!
|
||||
<br>Ajoutez-lui la tête "Don de Haut-Rêve" pour lui permettre d'utiliser ses compétences et d'accéder aux terres médianes du rêve`);
|
||||
}
|
||||
return formData;
|
||||
}
|
||||
|
||||
@ -134,30 +124,42 @@ export class RdDActorSheet extends ActorSheet {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _onDrop(event) {
|
||||
let toSuper = await RdDUtility.processItemDropEvent(this, event);
|
||||
if (toSuper) {
|
||||
super._onDrop(event);
|
||||
async _onDropActor(event, dragData) {
|
||||
console.log("DRAG", this.actor.id, dragData);
|
||||
this.actor.addSubacteur(dragData.id || dragData.data._id);
|
||||
super._onDropActor(event, dragData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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() {
|
||||
await this.actor.createOwnedItem({ name: 'Nouvelle tache', type: 'tache' }, { renderSheet: true });
|
||||
await this.createItem('Nouvelle tache', 'tache');
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async creerObjet() {
|
||||
let itemType = $("#creer-equipement").val();
|
||||
await this.actor.createOwnedItem({ name: 'Nouveau ' + itemType, type: itemType }, { renderSheet: true });
|
||||
let itemType = $(".item-type").val();
|
||||
await this.createItem('Nouveau ' + itemType, itemType);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async selectObjetType() {
|
||||
let itemType = ["objet", "arme", "armure", "conteneur", "herbe", "ingredient", "livre", "potion", "munition", "monnaie"];
|
||||
let options = '<span class="competence-label">Selectionnez le type d\'équipement</span><select id="creer-equipement">';
|
||||
for (let typeName of itemType) {
|
||||
options += '<option value="' + typeName + '">' + typeName + '</option>'
|
||||
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({
|
||||
@ -174,12 +176,34 @@ export class RdDActorSheet extends ActorSheet {
|
||||
d.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async selectTypeOeuvre() {
|
||||
let typeOeuvres = RdDItem.getTypesOeuvres();
|
||||
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) {
|
||||
super.activateListeners(html);
|
||||
|
||||
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;
|
||||
@ -189,29 +213,48 @@ export class RdDActorSheet extends ActorSheet {
|
||||
// Everything below here is only needed if the sheet is editable
|
||||
if (!this.options.editable) return;
|
||||
|
||||
html.find('.item-split').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.items.get(li.data("item-id"));
|
||||
this.splitItem(item);
|
||||
});
|
||||
html.find('.item-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("item-id"));
|
||||
const item = this.actor.items.get(li.data("item-id"));
|
||||
item.sheet.render(true);
|
||||
});
|
||||
html.find('.display-label a').click((event) => {
|
||||
let myID = event.currentTarget.attributes['data-item-id'].value;
|
||||
const item = this.actor.getEmbeddedDocument('Item', myID);
|
||||
item.sheet.render(true);
|
||||
});
|
||||
// Update Inventory Item
|
||||
html.find('.rencontre-delete').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const rencontreKey = li.data("item-id");
|
||||
this.actor.deleteTMRRencontre(rencontreKey);
|
||||
});
|
||||
|
||||
// Delete Inventory Item
|
||||
html.find('.item-delete').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
RdDUtility.confirmerSuppression(this, li);
|
||||
});
|
||||
html.find('.item-vendre').click(ev => {
|
||||
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(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const itemId = li.data("item-id");
|
||||
const item = this.actor.getObjet(itemId);
|
||||
this.actor.actionItem(item);
|
||||
});
|
||||
html.find('.subacteur-delete').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
RdDUtility.confirmerSuppressionSubacteur(this, li);
|
||||
});
|
||||
|
||||
html.find('#encaisser-direct').click(ev => {
|
||||
html.find('.encaisser-direct').click(ev => {
|
||||
this.actor.encaisser();
|
||||
});
|
||||
|
||||
@ -221,12 +264,15 @@ export class RdDActorSheet extends ActorSheet {
|
||||
ev.preventDefault();
|
||||
}
|
||||
});
|
||||
html.find('#creer-tache').click(ev => {
|
||||
html.find('.creer-tache').click(ev => {
|
||||
this.createEmptyTache();
|
||||
});
|
||||
html.find('#creer-un-objet').click(ev => {
|
||||
html.find('.creer-un-objet').click(ev => {
|
||||
this.selectObjetType();
|
||||
});
|
||||
html.find('.creer-une-oeuvre').click(ev => {
|
||||
this.selectTypeOeuvre();
|
||||
});
|
||||
html.find('#nettoyer-conteneurs').click(ev => {
|
||||
this.actor.nettoyerConteneurs();
|
||||
});
|
||||
@ -280,8 +326,8 @@ export class RdDActorSheet extends ActorSheet {
|
||||
});
|
||||
|
||||
// Roll Skill
|
||||
html.find('.competence-label a').click((event) => {
|
||||
let compName = event.currentTarget.text;
|
||||
html.find('a.competence-label').click((event) => {
|
||||
let compName = event.currentTarget.name;
|
||||
this.actor.rollCompetence(compName);
|
||||
});
|
||||
html.find('.tache-label a').click((event) => {
|
||||
@ -333,6 +379,14 @@ export class RdDActorSheet extends ActorSheet {
|
||||
}
|
||||
});
|
||||
|
||||
// Boutons spéciaux MJs
|
||||
html.find('.forcer-tmr-aleatoire').click((event) => {
|
||||
this.actor.cacheTMRetMessage();
|
||||
});
|
||||
html.find('.afficher-tmr').click((event) => {
|
||||
this.actor.afficheTMRetMessage();
|
||||
});
|
||||
|
||||
// Points de reve actuel
|
||||
html.find('.ptreve-actuel a').click((event) => {
|
||||
this.actor.rollCarac('reve-actuel');
|
||||
@ -356,49 +410,29 @@ export class RdDActorSheet extends ActorSheet {
|
||||
}
|
||||
});
|
||||
// Display TMR, visuualisation
|
||||
html.find('#visu-tmr').click((event) => {
|
||||
html.find('.visu-tmr').click((event) => {
|
||||
this.actor.displayTMR("visu");
|
||||
});
|
||||
|
||||
// Display TMR, normal
|
||||
html.find('#monte-tmr').click((event) => {
|
||||
html.find('.monte-tmr').click((event) => {
|
||||
this.actor.displayTMR("normal");
|
||||
});
|
||||
|
||||
// Display TMR, fast
|
||||
html.find('#monte-tmr-rapide').click((event) => {
|
||||
html.find('.monte-tmr-rapide').click((event) => {
|
||||
this.actor.displayTMR("rapide");
|
||||
});
|
||||
|
||||
html.find('#dormir-une-heure').click((event) => {
|
||||
html.find('.dormir-une-heure').click((event) => {
|
||||
this.actor.dormir(1);
|
||||
});
|
||||
html.find('#dormir-chateau-dormant').click((event) => {
|
||||
html.find('.dormir-chateau-dormant').click((event) => {
|
||||
this.actor.dormirChateauDormant();
|
||||
});
|
||||
html.find('#enlever-tous-effets').click((event) => {
|
||||
html.find('.enlever-tous-effets').click((event) => {
|
||||
this.actor.enleverTousLesEffets();
|
||||
});
|
||||
// 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;
|
||||
RdDUtility.toggleAfficheContenu(myID);
|
||||
@ -492,7 +526,7 @@ export class RdDActorSheet extends ActorSheet {
|
||||
this.render(true);
|
||||
});
|
||||
html.find('#ethylisme-test').click((event) => {
|
||||
this.actor.ethylismeTest();
|
||||
this.actor.jetEthylisme();
|
||||
this.render(true);
|
||||
});
|
||||
|
||||
@ -559,8 +593,10 @@ export class RdDActorSheet extends ActorSheet {
|
||||
/** @override */
|
||||
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 bodyHeight = position.height - 192;
|
||||
const bodyHeight = position.height - sheetHeader[0].clientHeight - sheetTabs[0].clientHeight;
|
||||
sheetBody.css("height", bodyHeight);
|
||||
return position;
|
||||
}
|
||||
@ -572,4 +608,19 @@ export class RdDActorSheet extends ActorSheet {
|
||||
// Update the Actor
|
||||
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])
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -34,12 +34,26 @@ export class RdDActorVehiculeSheet extends ActorSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
let formData = super.getData();
|
||||
|
||||
formData.itemsByType = Misc.classify(formData.items);
|
||||
const objectData = Misc.data(this.object);
|
||||
let formData = {
|
||||
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))),
|
||||
};
|
||||
|
||||
RdDUtility.filterItemsPerTypeForSheet(formData);
|
||||
RdDUtility.buildArbreDeConteneur(this, formData);
|
||||
this.objetVersConteneur = RdDUtility.buildArbreDeConteneurs(formData.conteneurs, formData.objets);
|
||||
formData.conteneurs = RdDUtility.conteneursRacine(formData.conteneurs);
|
||||
|
||||
formData.options.isGM = game.user.isGM;
|
||||
|
||||
@ -54,10 +68,10 @@ export class RdDActorVehiculeSheet extends ActorSheet {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _onDrop(event) {
|
||||
let toSuper = await RdDUtility.processItemDropEvent(this, event);
|
||||
if ( toSuper) {
|
||||
super._onDrop(event);
|
||||
async _onDropItem(event, dragData) {
|
||||
const callSuper = await this.actor.processDropItem(event, dragData, this.objetVersConteneur);
|
||||
if (callSuper) {
|
||||
await super._onDropItem(event, dragData)
|
||||
}
|
||||
}
|
||||
|
||||
@ -74,7 +88,7 @@ export class RdDActorVehiculeSheet extends ActorSheet {
|
||||
// Update Inventory Item
|
||||
html.find('.item-edit').click(ev => {
|
||||
const li = $(ev.currentTarget).parents(".item");
|
||||
const item = this.actor.getOwnedItem(li.data("itemId"));
|
||||
const item = this.actor.getEmbeddedDocument('Item', li.data("itemId"));
|
||||
item.sheet.render(true);
|
||||
});
|
||||
// Delete Inventory Item
|
||||
@ -94,10 +108,12 @@ export class RdDActorVehiculeSheet extends ActorSheet {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
setPosition(options={}) {
|
||||
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 bodyHeight = position.height - 192;
|
||||
const bodyHeight = position.height - sheetHeader[0].clientHeight - sheetTabs[0].clientHeight;
|
||||
sheetBody.css("height", bodyHeight);
|
||||
return position;
|
||||
}
|
||||
|
2229
module/actor.js
@ -1,3 +1,4 @@
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
/**
|
||||
* Class providing helper methods to get the list of users, and
|
||||
@ -7,31 +8,45 @@ export class ChatUtility {
|
||||
/* -------------------------------------------- */
|
||||
static onSocketMessage(sockmsg) {
|
||||
switch (sockmsg.msg) {
|
||||
case "msg_delete_chat_message": return ChatUtility.onRemoveMessages(sockmsg.part, sockmsg.gmId);
|
||||
case "msg_delete_chat_message": return ChatUtility.onRemoveMessages(sockmsg.data);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onRemoveMessages(part, gmId) {
|
||||
if (game.user._id == gmId) {
|
||||
const toDelete = game.messages.filter(it => it.data.content.includes(part));
|
||||
toDelete.forEach(it => it.delete());
|
||||
static onRemoveMessages(data) {
|
||||
if (game.user.isGM || game.user.id == data.gmId) {
|
||||
if (data.part){
|
||||
const toDelete = game.messages.filter(it => it.data.content.includes(data.part));
|
||||
toDelete.forEach(it => it.delete());
|
||||
}
|
||||
if (data.messageId){
|
||||
game.messages.get(data.messageId)?.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static removeChatMessageContaining(part) {
|
||||
const gmId = game.user.isGM ? game.user._id : game.users.entities.find(u => u.isGM && u.active)?.id;
|
||||
const removeMessageData = {
|
||||
part: part,
|
||||
gmId: Misc.connectedGMOrUser()
|
||||
};
|
||||
|
||||
if (!gmId || game.user.isGM) {
|
||||
ChatUtility.onRemoveMessages(part, game.user._id);
|
||||
if (game.user.isGM) {
|
||||
ChatUtility.onRemoveMessages(removeMessageData);
|
||||
}
|
||||
else {
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", {
|
||||
msg: "msg_delete_chat_message", data: {
|
||||
part:part,
|
||||
gmId: gmId,
|
||||
}});
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_delete_chat_message", data: removeMessageData });
|
||||
}
|
||||
}
|
||||
|
||||
static removeChatMessageId(messageId) {
|
||||
const removeMessageData = { messageId: messageId, gmId: Misc.connectedGMOrUser() };
|
||||
if (game.user.isGM) {
|
||||
ChatUtility.onRemoveMessages(removeMessageData);
|
||||
}
|
||||
else {
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", { msg: "msg_delete_chat_message", data: removeMessageData });
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +62,7 @@ export class ChatUtility {
|
||||
if (!game.user.isGM) {
|
||||
ChatUtility.blindMessageToGM(chatOptions);
|
||||
|
||||
chatOptions.whisper = [game.user._id];
|
||||
chatOptions.whisper = [game.user.id];
|
||||
chatOptions.content = "Message envoyé en aveugle au Gardien";
|
||||
}
|
||||
else {
|
||||
@ -65,7 +80,7 @@ export class ChatUtility {
|
||||
/* -------------------------------------------- */
|
||||
static prepareChatMessage(rollMode, name) {
|
||||
return {
|
||||
user: game.user._id,
|
||||
user: game.user.id,
|
||||
whisper: ChatUtility.getWhisperRecipients(rollMode, name)
|
||||
}
|
||||
}
|
||||
@ -75,7 +90,7 @@ export class ChatUtility {
|
||||
switch (rollMode) {
|
||||
case "blindroll": return ChatUtility.getUsers(user => user.isGM);
|
||||
case "gmroll": return ChatUtility.getWhisperRecipientsAndGMs(name);
|
||||
case "selfroll": return [game.user._id];
|
||||
case "selfroll": return [game.user.id];
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -104,7 +119,7 @@ export class ChatUtility {
|
||||
static handleGMChatMessage(data) {
|
||||
console.log("blindMessageToGM", data);
|
||||
if (game.user.isGM) { // message privé pour GM only
|
||||
data.user = game.user._id;
|
||||
data.user = game.user.id;
|
||||
ChatMessage.create(data);
|
||||
}
|
||||
}
|
||||
|
1
module/constants.js
Normal file
@ -0,0 +1 @@
|
||||
export const SYSTEM_RDD = "foundryvtt-reve-de-dragon";
|
@ -1,27 +0,0 @@
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
|
||||
export class DeDraconique extends Roll{
|
||||
|
||||
static async ddr(rollMode=undefined) {
|
||||
let ddr = new DeDraconique().evaluate();
|
||||
await RdDDice.show(ddr, rollMode);
|
||||
return ddr;
|
||||
}
|
||||
|
||||
constructor(){
|
||||
super("1d8x8 - 0")
|
||||
}
|
||||
|
||||
evaluate() {
|
||||
super.evaluate();
|
||||
const rerolls = Math.ceil(this.total / 8);
|
||||
this.terms[this.terms.length - 1] = rerolls;
|
||||
this.results[this.results.length - 1] = rerolls;
|
||||
this._total -= rerolls;
|
||||
return this;
|
||||
}
|
||||
|
||||
async render(chatOptions) {
|
||||
return super.render(chatOptions)
|
||||
}
|
||||
}
|
82
module/dialog-consommer.js
Normal file
@ -0,0 +1,82 @@
|
||||
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/consommer/dialog-${Misc.data(item).type}.html`, consommerData);
|
||||
return new DialogConsommer(actor, item, consommerData, html, options)
|
||||
}
|
||||
|
||||
constructor(actor, item, consommerData, html, options = {}) {
|
||||
mergeObject(options, { classes: ["dialogconsommer"], width: 600, height: 500, 'z-index': 99999 }, { overwrite: false })
|
||||
|
||||
let conf = {
|
||||
title: consommerData.title,
|
||||
content: html,
|
||||
default: consommerData.buttonName,
|
||||
buttons: {
|
||||
[consommerData.buttonName]: {
|
||||
label: consommerData.buttonName, callback: it => {
|
||||
this.actor.consommer(this.item, this.consommerData.choix);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
super(conf, options);
|
||||
|
||||
this.actor = actor;
|
||||
this.item = item;
|
||||
this.consommerData = consommerData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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.consommerData.choix.seForcer = event.currentTarget.checked;
|
||||
});
|
||||
html.find(".consommer-doses").change(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)
|
||||
});
|
||||
}
|
||||
|
||||
}
|
116
module/dialog-create-signedraconique.js
Normal file
@ -0,0 +1,116 @@
|
||||
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();
|
||||
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() {
|
||||
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();
|
||||
|
||||
$("[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);
|
||||
}
|
||||
|
||||
}
|
64
module/dialog-fabriquer-potion.js
Normal file
@ -0,0 +1,64 @@
|
||||
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 = potionData.data.quantite;
|
||||
potionData.buttonName = "Fabriquer";
|
||||
return potionData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(actor, potionData, conf, options) {
|
||||
conf.buttons = {
|
||||
[potionData.buttonName]: {
|
||||
label: potionData.buttonName, callback: it => {
|
||||
this.fabriquer();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
super(conf, options);
|
||||
|
||||
this.actor = actor;
|
||||
this.potionData = potionData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
|
||||
html.find("#nbBrins").change(event => {
|
||||
this.potionData.nbBrins = Misc.toInt(event.currentTarget.value);
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async fabriquer() {
|
||||
this.actor.fabriquerPotion( this.potionData );
|
||||
this.close();
|
||||
}
|
||||
}
|
87
module/dialog-item-achat.js
Normal file
@ -0,0 +1,87 @@
|
||||
import { RdDActor } from "./actor.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
export class DialogItemAchat extends Dialog {
|
||||
|
||||
static async onButtonAcheter(event) {
|
||||
let jsondata = event.currentTarget.attributes['data-jsondata']?.value;
|
||||
if (!jsondata) {
|
||||
ui.notifications.warn("Impossible d'acheter: informations sur l'objet manquantes")
|
||||
return;
|
||||
}
|
||||
const vendeurId = event.currentTarget.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;
|
||||
}
|
||||
|
||||
const chatMessageIdVente = RdDUtility.findChatMessageId(event.currentTarget);
|
||||
const itemData = JSON.parse(jsondata);
|
||||
const prixLot = event.currentTarget.attributes['data-prixLot']?.value ?? 0;
|
||||
let venteData = {
|
||||
item: itemData,
|
||||
vendeurId: vendeurId,
|
||||
vendeur: Misc.data(vendeur),
|
||||
acheteur: Misc.data(acheteur),
|
||||
tailleLot: event.currentTarget.attributes['data-tailleLot']?.value ?? 1,
|
||||
quantiteNbLots: event.currentTarget.attributes['data-quantiteNbLots']?.value,
|
||||
nombreLots: 1,
|
||||
prixLot: prixLot,
|
||||
prixTotal: prixLot,
|
||||
isVente: prixLot > 0
|
||||
};
|
||||
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;
|
||||
}
|
||||
|
||||
async onAchat() {
|
||||
(this.vendeur ?? this.acheteur).achatVente(
|
||||
this.vendeur?.id,
|
||||
this.acheteur?.id,
|
||||
this.venteData,
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
90
module/dialog-item-vente.js
Normal file
@ -0,0 +1,90 @@
|
||||
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(); } } }
|
||||
};
|
||||
|
||||
super(conf, options);
|
||||
this.callback = callback;
|
||||
this.venteData = venteData;
|
||||
}
|
||||
|
||||
async onProposer() {
|
||||
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)
|
||||
}
|
||||
}
|
51
module/dialog-split-item.js
Normal file
@ -0,0 +1,51 @@
|
||||
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(){
|
||||
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);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@ -3,7 +3,7 @@ import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// Activate chat listeners defined
|
||||
Hooks.on('renderChatLog', (log, html, data) => {
|
||||
RdDUtility.chatListeners(html);
|
||||
});
|
||||
// Hooks.on('renderChatLog', (log, html, data) => {
|
||||
// RdDUtility.chatListeners(html);
|
||||
// });
|
||||
|
||||
|
@ -1,8 +1,11 @@
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
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"]];
|
||||
|
||||
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 competence_niveau_max = competence_xp_par_niveau.length - 10;
|
||||
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 niveau_max = xp_par_niveau.length - 10;
|
||||
/* -------------------------------------------- */
|
||||
const limitesArchetypes = [
|
||||
{ "niveau": 0, "nombreMax": 100, "nombre": 0 },
|
||||
@ -21,14 +24,14 @@ const limitesArchetypes = [
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const categorieCompetences = {
|
||||
"generale": { level: "-4", label: "Générales" },
|
||||
"particuliere": { level: "-8", label: "Particulières" },
|
||||
"specialisee": { level: "-11", label: "Spécialisées" },
|
||||
"connaissance": { level: "-11", label: "Connaissances" },
|
||||
"draconic": { level: "-11", label: "Draconics" },
|
||||
"melee": { level: "-6", label: "Mêlée" },
|
||||
"tir": { level: "-8", label: "Tir" },
|
||||
"lancer": { level: "-8", label: "Lancer" }
|
||||
"generale": { base: -4, label: "Générales" },
|
||||
"particuliere": { base: -8, label: "Particulières" },
|
||||
"specialisee": { base: -11, label: "Spécialisées" },
|
||||
"connaissance": { base: -11, label: "Connaissances" },
|
||||
"draconic": { base: -11, label: "Draconics" },
|
||||
"melee": { base: -6, label: "Mêlée" },
|
||||
"tir": { base: -8, label: "Tir" },
|
||||
"lancer": { base: -8, label: "Lancer" }
|
||||
}
|
||||
|
||||
const compendiumCompetences = {
|
||||
@ -41,9 +44,9 @@ const compendiumCompetences = {
|
||||
function _buildCumulXP() {
|
||||
let cumulXP = { "-11": 0 };
|
||||
let cumul = 0;
|
||||
for (let i = 0; i <= competence_xp_par_niveau.length; i++) {
|
||||
for (let i = 0; i <= xp_par_niveau.length; i++) {
|
||||
let level = i - 10;
|
||||
cumul += competence_xp_par_niveau[i];
|
||||
cumul += xp_par_niveau[i];
|
||||
cumulXP[level] = cumul;
|
||||
}
|
||||
return cumulXP;
|
||||
@ -53,29 +56,48 @@ const competence_xp_cumul = _buildCumulXP();
|
||||
|
||||
export class RdDItemCompetence extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static actorCompendium(actorType) {
|
||||
return compendiumCompetences[actorType];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getCategorieCompetences() {
|
||||
return categorieCompetences;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getNiveauBase(category) {
|
||||
return categorieCompetences[category].level;
|
||||
return categorieCompetences[category].base;
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getLabelCategorie(category) {
|
||||
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) {
|
||||
return { name: 'Esquive', niveau: RdDItemCompetence.findCompetence(competences, 'Esquive')?.data.niveau ?? -6 };
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isCompetenceArme(competence) {
|
||||
switch (competence.data.categorie) {
|
||||
switch (Misc.templateData(competence).categorie) {
|
||||
case 'melee':
|
||||
return competence.name != 'Esquive';
|
||||
return Misc.data(competence).name != 'Esquive';
|
||||
case 'tir':
|
||||
case 'lancer':
|
||||
return true;
|
||||
@ -85,15 +107,15 @@ export class RdDItemCompetence extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isArmeUneMain(competence) {
|
||||
return competence?.name.toLowerCase().includes("1 main");
|
||||
return Misc.data(competence)?.name.toLowerCase().includes("1 main");
|
||||
}
|
||||
static isArme2Main(competence) {
|
||||
return competence?.name.toLowerCase().includes("2 main");
|
||||
return Misc.data(competence)?.name.toLowerCase().includes("2 main");
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isMalusEncombrementTotal(competence) {
|
||||
return competence?.name.toLowerCase().match(/(natation|acrobatie)/);
|
||||
return Misc.data(competence)?.name.toLowerCase().match(/(natation|acrobatie)/);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -110,17 +132,18 @@ export class RdDItemCompetence extends Item {
|
||||
/* -------------------------------------------- */
|
||||
static computeTotalXP(competences) {
|
||||
const total = competences.map(c => RdDItemCompetence.computeXP(c))
|
||||
.reduce((a, b) => a + b, 0);
|
||||
.reduce(Misc.sum(), 0);
|
||||
const economieTronc = RdDItemCompetence.computeEconomieXPTronc(competences);
|
||||
return total - economieTronc;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeXP(competence) {
|
||||
const factor = competence.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double !
|
||||
const xpNiveau = RdDItemCompetence.computeDeltaXP(competence.data.base, competence.data.niveau ?? competence.data.base);
|
||||
const xp = competence.data.xp ?? 0;
|
||||
const xpSort = competence.data.xp_sort ?? 0;
|
||||
const itemData = Misc.data(competence);
|
||||
const factor = itemData.name.includes('Thanatos') ? 2 : 1; // Thanatos compte double !
|
||||
const xpNiveau = RdDItemCompetence.computeDeltaXP(itemData.data.base, itemData.data.niveau ?? itemData.data.base);
|
||||
const xp = itemData.data.xp ?? 0;
|
||||
const xpSort = itemData.data.xp_sort ?? 0;
|
||||
return factor * (xpNiveau + xp) + xpSort;
|
||||
}
|
||||
|
||||
@ -128,12 +151,12 @@ export class RdDItemCompetence extends Item {
|
||||
static computeEconomieXPTronc(competences) {
|
||||
return competenceTroncs.map(
|
||||
list => list.map(name => RdDItemCompetence.findCompetence(competences, name))
|
||||
// calcul du coût xp jusqu'au niveau 0 maximum
|
||||
.map(it => RdDItemCompetence.computeDeltaXP(it?.data.base ?? -11, Math.min(it?.data.niveau ?? -11, 0)))
|
||||
.sort((a, b) => b - a) // tri descendant
|
||||
.splice(0, 1) // ignorer le coût xp le plus élevé
|
||||
.reduce((a, b) => a + b, 0)
|
||||
).reduce((a, b) => a + b, 0);
|
||||
// calcul du coût xp jusqu'au niveau 0 maximum
|
||||
.map(it => RdDItemCompetence.computeDeltaXP(it?.data.base ?? -11, Math.min(it?.data.niveau ?? -11, 0)))
|
||||
.sort(Misc.ascending())
|
||||
.splice(0, list.length-1) // prendre toutes les valeurs sauf l'une des plus élevées
|
||||
.reduce(Misc.sum(), 0)
|
||||
).reduce(Misc.sum(), 0);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -146,10 +169,11 @@ export class RdDItemCompetence extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeCompetenceXPCost(competence) {
|
||||
let xp = RdDItemCompetence.getDeltaXp(competence.data.base, competence.data.niveau ?? competence.data.base);
|
||||
xp += competence.data.xp ?? 0;
|
||||
if (competence.name.includes('Thanatos')) xp *= 2; /// Thanatos compte double !
|
||||
xp += competence.data.xp_sort ?? 0;
|
||||
const compData = Misc.data(competence);
|
||||
let xp = RdDItemCompetence.getDeltaXp(compData.data.base, compData.data.niveau ?? compData.data.base);
|
||||
xp += compData.data.xp ?? 0;
|
||||
if (compData.name.includes('Thanatos')) xp *= 2; /// Thanatos compte double !
|
||||
xp += compData.data.xp_sort ?? 0;
|
||||
return xp;
|
||||
}
|
||||
|
||||
@ -158,20 +182,22 @@ export class RdDItemCompetence extends Item {
|
||||
let economie = 0;
|
||||
for (let troncList of competenceTroncs) {
|
||||
let list = troncList.map(name => RdDItemCompetence.findCompetence(competences, name))
|
||||
.sort((c1, c2) => c2.data.niveau - c1.data.niveau); // tri du plus haut au plus bas
|
||||
.sort(Misc.descending(c => Misc.templateData(c).niveau)); // tri du plus haut au plus bas
|
||||
list.splice(0, 1); // ignorer la plus élevée
|
||||
list.forEach(c => {
|
||||
economie += RdDItemCompetence.getDeltaXp(c.data.base, Math.min(c.data.niveau, 0));
|
||||
list.map(c => Misc.templateData(c)).forEach(tplData => {
|
||||
economie += RdDItemCompetence.getDeltaXp(tplData.base, Math.min(tplData.niveau, 0));
|
||||
});
|
||||
}
|
||||
return economie;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static levelUp(itemData) {
|
||||
itemData.data.xpNext = RdDItemCompetence.getCompetenceNextXp(itemData.data.niveau);
|
||||
itemData.data.isLevelUp = itemData.data.xp >= itemData.data.xpNext;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isVisible(itemData) {
|
||||
return Number(itemData.data.niveau) != RdDItemCompetence.getNiveauBase(itemData.data.categorie);
|
||||
}
|
||||
@ -183,8 +209,20 @@ export class RdDItemCompetence extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static findCompetence(list, name) {
|
||||
name = name.toLowerCase();
|
||||
return list.find(it => it.name.toLowerCase() == name && (it.type == "competence" || it.type == "competencecreature"))
|
||||
name = Grammar.toLowerCaseNoAccent(name);
|
||||
const competences = list.filter(it => Grammar.toLowerCaseNoAccent(it.name).includes(name) && (it.type == "competence" || it.type == "competencecreature"));
|
||||
if (competences.length == 0) {
|
||||
return undefined;
|
||||
}
|
||||
let competence = competences.find(it => Grammar.toLowerCaseNoAccent(it.name) == name);
|
||||
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;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -195,7 +233,7 @@ export class RdDItemCompetence extends Item {
|
||||
/* -------------------------------------------- */
|
||||
static getCompetenceXp(niveau) {
|
||||
RdDItemCompetence._valideNiveau(niveau);
|
||||
return niveau < -10 ? 0 : competence_xp_par_niveau[niveau + 10];
|
||||
return niveau < -10 ? 0 : xp_par_niveau[niveau + 10];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -207,19 +245,19 @@ export class RdDItemCompetence extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _valideNiveau(niveau) {
|
||||
if (niveau < -11 || niveau > competence_niveau_max) {
|
||||
console.warn(`Niveau ${niveau} en dehors des niveaux de compétences: [-11, ${competence_niveau_max} ]`);
|
||||
if (niveau < -11 || niveau > niveau_max) {
|
||||
console.warn(`Niveau ${niveau} en dehors des niveaux de compétences: [-11, ${niveau_max} ]`);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeResumeArchetype(competences) {
|
||||
const archetype = RdDItemCompetence.getLimitesArchetypes();
|
||||
competences.forEach(it => {
|
||||
let niveau = Math.max(0, it.data.niveau_archetype);
|
||||
archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 };
|
||||
archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1;
|
||||
});
|
||||
competences.map(it => Math.max(0, Misc.templateData(it).niveau_archetype))
|
||||
.forEach(niveau => {
|
||||
archetype[niveau] = archetype[niveau] ?? { "niveau": niveau, "nombreMax": 0, "nombre": 0 };
|
||||
archetype[niveau].nombre = (archetype[niveau]?.nombre ?? 0) + 1;
|
||||
});
|
||||
return archetype;
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,8 @@ export class RdDItemCompetenceCreature extends Item {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static setRollDataCreature(rollData) {
|
||||
rollData.competence = Misc.data(rollData.competence);
|
||||
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.categorie = "creature";
|
||||
rollData.selectedCarac = rollData.carac.carac_creature;
|
||||
@ -26,6 +26,7 @@ export class RdDItemCompetenceCreature extends Item {
|
||||
competence: itemData.name,
|
||||
resistance: 100,
|
||||
equipe: true,
|
||||
dommagesReels: arme.data.dommages,
|
||||
penetration: 0,
|
||||
force: 0,
|
||||
rapide: true
|
||||
|
@ -1,22 +1,23 @@
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
const monnaiesData = [
|
||||
{
|
||||
_id: randomID(16), name: "Etain (1 denier)", type: 'monnaie',
|
||||
name: "Etain (1 denier)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_etain_poisson.webp",
|
||||
data: { quantite: 0, valeur_deniers: 1, encombrement: 0.001, description: "" }
|
||||
},
|
||||
{
|
||||
_id: randomID(16), name: "Bronze (10 deniers)", type: 'monnaie',
|
||||
name: "Bronze (10 deniers)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_bronze_epees.webp",
|
||||
data: { quantite: 0, valeur_deniers: 10, encombrement: 0.002, description: "" }
|
||||
},
|
||||
{
|
||||
_id: randomID(16), name: "Argent (1 sol)", type: 'monnaie',
|
||||
name: "Argent (1 sol)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_argent_sol.webp",
|
||||
data: { quantite: 0, valeur_deniers: 100, encombrement: 0.003, description: "" }
|
||||
},
|
||||
{
|
||||
_id: randomID(16), name: "Or (10 sols)", type: 'monnaie',
|
||||
name: "Or (10 sols)", type: 'monnaie',
|
||||
img: "systems/foundryvtt-reve-de-dragon/icons/objets/piece_or_sol.webp",
|
||||
data: { quantite: 0, valeur_deniers: 1000, encombrement: 0.004, description: "" }
|
||||
}
|
||||
@ -29,12 +30,21 @@ export class Monnaie {
|
||||
}
|
||||
|
||||
static filtrerMonnaies(items) {
|
||||
return items.filter(it => it.type == 'monnaie');
|
||||
return items.filter(it => Misc.data(it).type == 'monnaie');
|
||||
}
|
||||
|
||||
static monnaiesManquantes(items) {
|
||||
const valeurs = Monnaie.filtrerMonnaies(items)
|
||||
.map(it => it.data.valeur_deniers)
|
||||
return duplicate(monnaiesData.filter(monnaie => !valeurs.find(v => v != monnaie.data.valeur_deniers)));
|
||||
const valeurs = Monnaie.filtrerMonnaies(items)
|
||||
.map(it => Misc.templateData(it).valeur_deniers)
|
||||
const manquantes = monnaiesData.filter(monnaie => !valeurs.find(v => v != Misc.templateData(monnaie).valeur_deniers));
|
||||
return manquantes;
|
||||
}
|
||||
|
||||
static deValeur(monnaie, v) {
|
||||
return v != monnaie.data.valeur_deniers;
|
||||
}
|
||||
|
||||
static arrondiDeniers(sols) {
|
||||
return sols.toFixed(2);
|
||||
}
|
||||
}
|
||||
|
@ -1,315 +0,0 @@
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -1,9 +1,11 @@
|
||||
import { RdDItemSort } from "./item-sort.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { RdDItem } from "./item-rdd.js";
|
||||
import { RdDAlchimie } from "./rdd-alchimie.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDHerbes } from "./rdd-herbes.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
|
||||
@ -12,85 +14,139 @@ import { Misc } from "./misc.js";
|
||||
export class RdDItemSheet 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-sheet.html",
|
||||
width: 550,
|
||||
height: 550
|
||||
static get defaultOptions() {
|
||||
return mergeObject(super.defaultOptions, {
|
||||
classes: ["foundryvtt-reve-de-dragon", "sheet", "item"],
|
||||
template: "systems/foundryvtt-reve-de-dragon/templates/item-sheet.html",
|
||||
width: 550,
|
||||
height: 550
|
||||
//tabs: [{navSelector: ".sheet-tabs", contentSelector: ".sheet-body", initial: "description"}]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_getHeaderButtons() {
|
||||
let buttons = super._getHeaderButtons();
|
||||
const videSiConteneur = this.object.isConteneur() ? this.object.isVide() : true;
|
||||
// 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!
|
||||
buttons.unshift(
|
||||
{
|
||||
if ("cout" in Misc.templateData(this.object) && videSiConteneur) {
|
||||
buttons.unshift({
|
||||
class: "post",
|
||||
icon: "fas fa-comments-dollar",
|
||||
onclick: ev => this.item.proposerVente()
|
||||
});
|
||||
}
|
||||
else {
|
||||
buttons.unshift({
|
||||
class: "post",
|
||||
icon: "fas fa-comment",
|
||||
onclick: ev => new RdDItem(Misc.data(this.item)).postItem()
|
||||
})
|
||||
onclick: ev => this.item.postItem()
|
||||
});
|
||||
}
|
||||
return buttons
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
setPosition(options={}) {
|
||||
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 - 192;
|
||||
const bodyHeight = position.height - sheetHeader[0].clientHeight;
|
||||
sheetBody.css("height", bodyHeight);
|
||||
return position;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async getData() {
|
||||
let formData = super.getData();
|
||||
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences();
|
||||
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.competences = await RdDUtility.loadCompendiumNames( 'foundryvtt-reve-de-dragon.competences' );
|
||||
const objectData = Misc.data(this.object);
|
||||
|
||||
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 (formData.item.type == 'arme') {
|
||||
formData.competences = await RdDUtility.loadCompendium( 'foundryvtt-reve-de-dragon.competences', it => RdDItemCompetence.isCompetenceArme(it));
|
||||
}
|
||||
if ( formData.item.type == 'recettealchimique' ) {
|
||||
RdDAlchimie.processManipulation(formData.item, this.actor && this.actor._id );
|
||||
}
|
||||
if ( this.actor ) {
|
||||
if (this.actor) {
|
||||
formData.isOwned = true;
|
||||
formData.actorId = this.actor._id;
|
||||
formData.actorId = this.actor.id;
|
||||
}
|
||||
|
||||
formData.categorieCompetences = RdDItemCompetence.getCategorieCompetences();
|
||||
if (formData.type == 'tache' || formData.type == 'livre' || formData.type == 'meditation' || formData.type == 'oeuvre') {
|
||||
formData.caracList = duplicate(game.system.model.Actor.personnage.carac);
|
||||
formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences');
|
||||
}
|
||||
if (formData.type == 'arme') {
|
||||
formData.competences = await RdDUtility.loadCompendium('foundryvtt-reve-de-dragon.competences', it => RdDItemCompetence.isCompetenceArme(it));
|
||||
console.log(formData.competences);
|
||||
}
|
||||
if (formData.type == 'recettealchimique') {
|
||||
RdDAlchimie.processManipulation(objectData, this.actor && this.actor.id);
|
||||
}
|
||||
if (formData.type == 'potion') {
|
||||
if (this.dateUpdated) {
|
||||
formData.data.prdate = this.dateUpdated;
|
||||
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.isGM = game.user.isGM; // Pour verrouiller certaines éditions
|
||||
|
||||
return formData;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/** @override */
|
||||
activateListeners(html) {
|
||||
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
|
||||
if (!this.options.editable) return;
|
||||
|
||||
// Select competence categorie
|
||||
html.find("#categorie").on("click", this._onClickSelectCategorie.bind(this) );
|
||||
html.find(".categorie").change(event => this._onSelectCategorie(event));
|
||||
|
||||
html.find('#sheet-competence-xp').change((event) => {
|
||||
if ( this.object.data.type == 'competence') {
|
||||
RdDUtility.checkThanatosXP( this.object.data.name );
|
||||
html.find('.sheet-competence-xp').change((event) => {
|
||||
if (this.object.data.type == 'competence') {
|
||||
RdDUtility.checkThanatosXP(this.object.data.name);
|
||||
}
|
||||
} );
|
||||
});
|
||||
|
||||
html.find('#creer-tache-livre').click((event) => {
|
||||
html.find('.enchanteDate').change((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 actor = game.actors.get( actorId );
|
||||
actor.creerTacheDepuisLivre( this.item );
|
||||
let actor = game.actors.get(actorId);
|
||||
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) => {
|
||||
@ -98,8 +154,8 @@ export class RdDItemSheet extends ItemSheet {
|
||||
let recetteId = event.currentTarget.attributes['data-recette-id'].value;
|
||||
let tacheName = event.currentTarget.attributes['data-alchimie-tache'].value;
|
||||
let tacheData = event.currentTarget.attributes['data-alchimie-data'].value;
|
||||
let actor = game.actors.get( actorId );
|
||||
if ( actor ) {
|
||||
let actor = game.actors.get(actorId);
|
||||
if (actor) {
|
||||
actor.effectuerTacheAlchimie(recetteId, tacheName, tacheData);
|
||||
} else {
|
||||
ui.notifications.info("Impossible trouver un actur pour réaliser cette tache Alchimique.");
|
||||
@ -109,27 +165,30 @@ export class RdDItemSheet extends ItemSheet {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _onClickSelectCategorie(event) {
|
||||
async _onSelectCategorie(event) {
|
||||
event.preventDefault();
|
||||
|
||||
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
|
||||
this.object.data.data.base = level;
|
||||
$("#base").val( level );
|
||||
if (this.object.isCompetence()){
|
||||
let level = RdDItemCompetence.getNiveauBase(event.currentTarget.value);
|
||||
Misc.templateData(this.object).base = level;
|
||||
$("#base").val(level);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
get template()
|
||||
{
|
||||
let type = this.item.type;
|
||||
get template() {
|
||||
//console.log(this);
|
||||
let type = this.object.data.type;
|
||||
return `systems/foundryvtt-reve-de-dragon/templates/item-${type}-sheet.html`;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
||||
/** @override */
|
||||
_updateObject(event, formData) {
|
||||
_updateObject(event, formData) { // Deprecated en v0.8 à clarifier
|
||||
//console.log("UPDATE !", formData);
|
||||
// Données de bonus de cases ?
|
||||
formData = RdDItemSort.buildBonusCaseStringFromFormData( formData );
|
||||
formData = RdDItemSort.buildBonusCaseStringFromFormData(formData);
|
||||
|
||||
return this.object.update(formData);
|
||||
}
|
||||
|
104
module/item-signedraconique-sheet.js
Normal file
@ -0,0 +1,104 @@
|
||||
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();
|
||||
// $("[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);
|
||||
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}`;
|
||||
}
|
||||
}
|
100
module/item-signedraconique.js
Normal file
@ -0,0 +1,100 @@
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||
import { TMRType } 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": [Misc.upperFirst(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() {
|
||||
let modele = await RdDDice.rollOneOf(tableSignesIndicatifs);
|
||||
return {
|
||||
name: await RdDItemSigneDraconique.randomSigneDescription(),
|
||||
type: "signedraconique",
|
||||
img: 'systems/foundryvtt-reve-de-dragon/icons/tmr/signe_draconique.webp',
|
||||
data: {
|
||||
typesTMR: await RdDItemSigneDraconique.randomTmrs(modele.nbCases),
|
||||
ephemere: true,
|
||||
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 => Misc.upperFirst(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);
|
||||
}
|
||||
|
||||
}
|
@ -51,10 +51,10 @@ export class RdDItemSort extends Item {
|
||||
* Retourne une liste de bonus/case pour un item-sheet
|
||||
* @param {} item
|
||||
*/
|
||||
static getBonusCaseList( data, newCase = false ) {
|
||||
static getBonusCaseList( item, newCase = false ) {
|
||||
// Gestion spéciale case bonus
|
||||
if ( data.item.type == 'sort') {
|
||||
return this.buildBonusCaseList(data.data.bonuscase, newCase );
|
||||
if ( item.type == 'sort') {
|
||||
return this.buildBonusCaseList(item.data.bonuscase, newCase );
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -106,7 +106,7 @@ export class RdDItemSort extends Item {
|
||||
// Sauvegarde/update
|
||||
let bonuscase = StringList.toString();
|
||||
//console.log("Bonus cae :", bonuscase);
|
||||
actor.updateEmbeddedEntity("OwnedItem", { _id: sort._id, 'data.bonuscase': bonuscase } );
|
||||
actor.updateEmbeddedDocuments('Item', [{ _id: sort._id, 'data.bonuscase': bonuscase }] );
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
512
module/item.js
Normal file
@ -0,0 +1,512 @@
|
||||
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 class RdDItem extends Item {
|
||||
|
||||
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.object).magique;
|
||||
}
|
||||
|
||||
getEnc() {
|
||||
const itemData = Misc.data(this);
|
||||
switch (itemData.type) {
|
||||
case 'herbe':
|
||||
return encBrin;
|
||||
}
|
||||
return itemData.data.encombrement
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
for (const [key, value] of Object.entries(tplData)) {
|
||||
if (['quantite', 'encTotal', 'prixTotal', 'cout'].includes(key)) continue;
|
||||
if (value != otherTplData[key]) 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[`_${venteData.item.type}ChatData`]();
|
||||
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));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async postItem() {
|
||||
console.log(this);
|
||||
let chatData = duplicate(Misc.data(this));
|
||||
const properties = this[`_${chatData.type}ChatData`]();
|
||||
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;
|
||||
}
|
||||
|
||||
}
|
@ -1,3 +1,4 @@
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
|
||||
/**
|
||||
* This class is intended as a placeholder for utility methods unrelated
|
||||
@ -18,6 +19,24 @@ export class Misc {
|
||||
return isPositiveNumber ? "+" + number : number
|
||||
}
|
||||
|
||||
static sum() {
|
||||
return (a, b) => a + b;
|
||||
}
|
||||
|
||||
static ascending(orderFunction = x => x) {
|
||||
return (a, b) => Misc.sortingBy(orderFunction(a), orderFunction(b));
|
||||
}
|
||||
|
||||
static descending(orderFunction = x => x) {
|
||||
return (a, b) => Misc.sortingBy(orderFunction(b), orderFunction(a));
|
||||
}
|
||||
|
||||
static sortingBy(a, b) {
|
||||
if (a > b) return 1;
|
||||
if (a < b) return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the value to an integer, or to 0 if undefined/null/not representing integer
|
||||
* @param {*} value value to convert to an integer using parseInt
|
||||
@ -30,6 +49,12 @@ export class Misc {
|
||||
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) {
|
||||
if (!diviseur || diviseur <= 1) return undefined;
|
||||
switch (diviseur || 1) {
|
||||
@ -39,9 +64,9 @@ export class Misc {
|
||||
}
|
||||
}
|
||||
|
||||
static classify(items, classifier = it => it.type, transform = it => it) {
|
||||
static classify(items, classifier = it => it.type) {
|
||||
let itemsBy = {};
|
||||
Misc.classifyInto(itemsBy, items, classifier, transform);
|
||||
Misc.classifyInto(itemsBy, items, classifier);
|
||||
return itemsBy;
|
||||
}
|
||||
|
||||
@ -56,7 +81,7 @@ export class Misc {
|
||||
return itemsBy;
|
||||
}
|
||||
|
||||
static classifyInto(itemsBy, items, classifier = it => it.type, transform = it => it) {
|
||||
static classifyInto(itemsBy, items, classifier = it => it.type) {
|
||||
for (const item of items) {
|
||||
const classification = classifier(item);
|
||||
let list = itemsBy[classification];
|
||||
@ -64,31 +89,16 @@ export class Misc {
|
||||
list = [];
|
||||
itemsBy[classification] = list;
|
||||
}
|
||||
list.push(transform(item));
|
||||
list.push(item);
|
||||
}
|
||||
}
|
||||
|
||||
static rollOneOf(array) {
|
||||
return array[new Roll("1d" + array.length).evaluate().total - 1];
|
||||
}
|
||||
|
||||
static distinct(array) {
|
||||
return [...new Set(array)];
|
||||
}
|
||||
|
||||
static actorData(actor) {
|
||||
return Misc.data(actor);
|
||||
}
|
||||
|
||||
static itemData(item) {
|
||||
return Misc.data(item);
|
||||
}
|
||||
|
||||
static data(it) {
|
||||
if (it instanceof Item) {
|
||||
return it.data;
|
||||
}
|
||||
if (it instanceof Actor) {
|
||||
if (it instanceof Actor || it instanceof Item || it instanceof Combatant) {
|
||||
return it.data;
|
||||
}
|
||||
return it;
|
||||
@ -97,4 +107,14 @@ export class Misc {
|
||||
static templateData(it) {
|
||||
return Misc.data(it)?.data ?? {}
|
||||
}
|
||||
|
||||
static connectedGMOrUser(ownerId = undefined) {
|
||||
if (ownerId && game.user.id == ownerId) {
|
||||
return ownerId;
|
||||
}
|
||||
return (game.user.isGM ? game.user.id : game.users.entities.find(u => u.isGM && u.active)?.id) ?? game.user.id;
|
||||
}
|
||||
static isElectedUser() {
|
||||
return game.user.id == Misc.connectedGMOrUser();
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import { Misc } from "./misc.js"
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
|
||||
const poesieHautReve = [
|
||||
{
|
||||
@ -50,7 +51,7 @@ const poesieHautReve = [
|
||||
},
|
||||
{
|
||||
reference: 'Denis Gerfaud',
|
||||
extrait: `Ainsi se cuccèdent les Jours et les Ages.
|
||||
extrait: `Ainsi se succèdent les Jours et les Ages.
|
||||
<br>Les jours des Dragons sont les Ages des Hommes.`
|
||||
},
|
||||
{
|
||||
@ -64,8 +65,8 @@ const poesieHautReve = [
|
||||
]
|
||||
|
||||
export class Poetique {
|
||||
static getExtrait(){
|
||||
return Misc.rollOneOf(poesieHautReve);
|
||||
static async getExtrait(){
|
||||
return await RdDDice.rollOneOf(poesieHautReve);
|
||||
}
|
||||
|
||||
}
|
@ -1,68 +1,65 @@
|
||||
/* -------------------------------------------- */
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
const matchOperations = new RegExp(/@(\w*){([\w\-]+)}/ig);
|
||||
const matchOperationTerms = new RegExp(/@(\w*){([\w\-]+)}/i);
|
||||
/* -------------------------------------------- */
|
||||
export class RdDAlchimie {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static processManipulation( recette, actorId = undefined ) {
|
||||
static processManipulation(recetteData, actorId = undefined) {
|
||||
//console.log("CALLED", recette, recette.isOwned, actorId );
|
||||
let manip = duplicate(recette.data.manipulation);
|
||||
let reg1 = new RegExp(/@(\w*){([\w\-]+)}/ig);
|
||||
let matchArray = manip.match( reg1 );
|
||||
if ( matchArray ) {
|
||||
for( let matchStr of matchArray) {
|
||||
let reg2 = new RegExp(/@(\w*){([\w\-]+)}/i);
|
||||
let result = matchStr.match(reg2);
|
||||
let manip = recetteData.data.manipulation;
|
||||
let matchArray = manip.match(matchOperations);
|
||||
if (matchArray) {
|
||||
for (let matchStr of matchArray) {
|
||||
let result = matchStr.match(matchOperationTerms);
|
||||
//console.log("RESULT ", result);
|
||||
if ( result[1] && result[2]) {
|
||||
let commande = Misc.upperFirst( result[1] );
|
||||
let replacement = this[`_alchimie${commande}`](recette, result[2], actorId);
|
||||
manip = manip.replace( result[0], replacement);
|
||||
if (result[1] && result[2]) {
|
||||
let commande = Misc.upperFirst(result[1]);
|
||||
let replacement = this[`_alchimie${commande}`](recetteData, result[2], actorId);
|
||||
manip = manip.replace(result[0], replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
recette.data.manipulation_update = manip;
|
||||
recetteData.data.manipulation_update = manip;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _alchimieCouleur( recette, couleurs, actorId ) {
|
||||
let replacement
|
||||
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>`;
|
||||
static _alchimieCouleur(recette, couleurs, actorId) {
|
||||
if (actorId) {
|
||||
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>`;
|
||||
} else {
|
||||
replacement = `<span class="alchimie-tache">couleur ${couleurs} </span>`;
|
||||
return `<span class="alchimie-tache">couleur ${couleurs} </span>`;
|
||||
}
|
||||
return replacement;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _alchimieConsistance( recette, consistances, actorId ) {
|
||||
let replacement
|
||||
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>`;
|
||||
static _alchimieConsistance(recette, consistances, actorId) {
|
||||
if (actorId) {
|
||||
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>`;
|
||||
} else {
|
||||
replacement = `<span class="alchimie-tache">consistance ${consistances} </span>`;
|
||||
return `<span class="alchimie-tache">consistance ${consistances} </span>`;
|
||||
}
|
||||
return replacement;
|
||||
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getDifficulte( aspects ) {
|
||||
let aspectsArray = aspects.split('-');
|
||||
let diff = 0;
|
||||
let nbDifferent = 0;
|
||||
let aspectsHash = {}
|
||||
for (let colconst of aspectsArray) {
|
||||
if ( aspectsHash[colconst] ){ // Deja present, augmente difficulté de 1
|
||||
diff -= 1;
|
||||
} else {
|
||||
nbDifferent++;
|
||||
aspectsHash[colconst] = colconst; // Keep track
|
||||
}
|
||||
static getDifficulte(aspects) {
|
||||
let elements = aspects.split('-');
|
||||
let composantes = elements.length;
|
||||
let distincts = Object.keys(Misc.classifyFirst(elements, it => it)).length;
|
||||
if (distincts == 1) {
|
||||
composantes--;
|
||||
}
|
||||
diff = diff - ((nbDifferent>1) ? nbDifferent : 0); // Ca doit marcher ....
|
||||
return Math.min(0, diff); // Pour être sur
|
||||
return Math.min(0, -composantes);
|
||||
}
|
||||
|
||||
static getCaracTache(tache) {
|
||||
switch (tache) {
|
||||
case "consistance": return 'dexterite';
|
||||
case "couleur": return 'vue';
|
||||
}
|
||||
return 'intellect';
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,12 +3,13 @@
|
||||
* Extend the base Dialog entity by defining a custom window to perform roll.
|
||||
* @extends {Dialog}
|
||||
*/
|
||||
export class RdDAstrologieEditeur extends Dialog {
|
||||
export class RdDAstrologieEditeur extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, calendrier, calendrierData) {
|
||||
|
||||
let myButtons = {
|
||||
resetButton: { label: "Re-tirer les nombres astraux", callback: html => this.resetNombreAstraux() },
|
||||
saveButton: { label: "Fermer", callback: html => this.fillData() }
|
||||
};
|
||||
|
||||
@ -21,6 +22,14 @@ export class RdDAstrologieEditeur extends Dialog {
|
||||
this.updateData( calendrierData );
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
resetNombreAstraux() {
|
||||
game.system.rdd.calendrier.resetNombreAstral();
|
||||
game.system.rdd.calendrier.rebuildListeNombreAstral();
|
||||
|
||||
game.system.rdd.calendrier.showAstrologieEditor();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
fillData( ) {
|
||||
}
|
||||
|
@ -8,34 +8,35 @@ import { Misc } from "./misc.js";
|
||||
*/
|
||||
export class RdDAstrologieJoueur extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async create(actor, dialogConfig) {
|
||||
/* -------------------------------------------- */
|
||||
static async create(actor, dialogConfig) {
|
||||
|
||||
let data = { nombres: this.organizeNombres( actor),
|
||||
dates: game.system.rdd.calendrier.getJoursSuivants( 10 ),
|
||||
etat: actor.getEtatGeneral(),
|
||||
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
|
||||
astrologie: RdDItemCompetence.findCompetence( actor.data.items, 'Astrologie')
|
||||
}
|
||||
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 };
|
||||
if (dialogConfig.options) {
|
||||
mergeObject(options, dialogConfig.options, { overwrite: true });
|
||||
}
|
||||
return new RdDAstrologieJoueur(html, actor, data);
|
||||
let data = {
|
||||
nombres: this.organizeNombres(actor),
|
||||
dates: game.system.rdd.calendrier.getJoursSuivants(10),
|
||||
etat: actor.getEtatGeneral(),
|
||||
ajustementsConditions: CONFIG.RDD.ajustementsConditions,
|
||||
astrologie: RdDItemCompetence.findCompetence(actor.data.items, 'Astrologie')
|
||||
}
|
||||
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 };
|
||||
if (dialogConfig.options) {
|
||||
mergeObject(options, dialogConfig.options, { overwrite: true });
|
||||
}
|
||||
return new RdDAstrologieJoueur(html, actor, data);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, actor, data ) {
|
||||
constructor(html, actor, data) {
|
||||
|
||||
let myButtons = {
|
||||
saveButton: { label: "Fermer", callback: html => this.quitDialog() }
|
||||
};
|
||||
saveButton: { label: "Fermer", callback: html => this.quitDialog() }
|
||||
};
|
||||
|
||||
// Get all n
|
||||
// Common conf
|
||||
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);
|
||||
|
||||
this.actor = actor;
|
||||
@ -44,14 +45,14 @@ export class RdDAstrologieJoueur extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static organizeNombres(actor) {
|
||||
let itemNombres = actor.data.items.filter( (item) => item.type == 'nombreastral');
|
||||
let itemNombres = actor.listItemsData('nombreastral');
|
||||
let itemFiltered = {};
|
||||
for ( let item of itemNombres) {
|
||||
if ( itemFiltered[item.data.jourindex] ) {
|
||||
for (let item of itemNombres) {
|
||||
if (itemFiltered[item.data.jourindex]) {
|
||||
itemFiltered[item.data.jourindex].listValues.push(item.data.value);
|
||||
} else {
|
||||
itemFiltered[item.data.jourindex] = {
|
||||
listValues: [ item.data.value ],
|
||||
listValues: [item.data.value],
|
||||
jourlabel: item.data.jourlabel
|
||||
}
|
||||
}
|
||||
@ -60,21 +61,22 @@ export class RdDAstrologieJoueur extends Dialog {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
requestJetAstrologie( ) {
|
||||
let data = { id: this.actor.data._id,
|
||||
carac_vue: Misc.data(this.actor).data.carac['vue'].value,
|
||||
etat: this.dataNombreAstral.etat,
|
||||
astrologie: this.dataNombreAstral.astrologie,
|
||||
conditions: $("#diffConditions").val(),
|
||||
date: $("#joursAstrologie").val()
|
||||
}
|
||||
if ( game.user.isGM) {
|
||||
game.system.rdd.calendrier.requestNombreAstral( data );
|
||||
requestJetAstrologie() {
|
||||
let data = {
|
||||
id: this.actor.data._id,
|
||||
carac_vue: Misc.data(this.actor).data.carac['vue'].value,
|
||||
etat: this.dataNombreAstral.etat,
|
||||
astrologie: this.dataNombreAstral.astrologie,
|
||||
conditions: $("#diffConditions").val(),
|
||||
date: $("#joursAstrologie").val()
|
||||
}
|
||||
if (game.user.isGM) {
|
||||
game.system.rdd.calendrier.requestNombreAstral(data);
|
||||
} else {
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", {
|
||||
msg: "msg_request_nombre_astral",
|
||||
data: data
|
||||
} );
|
||||
});
|
||||
}
|
||||
this.close();
|
||||
}
|
||||
|
@ -5,15 +5,17 @@ import { HtmlUtility } from "./html-utility.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { RdDUtility } from "./rdd-utility.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 heuresList = ["vaisseau", "sirene", "faucon", "couronne", "dragon", "epees", "lyre", "serpent", "poissonacrobate", "araignee", "roseau", "chateaudormant"];
|
||||
const heuresDef = {
|
||||
"vaisseau": { label: "Vaisseau", lettreFont: 'v', saison: "printemps", heure: 0, icon: 'hd01.svg' },
|
||||
"sirene": { label: "Sirène", lettreFont: 'S', saison: "printemps", heure: 1, icon: 'hd02.svg' },
|
||||
"sirene": { label: "Sirène", lettreFont: 'i', saison: "printemps", heure: 1, icon: 'hd02.svg' },
|
||||
"faucon": { label: "Faucon", lettreFont: 'f', saison: "printemps", heure: 2, icon: 'hd03.svg' },
|
||||
"couronne": { label: "Couronne", lettreFont: 'C', saison: "ete", heure: 3, icon: 'hd04.svg' },
|
||||
"couronne": { label: "Couronne", lettreFont: '', saison: "ete", heure: 3, icon: 'hd04.svg' },
|
||||
"dragon": { label: "Dragon", lettreFont: 'd', saison: "ete", heure: 4, icon: 'hd05.svg' },
|
||||
"epees": { label: "Epées", lettreFont: 'e', saison: "ete", heure: 5, icon: 'hd06.svg' },
|
||||
"lyre": { label: "Lyre", lettreFont: 'l', saison: "automne", heure: 6, icon: 'hd07.svg' },
|
||||
@ -39,8 +41,9 @@ export class RdDCalendrier extends Application {
|
||||
async initCalendrier() {
|
||||
// Calendrier
|
||||
this.calendrier = duplicate(game.settings.get("foundryvtt-reve-de-dragon", "calendrier"));
|
||||
console.log("CALENDRIER", this.calendrier);
|
||||
//console.log("CALENDRIER", this.calendrier);
|
||||
if (this.calendrier == undefined || this.calendrier.moisRdD == undefined) {
|
||||
this.calendrier = {};
|
||||
this.calendrier.heureRdD = 0; // Index dans heuresList
|
||||
this.calendrier.minutesRelative = 0;
|
||||
this.calendrier.moisRdD = 0; // Index dans heuresList
|
||||
@ -52,6 +55,7 @@ export class RdDCalendrier extends Application {
|
||||
// position
|
||||
this.calendrierPos = duplicate(game.settings.get("foundryvtt-reve-de-dragon", "calendrier-pos"));
|
||||
if (this.calendrierPos == undefined || this.calendrierPos.top == undefined) {
|
||||
this.calendrierPos = {};
|
||||
this.calendrierPos.top = 200;
|
||||
this.calendrierPos.left = 200;
|
||||
if (game.user.isGM) { // Uniquement si GM
|
||||
@ -88,6 +92,14 @@ export class RdDCalendrier extends Application {
|
||||
return day + " " + heuresList[month];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getNumericDateFromIndex(index = undefined) {
|
||||
if (!index) index = this.getCurrentDayIndex();
|
||||
let month = Math.floor(index / 28)
|
||||
return { month: heuresList[month],
|
||||
day: (index - (month * 28)) + 1 }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getCurrentHeure() {
|
||||
return heuresList[this.calendrier.heureRdD];
|
||||
@ -98,6 +110,10 @@ export class RdDCalendrier extends Application {
|
||||
return (this.calendrier.moisRdD * 28) + this.calendrier.jour;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getIndexFromDate(jour, mois) {
|
||||
return (heuresDef[mois].heure * 28) + (jour-1);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
getJoursSuivants(num) {
|
||||
let jours = [];
|
||||
@ -110,9 +126,9 @@ export class RdDCalendrier extends Application {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
ajouterNombreAstral(index) {
|
||||
async ajouterNombreAstral(index) {
|
||||
return {
|
||||
nombreAstral: new Roll("1d12").roll().total,
|
||||
nombreAstral: await RdDDice.rollTotal("1dh"),
|
||||
valeursFausses: [],
|
||||
index: index
|
||||
}
|
||||
@ -124,6 +140,12 @@ export class RdDCalendrier extends Application {
|
||||
return this.getNombreAstral(indexDate);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
resetNombreAstral( ) {
|
||||
this.listeNombreAstral = [];
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
getNombreAstral(indexDate) {
|
||||
const liste = this.listeNombreAstral ?? this._loadListNombreAstral();
|
||||
@ -199,7 +221,7 @@ export class RdDCalendrier extends Application {
|
||||
/* -------------------------------------------- */
|
||||
syncPlayerTime(calendrier) {
|
||||
this.calendrier = duplicate(calendrier); // Local copy update
|
||||
this.updateDisplay(); // Then update
|
||||
this.updateDisplay();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -247,24 +269,21 @@ export class RdDCalendrier extends Application {
|
||||
console.log(request);
|
||||
let jourDiff = this.getLectureAstrologieDifficulte(request.date);
|
||||
let niveau = Number(request.astrologie.data.niveau) + Number(request.conditions) + Number(jourDiff) + Number(request.etat);
|
||||
let rolled = await RdDResolutionTable.rollData({
|
||||
let rollData= {
|
||||
caracValue: request.carac_vue,
|
||||
finalLevel: niveau,
|
||||
showDice: false
|
||||
});
|
||||
};
|
||||
await RdDResolutionTable.rollData(rollData);
|
||||
let nbAstral = this.getNombreAstral(request.date);
|
||||
let nbAstralFaux = nbAstral;
|
||||
request.rolled = rollData.rolled;
|
||||
request.isValid = true;
|
||||
request.rolled = rolled;
|
||||
if (!rolled.isSuccess) {
|
||||
if (!request.rolled.isSuccess) {
|
||||
request.isValid = false;
|
||||
while (nbAstralFaux == nbAstral) {
|
||||
nbAstralFaux = new Roll("1d12").roll().total;
|
||||
}
|
||||
nbAstral = nbAstralFaux;
|
||||
nbAstral = await RdDDice.rollTotal("1dhr"+nbAstral);
|
||||
// Mise à jour des nombres astraux du joueur
|
||||
let astralData = this.listeNombreAstral.find((nombreAstral, i) => nombreAstral.index == request.date);
|
||||
astralData.valeursFausses.push({ actorId: request.id, nombreAstral: nbAstralFaux });
|
||||
astralData.valeursFausses.push({ actorId: request.id, nombreAstral: nbAstral });
|
||||
game.settings.set("foundryvtt-reve-de-dragon", "liste-nombre-astral", this.listeNombreAstral);
|
||||
}
|
||||
request.nbAstral = nbAstral;
|
||||
@ -338,7 +357,7 @@ export class RdDCalendrier extends Application {
|
||||
if (game.user.isGM) {
|
||||
dateHTML = dateHTML + " - NA: " + this.getCurrentNombreAstral();
|
||||
}
|
||||
for (let handle of document.getElementsByClassName("calendar-move-handle")) {
|
||||
for (let handle of document.getElementsByClassName("calendar-date-rdd")) {
|
||||
handle.innerHTML = dateHTML;
|
||||
}
|
||||
for (let heure of document.getElementsByClassName("calendar-heure-texte")) {
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
const tableCaracDerivee = {
|
||||
// xp: coût pour passer du niveau inférieur à ce niveau
|
||||
@ -61,7 +62,7 @@ export class RdDCarac {
|
||||
static computeTotal(carac, beaute = undefined) {
|
||||
const total = Object.values(carac).filter(c => !c.derivee)
|
||||
.map(it => parseInt(it.value))
|
||||
.reduce((a, b) => a + b, 0);
|
||||
.reduce(Misc.sum(), 0);
|
||||
const beauteSuperieur10 = Math.max((beaute ?? 10) - 10, 0);
|
||||
return total + beauteSuperieur10;
|
||||
}
|
||||
@ -94,7 +95,7 @@ export class RdDCarac {
|
||||
* ainsi que de Perception active et volontaire.
|
||||
*/
|
||||
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)/);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -75,36 +75,36 @@ export class RdDCombatManager extends Combat {
|
||||
const currentId = this.combatant._id;
|
||||
// calculate initiative
|
||||
for (let cId = 0; cId < ids.length; cId++) {
|
||||
const c = this.getCombatant(ids[cId]);
|
||||
const combatant = this.getCombatant(ids[cId]);
|
||||
//if (!c) return results;
|
||||
|
||||
let rollFormula = formula; // Init per default
|
||||
if (!rollFormula) {
|
||||
let armeCombat, competence;
|
||||
if (c.actor.data.type == 'creature' || c.actor.data.type == 'entite') {
|
||||
for (const competenceItemData of c.actor.data.items) {
|
||||
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
|
||||
for (const competenceItemData of combatant.actor.data.items) {
|
||||
if (competenceItemData.data.iscombat) {
|
||||
competence = duplicate(competenceItemData);
|
||||
}
|
||||
}
|
||||
rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, competence.data.carac_value) + ")/100)";
|
||||
} else {
|
||||
for (const itemData of c.actor.data.items) {
|
||||
for (const itemData of combatant.actor.data.items) {
|
||||
if (itemData.type == "arme" && itemData.data.equipe) {
|
||||
armeCombat = duplicate(itemData);
|
||||
}
|
||||
}
|
||||
let compName = (armeCombat == undefined) ? "Corps à corps" : armeCombat.data.competence;
|
||||
competence = RdDItemCompetence.findCompetence(c.actor.data.items, compName);
|
||||
competence = RdDItemCompetence.findCompetence(combatant.actor.data.items, compName);
|
||||
let bonusEcaille = (armeCombat && armeCombat.data.magique) ? armeCombat.data.ecaille_efficacite : 0;
|
||||
rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, Misc.data(c.actor).data.carac[competence.data.defaut_carac].value, bonusEcaille) + ")/100)";
|
||||
rollFormula = "2+( (" + RdDCombatManager.calculInitiative(competence.data.niveau, Misc.data(combatant.actor).data.carac[competence.data.defaut_carac].value, bonusEcaille) + ")/100)";
|
||||
}
|
||||
}
|
||||
//console.log("Combatat", c);
|
||||
const roll = super._getInitiativeRoll(c, rollFormula);
|
||||
const roll = combatant.getInitiativeRoll(rollFormula);
|
||||
if (roll.total <= 0) roll.total = 0.00;
|
||||
console.log("Compute init for", rollFormula, roll.total);
|
||||
await this.updateEmbeddedEntity("Combatant", { _id: c._id, initiative: roll.total });
|
||||
await this.updateEmbeddedDocuments("Combatant", [{ _id: combatant._id, initiative: roll.total }]);
|
||||
|
||||
// Send a chat message
|
||||
let rollMode = messageOptions.rollMode || game.settings.get("core", "rollMode");
|
||||
@ -112,12 +112,12 @@ export class RdDCombatManager extends Combat {
|
||||
{
|
||||
speaker: {
|
||||
scene: canvas.scene._id,
|
||||
actor: c.actor ? c.actor._id : null,
|
||||
token: c.token._id,
|
||||
alias: c.token.name,
|
||||
actor: combatant.actor ? combatant.actor._id : null,
|
||||
token: combatant.token._id,
|
||||
alias: combatant.token.name,
|
||||
sound: CONFIG.sounds.dice,
|
||||
},
|
||||
flavor: `${c.token.name} a fait son jet d'Initiative (${messageOptions.initInfo})
|
||||
flavor: `${combatant.token.name} a fait son jet d'Initiative (${messageOptions.initInfo})
|
||||
<br>
|
||||
`,
|
||||
},
|
||||
@ -143,35 +143,31 @@ export class RdDCombatManager extends Combat {
|
||||
// Gestion des armes 1/2 mains
|
||||
let armesEquipe = [];
|
||||
for (const arme of armes) {
|
||||
if (arme.data.equipe) {
|
||||
armesEquipe.push(arme);
|
||||
let comp = competences.find(c => c.name == arme.data.competence);
|
||||
arme.data.initiative = RdDCombatManager.calculInitiative(arme.data.niveau, carac[comp.data.defaut_carac].value);
|
||||
let armeData = Misc.data(arme);
|
||||
if (armeData.data.equipe) {
|
||||
let compData = competences.map(c => Misc.data(c)).find(c => c.name == armeData.data.competence);
|
||||
|
||||
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
|
||||
if (arme.data.unemain && !arme.data.deuxmains) {
|
||||
arme.data.mainInfo = "(1m)";
|
||||
} else if (!arme.data.unemain && arme.data.deuxmains) {
|
||||
arme.data.mainInfo = "(2m)";
|
||||
} else if (arme.data.unemain && arme.data.deuxmains) {
|
||||
arme.data.mainInfo = "(1m)";
|
||||
let arme2main = duplicate(arme);
|
||||
if (armeData.data.unemain && !armeData.data.deuxmains) {
|
||||
armeData.data.mainInfo = "(1m)";
|
||||
} else if (!armeData.data.unemain && armeData.data.deuxmains) {
|
||||
armeData.data.mainInfo = "(2m)";
|
||||
} else if (armeData.data.unemain && armeData.data.deuxmains) {
|
||||
armeData.data.mainInfo = "(1m)";
|
||||
let arme2main = duplicate(armeData);
|
||||
arme2main.data.mainInfo = "(2m)";
|
||||
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 !
|
||||
let comp = competences.find(c => c.name == arme2main.data.competence);
|
||||
let comp = Misc.data(competences.find(c => c.name == arme2main.data.competence));
|
||||
arme2main.data.niveau = comp.data.niveau;
|
||||
arme2main.data.initiative = RdDCombatManager.calculInitiative(arme2main.data.niveau, carac[comp.data.defaut_carac].value);
|
||||
armesEquipe.push(arme2main);
|
||||
}
|
||||
}
|
||||
}
|
||||
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;
|
||||
});
|
||||
return armesEquipe.sort(Misc.ascending(armeData => armeData.name + (armeData.data.mainInfo ?? '')));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -180,6 +176,7 @@ export class RdDCombatManager extends Combat {
|
||||
ui.notifications.warn(`Le combatant ${combatant.name} n'est pas associé à un acteur, impossible de déterminer ses actions de combat!`)
|
||||
return [];
|
||||
}
|
||||
const actorData = Misc.data(combatant.actor);
|
||||
let items = combatant.actor.data.items;
|
||||
let actions = []
|
||||
if (combatant.actor.isCreature()) {
|
||||
@ -188,13 +185,14 @@ export class RdDCombatManager extends Combat {
|
||||
} else {
|
||||
// Recupération des items 'arme'
|
||||
let armes = items.filter(it => RdDItemArme.isArmeUtilisable(it))
|
||||
.map(arme => duplicate(arme)) /* pas de changements aux armes d'origine */
|
||||
.concat(RdDItemArme.mainsNues());
|
||||
|
||||
let competences = items.filter(it => it.type == 'competence');
|
||||
actions = actions.concat(RdDCombatManager.finalizeArmeList(armes, competences, Misc.data(combatant.actor).data.carac));
|
||||
actions = actions.concat(RdDCombatManager.finalizeArmeList(armes, competences, actorData.data.carac));
|
||||
|
||||
actions.push({ name: "Draconic", data: { initOnly: true, competence: "Draconic" } });
|
||||
if (actorData.data.attributs.hautrevant.value){
|
||||
actions.push({ name: "Draconic", data: { initOnly: true, competence: "Draconic" } });
|
||||
}
|
||||
}
|
||||
|
||||
actions.push({ name: "Autre action", data: { initOnly: true, competence: "Autre action" } });
|
||||
@ -268,7 +266,7 @@ export class RdDCombatManager extends Combat {
|
||||
let initOffset = 0;
|
||||
let caracForInit = 0;
|
||||
let compNiveau = 0;
|
||||
let competence = { name: "Aucune" };
|
||||
let compData = { name: "Aucune" };
|
||||
if (combatant.actor.getSurprise() == "totale") {
|
||||
initOffset = -1; // To force 0
|
||||
initInfo = "Surprise Totale"
|
||||
@ -283,24 +281,24 @@ export class RdDCombatManager extends Combat {
|
||||
initInfo = "Draconic"
|
||||
} else {
|
||||
initOffset = 3; // Melée = 3.XX
|
||||
competence = RdDItemCompetence.findCompetence(combatant.actor.data.items, arme.data.competence);
|
||||
compNiveau = competence.data.niveau;
|
||||
compData = Misc.data(RdDItemCompetence.findCompetence(combatant.actor.data.items, arme.data.competence));
|
||||
compNiveau = compData.data.niveau;
|
||||
initInfo = arme.name + " / " + arme.data.competence;
|
||||
|
||||
if (combatant.actor.data.type == 'creature' || combatant.actor.data.type == 'entite') {
|
||||
caracForInit = competence.data.carac_value;
|
||||
if (competence.data.categorie == "lancer") {
|
||||
caracForInit = compData.data.carac_value;
|
||||
if (compData.data.categorie == "lancer") {
|
||||
initOffset = 5;
|
||||
}
|
||||
} else {
|
||||
caracForInit = Misc.data(combatant.actor).data.carac[competence.data.defaut_carac].value;
|
||||
if (competence.data.categorie == "lancer") { // Offset de principe pour les armes de jet
|
||||
caracForInit = Misc.data(combatant.actor).data.carac[compData.data.defaut_carac].value;
|
||||
if (compData.data.categorie == "lancer") { // Offset de principe pour les armes de jet
|
||||
initOffset = 4;
|
||||
}
|
||||
if (competence.data.categorie == "tir") { // Offset de principe pour les armes de jet
|
||||
if (compData.data.categorie == "tir") { // Offset de principe pour les armes de jet
|
||||
initOffset = 5;
|
||||
}
|
||||
if (competence.data.categorie == "melee") { // Offset de principe pour les armes de jet
|
||||
if (compData.data.categorie == "melee") { // Offset de principe pour les armes de jet
|
||||
initOffset = 3;
|
||||
}
|
||||
}
|
||||
@ -340,8 +338,8 @@ export class RdDCombat {
|
||||
|
||||
static init() {
|
||||
this.initStorePasseArmes();
|
||||
Hooks.on("updateCombat", (combat, data) => { RdDCombat.onUpdateCombat(combat, data) });
|
||||
Hooks.on("preDeleteCombat", (combat, options) => { RdDCombat.onPreDeleteCombat(combat, options); });
|
||||
Hooks.on("updateCombat", (combat, change, options, userId) => { RdDCombat.onUpdateCombat(combat, change, options, userId) });
|
||||
Hooks.on("preDeleteCombat", (combat, options, userId) => { RdDCombat.onPreDeleteCombat(combat, options, userId); });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -363,14 +361,14 @@ export class RdDCombat {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onUpdateCombat(combat, data) {
|
||||
static onUpdateCombat(combat, change, options, userId) {
|
||||
if (combat.data.round != 0 && combat.turns && combat.data.active) {
|
||||
RdDCombat.combatNouveauTour(combat);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static onPreDeleteCombat(combat, options) {
|
||||
static onPreDeleteCombat(combat, options, userId) {
|
||||
if (game.user.isGM) {
|
||||
combat.cleanItemUse();
|
||||
ChatUtility.removeChatMessageContaining(`<div data-combatid="${combat.id}" data-combatmessage="actor-turn-summary">`)
|
||||
@ -663,7 +661,7 @@ export class RdDCombat {
|
||||
/* -------------------------------------------- */
|
||||
static isEchecTotal(rollData) {
|
||||
if (!rollData.attackerRoll && rollData.ajustements.surprise.used) {
|
||||
return rollData.rolled.isEchec;
|
||||
return rollData.rolled.isEchec && rollData.rolled.code != 'notSign';
|
||||
}
|
||||
return rollData.rolled.isETotal;
|
||||
}
|
||||
@ -728,7 +726,6 @@ export class RdDCombat {
|
||||
surpriseDefenseur: this.defender.getSurprise(true),
|
||||
essais: {}
|
||||
};
|
||||
rollData.diviseurSignificative = this._getDiviseurSignificative(rollData);
|
||||
|
||||
if (this.attacker.isCreature()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData);
|
||||
@ -799,21 +796,19 @@ export class RdDCombat {
|
||||
}
|
||||
|
||||
// # utilisation esquive
|
||||
let esquiveUsage = 0;
|
||||
let esquive = this.defender.getCompetence("esquive");
|
||||
if (esquive) {
|
||||
esquiveUsage = this.defender.getItemUse(esquive._id);
|
||||
}
|
||||
const esquive = Misc.data(this.defender.getCompetence("esquive"));
|
||||
const corpsACorps = Misc.data(this.defender.getCompetence("Corps à corps"));
|
||||
const esquiveUsage = esquive ? this.defender.getItemUse(esquive._id) : 0;
|
||||
|
||||
const paramChatDefense = {
|
||||
passeArme: attackerRoll.passeArme,
|
||||
essais: attackerRoll.essais,
|
||||
defender: this.defender,
|
||||
attacker: this.attacker,
|
||||
defender: Misc.data(this.defender),
|
||||
attacker: Misc.data(this.attacker),
|
||||
attackerId: this.attackerId,
|
||||
esquiveUsage: esquiveUsage,
|
||||
defenderTokenId: this.defenderTokenId,
|
||||
mainsNues: attackerRoll.dmg.mortalite != 'mortel' && this.defender.getCompetence("Corps à corps"),
|
||||
mainsNues: attackerRoll.dmg.mortalite != 'mortel' && corpsACorps,
|
||||
armes: this._filterArmesParade(this.defender, attackerRoll.competence, attackerRoll.arme),
|
||||
diffLibre: attackerRoll.ajustements?.diffLibre?.value ?? 0,
|
||||
attaqueParticuliere: attackerRoll.particuliere,
|
||||
@ -851,7 +846,7 @@ export class RdDCombat {
|
||||
attackerId: this.attacker?.data._id,
|
||||
defenderId: this.defender?.data._id,
|
||||
defenderTokenId: this.defenderTokenId,
|
||||
defenderRoll: duplicate(defenderRoll),
|
||||
defenderRoll: defenderRoll,
|
||||
paramChatDefense: paramChatDefense,
|
||||
rollMode: true
|
||||
}
|
||||
@ -887,7 +882,7 @@ export class RdDCombat {
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(this.attacker.name),
|
||||
content: await renderTemplate('systems/foundryvtt-reve-de-dragon/templates/chat-demande-attaque-etotal.html', {
|
||||
attackerId: this.attackerId,
|
||||
attacker: this.attacker,
|
||||
attacker: Misc.data(this.attacker),
|
||||
defenderTokenId: this.defenderTokenId,
|
||||
essais: attackerRoll.essais
|
||||
})
|
||||
@ -958,20 +953,20 @@ export class RdDCombat {
|
||||
_prepareParade(attackerRoll, armeParade) {
|
||||
const compName = armeParade.data.competence;
|
||||
const armeAttaque = attackerRoll.arme;
|
||||
const parade = Misc.data(this.defender.getCompetence(compName));
|
||||
|
||||
let defenderRoll = {
|
||||
passeArme: attackerRoll.passeArme,
|
||||
diffLibre: attackerRoll.diffLibre,
|
||||
attackerRoll: attackerRoll,
|
||||
competence: this.defender.getCompetence(compName),
|
||||
competence: parade,
|
||||
arme: armeParade,
|
||||
surprise: this.defender.getSurprise(true),
|
||||
needParadeSignificative: ReglesOptionelles.isUsing('categorieParade') && RdDItemArme.needParadeSignificative(armeAttaque, armeParade),
|
||||
needResist: RdDItemArme.needArmeResist(armeAttaque, armeParade),
|
||||
carac: this.defender.data.data.carac,
|
||||
carac: Misc.templateData(this.defender).carac,
|
||||
show: {}
|
||||
};
|
||||
defenderRoll.diviseurSignificative = this._getDiviseurSignificative(defenderRoll);
|
||||
|
||||
if (this.defender.isCreature()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(defenderRoll);
|
||||
@ -980,24 +975,6 @@ export class RdDCombat {
|
||||
return defenderRoll;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_getDiviseurSignificative(defenderRoll) {
|
||||
let facteurSign = 1;
|
||||
if (defenderRoll.surprise == 'demi') {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (defenderRoll.needParadeSignificative) {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (RdDBonus.isDefenseAttaqueFinesse(defenderRoll)) {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (!ReglesOptionelles.isUsing('tripleSignificative')) {
|
||||
facteurSign = Math.min(facteurSign, 4);
|
||||
}
|
||||
return facteurSign;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_onParadeParticuliere(defenderRoll) {
|
||||
console.log("RdDCombat._onParadeParticuliere >>>", defenderRoll);
|
||||
@ -1033,7 +1010,7 @@ export class RdDCombat {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async esquive(attackerRoll) {
|
||||
let esquive = this.defender.getCompetence("esquive");
|
||||
const esquive = Misc.data(this.defender.getCompetence("esquive"));
|
||||
if (esquive == undefined) {
|
||||
ui.notifications.error(this.defender.name + " n'a pas de compétence 'esquive'");
|
||||
return;
|
||||
@ -1067,10 +1044,9 @@ export class RdDCombat {
|
||||
competence: competence,
|
||||
surprise: this.defender.getSurprise(true),
|
||||
surpriseDefenseur: this.defender.getSurprise(true),
|
||||
carac: this.defender.data.data.carac,
|
||||
carac: Misc.templateData(this.defender).carac,
|
||||
show: {}
|
||||
};
|
||||
rollData.diviseurSignificative = this._getDiviseurSignificative(rollData);
|
||||
|
||||
if (this.defender.isCreature()) {
|
||||
RdDItemCompetenceCreature.setRollDataCreature(rollData);
|
||||
@ -1136,7 +1112,7 @@ export class RdDCombat {
|
||||
resistance -= perteResistance;
|
||||
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
|
||||
defenderRoll.show.perteResistance = perteResistance;
|
||||
this.defender.updateEmbeddedEntity("OwnedItem", { _id: defenderRoll.arme._id, 'data.resistance': resistance });
|
||||
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'data.resistance': resistance }]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -1153,7 +1129,7 @@ export class RdDCombat {
|
||||
resistance -= dmg;
|
||||
defenderRoll.show.deteriorationArme = resistance <= 0 ? 'brise' : 'perte';
|
||||
defenderRoll.show.perteResistance = dmg;
|
||||
this.defender.updateEmbeddedEntity("OwnedItem", { _id: defenderRoll.arme._id, 'data.resistance': resistance });
|
||||
this.defender.updateEmbeddedDocuments('Item', [{ _id: defenderRoll.arme._id, 'data.resistance': resistance }]);
|
||||
}
|
||||
}
|
||||
// Si l'arme de parade n'est pas un bouclier, jet de désarmement (p.132)
|
||||
@ -1203,7 +1179,7 @@ export class RdDCombat {
|
||||
_computeImpactRecul(attaque) {
|
||||
const taille = this.defender.getTaille();
|
||||
const force = this.attacker.getForce();
|
||||
const dommages = attaque.arme.data.dommagesReels;
|
||||
const dommages = attaque.arme.data.dommagesReels ?? attaque.arme.data.dommages;
|
||||
return taille - (force + dommages);
|
||||
}
|
||||
|
||||
@ -1234,7 +1210,7 @@ export class RdDCombat {
|
||||
attackerId: this.attackerId,
|
||||
defenderTokenId: defenderTokenId,
|
||||
attackerRoll: attackerRoll,
|
||||
gmId: game.users.entities.find(u => u.isGM)?.id,
|
||||
gmId: Misc.connectedGMOrUser(),
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -1252,7 +1228,7 @@ export class RdDCombat {
|
||||
return true;
|
||||
}
|
||||
|
||||
let rolled = await RdDResolutionTable.roll(this.attacker.getReveActuel(), - Number(this.defender.data.data.carac.niveau.value));
|
||||
let rolled = await RdDResolutionTable.roll(this.attacker.getReveActuel(), - Number(Misc.templateData(this.defender).carac.niveau.value));
|
||||
|
||||
let message = {
|
||||
content: "Jet de points actuels de rêve à " + rolled.finalLevel + RdDResolutionTable.explain(rolled) + "<br>",
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* -------------------------------------------- */
|
||||
|
||||
import { DeDraconique } from "./de-draconique.js";
|
||||
import { DialogCreateSigneDraconique } from "./dialog-create-signedraconique.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
@ -11,9 +11,9 @@ import { RdDRollResolutionTable } from "./rdd-roll-resolution-table.js";
|
||||
import { RdDRollTables } from "./rdd-rolltables.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||
import { TMRType, 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 {
|
||||
@ -64,9 +64,11 @@ export class RdDCommands {
|
||||
descr: `Effectue un jet de dés dans la table de résolution. Exemples:
|
||||
<br><strong>/rdd</strong> ouvre la table de résolution
|
||||
<br><strong>/rdd 10 3</strong> effectue un jet 10 à +3
|
||||
<br><strong>/rdd 10 +2</strong> effectue un jet 10 à +2
|
||||
<br><strong>/rdd 15 -2</strong> effectue un jet 15 à -2
|
||||
<br><strong>/rdd 15 0 s</strong> effectue un jet 15 à 0, avec significative requise`
|
||||
<br><strong>/rdd 15 0 s</strong> effectue un jet 15 à 0, avec significative requise
|
||||
<br><strong>/rdd Vue Vigilance -2</strong> effectue un jet de Vue/Vigilance à -2 pour les tokens sélectionnés
|
||||
<br><strong>/rdd vol déser +2</strong> effectue un jet de Volonté/Survie en désert à +2 pour les tokens sélectionnés
|
||||
`
|
||||
});
|
||||
rddCommands.registerCommand({ path: ["/ddr"], func: (content, msg, params) => rddCommands.rollDeDraconique(msg), descr: "Lance un Dé Draconique" });
|
||||
|
||||
@ -81,6 +83,17 @@ export class RdDCommands {
|
||||
descr: `Affiche les heures de chance et de malchance selon l'heure de naissance donnée en argument. Exemples:
|
||||
<br><strong>/astro Lyre</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"
|
||||
});
|
||||
|
||||
game.system.rdd.commands = rddCommands;
|
||||
}
|
||||
}
|
||||
@ -164,16 +177,30 @@ export class RdDCommands {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
help(msg, table = undefined) {
|
||||
async help(msg) {
|
||||
this.help(msg, undefined);
|
||||
}
|
||||
async help(msg, table) {
|
||||
let list = []
|
||||
this._buildSubTableHelp(list, table || this.commandsTable);
|
||||
const messageAide = list.reduce((a, b) => a + '</li><li class="list-item">' + b);
|
||||
RdDCommands._chatAnswer(msg, `Commandes disponibles<ul class="alterne-list"><li class="list-item">${messageAide}</li></ul>`);
|
||||
|
||||
let html = await renderTemplate("systems/foundryvtt-reve-de-dragon/templates/settings/dialog-aide-commands.html", { commands: list });
|
||||
let d = new Dialog(
|
||||
{
|
||||
title: "Commandes disponibles dans le tchat",
|
||||
content: html,
|
||||
buttons: {},
|
||||
},
|
||||
{
|
||||
width: 600, height: 500,
|
||||
});
|
||||
|
||||
d.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _chatAnswer(msg, content) {
|
||||
msg.whisper = [game.user._id];
|
||||
msg.whisper = [game.user.id];
|
||||
msg.content = content;
|
||||
ChatMessage.create(msg);
|
||||
}
|
||||
@ -217,6 +244,27 @@ export class RdDCommands {
|
||||
await this.rollRdDNumeric(msg, carac, diff, significative);
|
||||
return;
|
||||
}
|
||||
|
||||
let actors = canvas.tokens.controlled.map(it => it.actor).filter(it => it);
|
||||
if (actors && actors.length > 0) {
|
||||
let length = params.length;
|
||||
let diff = Number(params[length - 1]);
|
||||
if (Number.isInteger(Number(diff))) {
|
||||
length--;
|
||||
}
|
||||
else {
|
||||
diff = 0;
|
||||
}
|
||||
const caracName = params[0];
|
||||
const compName = length > 1 ? params.slice(1, length).reduce((a, b) => `${a} ${b}`) : undefined;
|
||||
for (let actor of actors) {
|
||||
await actor.rollCaracCompetence(caracName, compName, diff);
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
ui.notifications.warn("Sélectionnez au moins un personnage pour lancer les dés")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -235,16 +283,14 @@ export class RdDCommands {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollDeDraconique(msg) {
|
||||
let ddr = new DeDraconique().evaluate();
|
||||
ddr.showDice = true;
|
||||
await RdDDice.showDiceSoNice(ddr);
|
||||
RdDCommands._chatAnswer(msg, `Lancer d'un Dé draconique: ${ddr.total}`);
|
||||
let ddr = await RdDDice.rollTotal("1dr + 7", { showDice:true });
|
||||
RdDCommands._chatAnswer(msg, `Lancer d'un Dé draconique: ${ddr}`);
|
||||
}
|
||||
|
||||
getTMRAleatoire(msg, params) {
|
||||
async getTMRAleatoire(msg, params) {
|
||||
if (params.length < 2) {
|
||||
let type = params[0];
|
||||
const tmr = TMRUtility.getTMRAleatoire(type ? (it => it.type == type) : (it => true));
|
||||
const tmr = await TMRUtility.getTMRAleatoire(type ? (it => it.type == type) : (it => true));
|
||||
RdDCommands._chatAnswer(msg, `Case aléatoire: ${tmr.coord} - ${tmr.label}`);
|
||||
}
|
||||
else {
|
||||
@ -276,5 +322,20 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ const typeDisplayName = {
|
||||
"ombre": "Ombre de Thanatos",
|
||||
"souffle": "Souffle de Dragon",
|
||||
"tete": "Tête de Dragon",
|
||||
"ingredient": "Ingrédient",
|
||||
"nourritureboisson": "Nourriture & boisson",
|
||||
"rencontresTMR": "Rencontre des TMR",
|
||||
"competencecreature": "Compétence de créature",
|
||||
"nombreastral": "Nombre astral",
|
||||
@ -36,14 +36,14 @@ export class RddCompendiumOrganiser {
|
||||
Hooks.on('renderCompendium', async (pack, html, data) => RddCompendiumOrganiser.onRenderCompendium(pack, html, data))
|
||||
}
|
||||
|
||||
static async onRenderCompendium(pack, html, data) {
|
||||
console.log('onRenderCompendium', pack, html, data);
|
||||
static async onRenderCompendium(compendium, html, data) {
|
||||
console.log('onRenderCompendium', compendium, html, data);
|
||||
let pack = compendium.collection
|
||||
if (pack.metadata.system === 'foundryvtt-reve-de-dragon') {
|
||||
const content = await pack.getContent();
|
||||
|
||||
html.find('.directory-item').each((i, element) => {
|
||||
let entity = content.find(it => it._id === element.dataset.entryId);
|
||||
|
||||
let entity = pack.get(element.dataset.documentId);
|
||||
if (entity?.entity === 'Actor' || entity?.entity === 'Item') {
|
||||
const typeName = typeDisplayName[entity.data.type] ?? Misc.upperFirst(entity.data.type);
|
||||
RddCompendiumOrganiser.insertEntityType(element, typeName);
|
||||
|
@ -1,10 +1,161 @@
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { SYSTEM_RDD } from "./constants.js";
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
function img(src) {
|
||||
return `<img src="${src}" class="dice-img" />`
|
||||
}
|
||||
|
||||
function iconHeure(heure) {
|
||||
if (heure < 10) {
|
||||
heure = '0' + heure;
|
||||
}
|
||||
return `systems/foundryvtt-reve-de-dragon/icons/heures/hd${heure}.webp`
|
||||
}
|
||||
const imagesHeures = [1, 2, 3, 4, 5, 6, 7, 9, 9, 10, 11, 12].map(it => iconHeure(it));
|
||||
|
||||
const imgSigneDragon = img(imagesHeures[4]);
|
||||
|
||||
/** De7 pour les jets de rencontre */
|
||||
export class De7 extends Die {
|
||||
/** @override */
|
||||
static DENOMINATION = "7";
|
||||
|
||||
static diceSoNiceData(system) {
|
||||
return {
|
||||
type: "d7",
|
||||
font: "HeuresDraconiques",
|
||||
fontScale: 0.7,
|
||||
labels: ['1', '2', '3', '4', '5', '6', 'd', '0'],
|
||||
system: system
|
||||
}
|
||||
}
|
||||
|
||||
constructor(termData) {
|
||||
termData.faces = 8;
|
||||
super(termData);
|
||||
}
|
||||
|
||||
async evaluate() {
|
||||
super.evaluate();
|
||||
this.explode("x=8");
|
||||
return this;
|
||||
}
|
||||
|
||||
get total() {
|
||||
return this.values.filter(it => it != 8).reduce(Misc.sum(), 0);
|
||||
}
|
||||
|
||||
static getResultLabel(result) {
|
||||
switch (result) {
|
||||
case 7: return imgSigneDragon;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/** DeDraconique pour le D8 sans limite avec 8=>0 */
|
||||
export class DeDraconique extends Die {
|
||||
static DENOMINATION = "r";
|
||||
|
||||
static diceSoNiceData(system) {
|
||||
return {
|
||||
type: "dr",
|
||||
font: "HeuresDraconiques",
|
||||
fontScale: 0.7,
|
||||
labels: ['1', '2', '3', '4', '5', '6', 'd', '0'],
|
||||
system: system
|
||||
}
|
||||
}
|
||||
|
||||
constructor(termData) {
|
||||
termData.faces = 8;
|
||||
super(termData);
|
||||
}
|
||||
|
||||
async evaluate() {
|
||||
super.evaluate();
|
||||
this.explode("x=7");
|
||||
return this;
|
||||
}
|
||||
|
||||
get total() {
|
||||
return this.values.filter(it => it != 8).reduce(Misc.sum(), 0);
|
||||
}
|
||||
|
||||
static getResultLabel(result) {
|
||||
switch (result) {
|
||||
case 7: return imgSigneDragon;
|
||||
case 8: return 0;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/** De 12 avec les heures */
|
||||
export class DeHeure extends Die {
|
||||
|
||||
/** @override */
|
||||
static DENOMINATION = "h";
|
||||
|
||||
static diceSoNiceData(system) {
|
||||
return {
|
||||
type: "dh",
|
||||
font: "HeuresDraconiques",
|
||||
labels: ['v', 'i', 'f', 'o', 'd', 'e', 'l', 's', 'p', 'a', 'r', 'c'],
|
||||
system: system
|
||||
}
|
||||
}
|
||||
|
||||
constructor(termData) {
|
||||
termData.faces = 12;
|
||||
super(termData);
|
||||
}
|
||||
|
||||
static getResultLabel(result) {
|
||||
return img(imagesHeures[result - 1]);
|
||||
}
|
||||
}
|
||||
|
||||
export class RdDDice {
|
||||
static init() {
|
||||
CONFIG.Dice.terms[De7.DENOMINATION] = De7;
|
||||
CONFIG.Dice.terms[DeDraconique.DENOMINATION] = DeDraconique;
|
||||
CONFIG.Dice.terms[DeHeure.DENOMINATION] = DeHeure;
|
||||
}
|
||||
|
||||
static async roll(formula, options = { showDice: false }) {
|
||||
const roll = new Roll(formula);
|
||||
await roll.evaluate({ async: true });
|
||||
if (options.showDice) {
|
||||
roll.showDice = options.showDice;
|
||||
}
|
||||
await RdDDice.show(roll, game.settings.get("core", "rollMode"));
|
||||
return roll;
|
||||
}
|
||||
|
||||
static async rollTotal(formula) {
|
||||
const roll = new Roll(formula);
|
||||
await roll.evaluate({ async: true });
|
||||
return roll.total;
|
||||
}
|
||||
|
||||
static async rollOneOf(array) {
|
||||
const roll = await RdDDice.rollTotal(`1d${array.length}`);
|
||||
return array[roll-1];
|
||||
}
|
||||
|
||||
static diceSoNiceReady(dice3d) {
|
||||
for (const system of Object.keys(dice3d.DiceFactory.systems)) {
|
||||
dice3d.addDicePreset(De7.diceSoNiceData(system));
|
||||
dice3d.addDicePreset(DeDraconique.diceSoNiceData(system));
|
||||
dice3d.addDicePreset(DeHeure.diceSoNiceData(system));
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async show(roll, rollMode = undefined) {
|
||||
if (roll.showDice || game.settings.get("foundryvtt-reve-de-dragon", "dice-so-nice") == true) {
|
||||
if (roll.showDice || game.settings.get(SYSTEM_RDD, "dice-so-nice") == true) {
|
||||
await this.showDiceSoNice(roll, rollMode);
|
||||
}
|
||||
return roll;
|
||||
@ -26,7 +177,7 @@ export class RdDDice {
|
||||
whisper = ChatUtility.getUsers(user => user.active);
|
||||
break;
|
||||
case "selfroll":
|
||||
whisper = [game.user._id];
|
||||
whisper = [game.user.id];
|
||||
break;
|
||||
}
|
||||
await game.dice3d.showForRoll(roll, game.user, true, whisper, blind);
|
||||
|
76
module/rdd-herbes.js
Normal file
@ -0,0 +1,76 @@
|
||||
/* -------------------------------------------- */
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -9,12 +9,12 @@ export class RdDHotbar {
|
||||
*/
|
||||
static initDropbar( ) {
|
||||
|
||||
Hooks.on("hotbarDrop", async (bar, data, slot) => {
|
||||
Hooks.on("hotbarDrop", async (bar, documentData, slot) => {
|
||||
// Create item macro if rollable item - weapon, spell, prayer, trait, or skill
|
||||
if (data.type == "Item") {
|
||||
if (data.data.type != "arme" && data.data.type != "competence" )
|
||||
if (documentData.type == "Item") {
|
||||
if (documentData.data.type != "arme" && documentData.data.type != "competence" )
|
||||
return
|
||||
let item = data.data
|
||||
let item = documentData.data
|
||||
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));
|
||||
if (!macro) {
|
||||
@ -28,9 +28,9 @@ export class RdDHotbar {
|
||||
game.user.assignHotbarMacro(macro, slot);
|
||||
}
|
||||
// Create a macro to open the actor sheet of the actor dropped on the hotbar
|
||||
else if (data.type == "Actor") {
|
||||
let actor = game.actors.get(data.id);
|
||||
let command = `game.actors.get("${data.id}").sheet.render(true)`
|
||||
else if (documentData.type == "Actor") {
|
||||
let actor = game.actors.get(documentData.id);
|
||||
let command = `game.actors.get("${documentData.id}").sheet.render(true)`
|
||||
let macro = game.macros.entities.find(m => (m.name === actor.name) && (m.command === command));
|
||||
if (!macro) {
|
||||
macro = await Macro.create({
|
||||
@ -43,9 +43,9 @@ export class RdDHotbar {
|
||||
}
|
||||
}
|
||||
// Create a macro to open the journal sheet of the journal dropped on the hotbar
|
||||
else if (data.type == "JournalEntry") {
|
||||
let journal = game.journal.get(data.id);
|
||||
let command = `game.journal.get("${data.id}").sheet.render(true)`
|
||||
else if (documentData.type == "JournalEntry") {
|
||||
let journal = game.journal.get(documentData.id);
|
||||
let command = `game.journal.get("${documentData.id}").sheet.render(true)`
|
||||
let macro = game.macros.entities.find(m => (m.name === journal.name) && (m.command === command));
|
||||
if (!macro) {
|
||||
macro = await Macro.create({
|
||||
|
@ -22,13 +22,16 @@ import { RdDTokenHud } from "./rdd-token-hud.js";
|
||||
import { RdDCommands } from "./rdd-commands.js";
|
||||
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js";
|
||||
import { ChatUtility } from "./chat-utility.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { StatusEffects } from "./status-effects.js";
|
||||
import { RddCompendiumOrganiser } from "./rdd-compendium-organiser.js";
|
||||
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||
import { RdDHotbar } from "./rdd-hotbar-drop.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 { RdDSigneDraconiqueItemSheet } from "./item-signedraconique-sheet.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
@ -116,6 +119,20 @@ Hooks.once("init", async function () {
|
||||
default: true,
|
||||
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
|
||||
@ -125,15 +142,17 @@ Hooks.once("init", async function () {
|
||||
};
|
||||
|
||||
/* -------------------------------------------- */
|
||||
game.socket.on("system.foundryvtt-reve-de-dragon", data => {
|
||||
RdDUtility.onSocketMesssage(data);
|
||||
RdDCombat.onSocketMessage(data);
|
||||
ChatUtility.onSocketMessage(data);
|
||||
game.socket.on("system.foundryvtt-reve-de-dragon", sockmsg => {
|
||||
RdDUtility.onSocketMesssage(sockmsg);
|
||||
RdDCombat.onSocketMessage(sockmsg);
|
||||
ChatUtility.onSocketMessage(sockmsg);
|
||||
RdDActor.onSocketMessage(sockmsg);
|
||||
});
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// Define custom Entity classes
|
||||
CONFIG.Actor.entityClass = RdDActor;
|
||||
CONFIG.Actor.documentClass = RdDActor;
|
||||
CONFIG.Item.documentClass = RdDItem;
|
||||
CONFIG.RDD = {
|
||||
resolutionTable: RdDResolutionTable.resolutionTable,
|
||||
carac_array: RdDUtility.getCaracArray(),
|
||||
@ -149,17 +168,24 @@ Hooks.once("init", async function () {
|
||||
Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorVehiculeSheet, { types: ["vehicule"], makeDefault: true });
|
||||
Actors.registerSheet("foundryvtt-reve-de-dragon", RdDActorEntiteSheet, { types: ["entite"], makeDefault: true });
|
||||
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 });
|
||||
CONFIG.Combat.entityClass = RdDCombatManager;
|
||||
CONFIG.Combat.documentClass = RdDCombatManager;
|
||||
|
||||
// préparation des différents modules
|
||||
ReglesOptionelles.init();
|
||||
RdDUtility.init();
|
||||
RdDDice.init();
|
||||
RdDCommands.init();
|
||||
RdDCombat.init();
|
||||
RdDCombatManager.init(),
|
||||
RdDCombatManager.init();
|
||||
RdDTokenHud.init();
|
||||
RdDActor.init();
|
||||
RddCompendiumOrganiser.init();
|
||||
ReglesOptionelles.init();
|
||||
EffetsDraconiques.init()
|
||||
TMRUtility.init();
|
||||
TMRRencontres.init();
|
||||
@ -171,7 +197,7 @@ function messageDeBienvenue() {
|
||||
if (game.user.isGM) {
|
||||
ChatUtility.removeChatMessageContaining('<div id="message-bienvenue-rdd">');
|
||||
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>
|
||||
<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>
|
||||
@ -179,12 +205,13 @@ function messageDeBienvenue() {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
/* -------------------------------------------- */
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
/* -------------------------------------------- */
|
||||
Hooks.once("ready", function () {
|
||||
|
||||
StatusEffects.onReady();
|
||||
RdDHerbes.initializeHerbes();
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Affiche/Init le calendrier */
|
||||
@ -202,7 +229,7 @@ Hooks.once("ready", function () {
|
||||
ui.notifications.info("Attention ! Vous n'êtes connecté à aucun personnage !");
|
||||
ChatMessage.create({
|
||||
content: "<b>ATTENTION</b> Le joueur " + game.user.name + " n'est connecté à aucun personnage !",
|
||||
user: game.user._id
|
||||
user: game.user.id
|
||||
});
|
||||
//whisper: [ ChatMessage.getWhisperRecipients("GM") ] } );
|
||||
}
|
||||
@ -211,7 +238,12 @@ Hooks.once("ready", function () {
|
||||
});
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT Initialization */
|
||||
/* Dice-so-nice ready */
|
||||
/* -------------------------------------------- */
|
||||
Hooks.once('diceSoNiceReady', (dice3d) => RdDDice.diceSoNiceReady(dice3d));
|
||||
|
||||
/* -------------------------------------------- */
|
||||
/* Foundry VTT chat message */
|
||||
/* -------------------------------------------- */
|
||||
Hooks.on("chatMessage", (html, content, msg) => {
|
||||
if (content[0] == '/') {
|
||||
@ -224,8 +256,3 @@ Hooks.on("chatMessage", (html, content, msg) => {
|
||||
return true;
|
||||
});
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
Hooks.on("renderChatMessage", async (app, html, msg) => {
|
||||
RdDUtility.onRenderChatMessage(app, html, msg);
|
||||
});
|
||||
|
@ -1,14 +1,17 @@
|
||||
import { Grammar } from "./grammar.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',
|
||||
'alta', 'par', 'pir', 'zor', 'zir', 'de', 'pol', 'tran', 'no', 'la','al' , 'pul', 'one', 'ner', 'nur' ];
|
||||
'alta', 'par', 'pir', 'zor', 'zir', 'de', 'pol', 'tran', 'no', 'la', 'al' , 'pul', 'one', 'ner', 'nur', 'mac', 'mery',
|
||||
'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 {
|
||||
|
||||
static getName( msg, params ) {
|
||||
let name = Misc.upperFirst( Misc.rollOneOf(words) + Misc.rollOneOf(words) )
|
||||
static async getName( msg, params ) {
|
||||
let name = Misc.upperFirst( await RdDDice.rollOneOf(words) + await RdDDice.rollOneOf(words) )
|
||||
//console.log(name);
|
||||
ChatMessage.create( { content: `Nom : ${name}`, whisper: ChatMessage.getWhisperRecipients("GM") } );
|
||||
}
|
||||
|
@ -51,10 +51,8 @@ const reussites = [
|
||||
{ code: "error", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: true, isETotal: true, ptTache: 0, ptQualite: 0, quality: "Jet de dés invalide", condition: (target, roll) => (roll <= 0 || roll > 100) }
|
||||
];
|
||||
|
||||
const reussiteInsuffisante = { code: "notSign", isPart: false, isSign: false, isSuccess: false, isEchec: true, isEPart: false, isETotal: false, ptTache: 0, ptQualite: -2, quality: "Réussite insuffisante", condition: (target, roll) => false }
|
||||
/* -------------------------------------------- */
|
||||
const reussiteSignificative = reussites.find(r => r.code == "sign");
|
||||
const reussiteNormale = reussites.find(r => r.code == "norm");
|
||||
const echecNormal = reussites.find(r => r.code == "echec");
|
||||
const caracMaximumResolution = 60;
|
||||
/* -------------------------------------------- */
|
||||
export class RdDResolutionTable {
|
||||
@ -115,7 +113,7 @@ export class RdDResolutionTable {
|
||||
this._updateChancesFactor(chances, diviseur);
|
||||
chances.showDice = showDice;
|
||||
|
||||
let rolled = await this.rollChances(chances);
|
||||
let rolled = await this.rollChances(chances, diviseur);
|
||||
rolled.caracValue = caracValue;
|
||||
rolled.finalLevel = finalLevel;
|
||||
rolled.bonus = bonus;
|
||||
@ -150,12 +148,9 @@ export class RdDResolutionTable {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async rollChances(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), { overwrite: true });
|
||||
static async rollChances(chances, diviseur) {
|
||||
chances.roll = await RdDDice.rollTotal("1d100", {showDice:chances.showDice});
|
||||
mergeObject(chances, this.computeReussite(chances, chances.roll, diviseur), { overwrite: true });
|
||||
return chances;
|
||||
}
|
||||
|
||||
@ -216,8 +211,12 @@ export class RdDResolutionTable {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static computeReussite(chances, roll) {
|
||||
return reussites.find(x => x.condition(chances, roll));
|
||||
static computeReussite(chances, roll, diviseur) {
|
||||
const reussite = reussites.find(x => x.condition(chances, roll));
|
||||
if (diviseur > 1 && reussite.code == 'norm') {
|
||||
return reussiteInsuffisante;
|
||||
}
|
||||
return reussite;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -269,8 +268,8 @@ export class RdDResolutionTable {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static buildHTMLResults(caracValue, levelValue) {
|
||||
if ( caracValue == undefined || isNaN(caracValue )) caracValue = 10;
|
||||
if ( levelValue == undefined || isNaN(levelValue )) levelValue = 0;
|
||||
if (caracValue == undefined || isNaN(caracValue)) caracValue = 10;
|
||||
if (levelValue == undefined || isNaN(levelValue)) levelValue = 0;
|
||||
|
||||
let cell = this.computeChances(caracValue, levelValue);
|
||||
cell.epart = cell.epart > 99 ? 'N/A' : cell.epart;
|
||||
@ -278,14 +277,14 @@ export class RdDResolutionTable {
|
||||
cell.score = Math.min(cell.score, 99);
|
||||
|
||||
return `
|
||||
<span class="table-proba-reussite competence-label">
|
||||
Particulière: <span class="rdd-roll-part">${cell.part}</span>
|
||||
- Significative: <span class="rdd-roll-sign">${cell.sign}</span>
|
||||
- Réussite: <span class="rdd-roll-norm">${cell.score}</span>
|
||||
- Echec Particulier: <span class="rdd-roll-epart">${cell.epart}</span>
|
||||
- Echec Total: <span class="rdd-roll-etotal">${cell.etotal}</span>
|
||||
</span>
|
||||
`
|
||||
<span class="table-proba-reussite competence-label">
|
||||
Particulière: <span class="rdd-roll-part">${cell.part}</span>
|
||||
- Significative: <span class="rdd-roll-sign">${cell.sign}</span>
|
||||
- Réussite: <span class="rdd-roll-norm">${cell.score}</span>
|
||||
- Echec Particulier: <span class="rdd-roll-epart">${cell.epart}</span>
|
||||
- Echec Total: <span class="rdd-roll-etotal">${cell.etotal}</span>
|
||||
</span>
|
||||
`
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -7,17 +7,23 @@ export class RdDEncaisser extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, actor) {
|
||||
// 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 = {
|
||||
title: "Jet d'Encaissement",
|
||||
content: html,
|
||||
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") }
|
||||
},
|
||||
buttons: buttons,
|
||||
default: "coupMortel"
|
||||
}
|
||||
|
||||
|
||||
let dialogOptions = {
|
||||
classes: ["rdddialog"],
|
||||
width: 320,
|
||||
@ -32,13 +38,15 @@ export class RdDEncaisser extends Dialog {
|
||||
this.encaisserSpecial = "aucun";
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
performEncaisser(html, mortalite = "mortel") {
|
||||
performEncaisser(mortalite) {
|
||||
this.actor.encaisserDommages({
|
||||
dmg:{
|
||||
dmg: {
|
||||
total: Number(this.modifier),
|
||||
encaisserSpecial: this.encaisserSpecial,
|
||||
loc: { result: 0, label: "Corps" },
|
||||
loc: { result: 0, label: "" },
|
||||
mortalite: mortalite
|
||||
}
|
||||
});
|
||||
|
@ -8,22 +8,27 @@ import { Misc } from "./misc.js";
|
||||
export class RdDRollDialogEthylisme extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
constructor(html, rollData, actor) {
|
||||
|
||||
let myButtons = {
|
||||
rollButton: { label: "Test d'éthylisme", callback: html => this.actor.performEthylisme(this.rollData) }
|
||||
};
|
||||
|
||||
constructor(html, rollData, actor, onRoll) {
|
||||
// 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 }
|
||||
let dialogConf = {
|
||||
title: "Test d'éthylisme",
|
||||
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 }
|
||||
super(dialogConf, dialogOptions)
|
||||
|
||||
//console.log("ETH", rollData);
|
||||
this.onRoll = onRoll;
|
||||
this.rollData = rollData;
|
||||
this.actor = actor;
|
||||
}
|
||||
|
||||
async onButton(html) {
|
||||
this.onRoll(this.rollData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
activateListeners(html) {
|
||||
super.activateListeners(html);
|
||||
@ -31,28 +36,27 @@ export class RdDRollDialogEthylisme extends Dialog {
|
||||
this.bringToTop(); // Ensure top level
|
||||
// Get the rollData stuff
|
||||
var rollData = this.rollData;
|
||||
|
||||
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));
|
||||
}
|
||||
var dialog = this;
|
||||
|
||||
// Setup everything onload
|
||||
$(function () {
|
||||
$("#forceAlcool").val(Misc.toInt(rollData.forceAlcool));
|
||||
updateRollResult(rollData);
|
||||
dialog.updateRollResult();
|
||||
});
|
||||
|
||||
// Update !
|
||||
html.find('#forceAlcool').change((event) => {
|
||||
rollData.forceAlcool = Misc.toInt(event.currentTarget.value); // Update the selected bonus/malus
|
||||
updateRollResult(rollData);
|
||||
dialog.updateRollResult();
|
||||
});
|
||||
}
|
||||
async updateRollResult() {
|
||||
|
||||
this.rollData.finalLevel = Number(this.rollData.etat) + Number(this.rollData.forceAlcool) + this.rollData.diffNbDoses;
|
||||
|
||||
// Mise à jour valeurs
|
||||
$("#roll-param").text(this.rollData.vie + " / " + Misc.toSignedString(this.rollData.finalLevel));
|
||||
$(".table-resolution").remove();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,12 +1,12 @@
|
||||
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { RdDItemCompetence } from "./item-competence.js";
|
||||
import { RdDItemMeditation } from "./item-meditation.js";
|
||||
import { RdDItemSort } from "./item-sort.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDBonus } from "./rdd-bonus.js";
|
||||
import { RdDCarac } from "./rdd-carac.js";
|
||||
import { RdDResolutionTable } from "./rdd-resolution-table.js";
|
||||
import { ReglesOptionelles } from "./regles-optionelles.js";
|
||||
|
||||
/**
|
||||
* Extend the base Dialog entity to select roll parameters
|
||||
@ -64,13 +64,32 @@ export class RdDRoll extends Dialog {
|
||||
canClose: true
|
||||
};
|
||||
|
||||
|
||||
mergeObject(rollData, defaultRollData, { recursive: true, overwrite: false });
|
||||
if (rollData.forceCarac) {
|
||||
rollData.carac = rollData.forceCarac;
|
||||
}
|
||||
rollData.diviseurSignificative = RdDRoll.getDiviseurSignificative(rollData);
|
||||
|
||||
RollDataAjustements.calcul(rollData, actor);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
static getDiviseurSignificative(rollData) {
|
||||
let facteurSign = 1;
|
||||
if (rollData.surprise == 'demi') {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (rollData.needParadeSignificative) {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (RdDBonus.isDefenseAttaqueFinesse(rollData)) {
|
||||
facteurSign *= 2;
|
||||
}
|
||||
if (!ReglesOptionelles.isUsing('tripleSignificative')) {
|
||||
facteurSign = Math.min(facteurSign, 4);
|
||||
}
|
||||
return facteurSign;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static _ensureCorrectActions(actions) {
|
||||
@ -122,7 +141,6 @@ export class RdDRoll extends Dialog {
|
||||
await RdDResolutionTable.rollData(this.rollData);
|
||||
console.log("RdDRoll -=>", this.rollData, this.rollData.rolled);
|
||||
this.actor.setRollWindowsOpened(false);
|
||||
|
||||
if (action.callbacks)
|
||||
for (let callback of action.callbacks) {
|
||||
if (callback.condition == undefined || callback.condition(this.rollData)) {
|
||||
@ -141,14 +159,17 @@ export class RdDRoll extends Dialog {
|
||||
|
||||
function onLoad() {
|
||||
let rollData = dialog.rollData;
|
||||
console.log(rollData);
|
||||
// Update html, according to data
|
||||
if (rollData.competence) {
|
||||
const defaut_carac = Misc.templateData(rollData.competence).defaut_carac;
|
||||
// Set the default carac from the competence item
|
||||
rollData.selectedCarac = rollData.carac[rollData.competence.data.defaut_carac];
|
||||
$("#carac").val(rollData.competence.data.defaut_carac);
|
||||
rollData.selectedCarac = rollData.carac[defaut_carac];
|
||||
$("#carac").val(defaut_carac);
|
||||
}
|
||||
if (rollData.selectedSort) {
|
||||
$("#draconic").val(rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
|
||||
dialog.setSelectedSort(rollData.selectedSort);
|
||||
$(".draconic").val(rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
|
||||
}
|
||||
RdDItemSort.setCoutReveReel(rollData.selectedSort);
|
||||
$("#diffLibre").val(Misc.toInt(rollData.diffLibre));
|
||||
@ -173,17 +194,20 @@ export class RdDRoll extends Dialog {
|
||||
this.rollData.selectedCarac = this.rollData.carac[caracKey]; // Update the selectedCarac
|
||||
this.updateRollResult();
|
||||
});
|
||||
html.find('#draconic').change((event) => {
|
||||
html.find('.roll-draconic').change((event) => {
|
||||
let draconicKey = Misc.toInt(event.currentTarget.value);
|
||||
this.rollData.competence = this.rollData.draconicList[draconicKey]; // Update the selectedCarac
|
||||
this.updateRollResult();
|
||||
});
|
||||
html.find('#sort').change((event) => {
|
||||
html.find('.roll-sort').change((event) => {
|
||||
let sortKey = Misc.toInt(event.currentTarget.value);
|
||||
this.rollData.selectedSort = this.rollData.sortList[sortKey]; // Update the selectedCarac
|
||||
this.rollData.bonus = RdDItemSort.getCaseBonus(this.rollData.selectedSort, this.rollData.tmr.coord);
|
||||
RdDItemSort.setCoutReveReel(this.rollData.selectedSort);
|
||||
$("#draconic").val(this.rollData.selectedSort.data.listIndex); // Uniquement a la selection du sort, pour permettre de changer
|
||||
this.setSelectedSort(this.rollData.sortList[sortKey]);
|
||||
this.updateRollResult();
|
||||
$("#diffLibre").val(this.rollData.diffLibre);
|
||||
});
|
||||
html.find('.roll-signedraconique').change((event) => {
|
||||
let sortKey = Misc.toInt(event.currentTarget.value);
|
||||
this.setSelectedSigneDraconique(this.rollData.signes[sortKey]);
|
||||
this.updateRollResult();
|
||||
});
|
||||
html.find('#ptreve-variable').change((event) => {
|
||||
@ -196,16 +220,18 @@ export class RdDRoll extends Dialog {
|
||||
this.rollData.dmg.mortalite = event.currentTarget.checked ? "non-mortel" : "mortel";
|
||||
this.updateRollResult();
|
||||
});
|
||||
html.find('#tactique-combat').change((event) => {
|
||||
this.rollData.tactique = event.currentTarget.value;
|
||||
html.find('.cuisine-proportions').change((event) => {
|
||||
this.rollData.proportions = Number(event.currentTarget.value);
|
||||
this.updateRollResult();
|
||||
});
|
||||
html.find('#useMalusSurenc').change((event) => {
|
||||
this.rollData.useMalusSurenc = event.currentTarget.checked;
|
||||
html.find('.select-by-name').change((event) => {
|
||||
const attribute = event.currentTarget.attributes['name'].value;
|
||||
this.rollData[attribute] = event.currentTarget.value;
|
||||
this.updateRollResult();
|
||||
});
|
||||
html.find('#useMalusEncTotal').change((event) => {
|
||||
this.rollData.useMalusEncTotal = event.currentTarget.checked;
|
||||
html.find('.checkbox-by-name').change((event) => {
|
||||
const attribute = event.currentTarget.attributes['name'].value;
|
||||
this.rollData[attribute] = event.currentTarget.checked;
|
||||
this.updateRollResult();
|
||||
});
|
||||
html.find('.imgAppelAuMoral').click((event) => { /* l'appel au moral, qui donne un bonus de +1 */
|
||||
@ -232,6 +258,35 @@ 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() {
|
||||
let rollData = this.rollData;
|
||||
@ -243,12 +298,7 @@ export class RdDRoll extends Dialog {
|
||||
let dmgText = Misc.toSignedString(rollData.dmg.total);
|
||||
|
||||
if (rollData.coupsNonMortels) {
|
||||
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))
|
||||
dmgText = `(${dmgText}) non-mortel`
|
||||
}
|
||||
|
||||
RollDataAjustements.calcul(rollData, this.actor);
|
||||
@ -260,9 +310,9 @@ export class RdDRoll extends Dialog {
|
||||
HtmlUtility._showControlWhen($("#ajust-astrologique"), RdDResolutionTable.isAjustementAstrologique(rollData));
|
||||
|
||||
// Mise à jour valeurs
|
||||
$("#compdialogTitle").text(this._getTitle(rollData));
|
||||
$(".dialog-roll-title").text(this._getTitle(rollData));
|
||||
$('#coupsNonMortels').prop('checked', rollData.coupsNonMortels);
|
||||
$("#dmg-arme-actor").text(dmgText);
|
||||
$(".dmg-arme-actor").text(dmgText);
|
||||
$('.table-ajustement').remove();
|
||||
$(".table-resolution").remove();
|
||||
$(".table-proba-reussite").remove();
|
||||
@ -274,7 +324,7 @@ export class RdDRoll extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async buildAjustements(rollData) {
|
||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/dialog-roll-ajustements.html`, rollData);
|
||||
const html = await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.html`, rollData);
|
||||
return html;
|
||||
}
|
||||
|
||||
@ -328,9 +378,9 @@ export class RdDRoll extends Dialog {
|
||||
const niveau = Misc.toSignedString(rollData.competence.data.niveau);
|
||||
if (compName == carac) {
|
||||
// cas des créatures
|
||||
return carac + " " + niveau
|
||||
return carac + " Niveau " + niveau
|
||||
}
|
||||
const armeTitle = (rollData.arme) ? " (" + rollData.arme.name + ") " : "";
|
||||
return carac + "/" + compName + armeTitle + " " + niveau
|
||||
return carac + "/" + compName + armeTitle + " Niveau " + niveau
|
||||
}
|
||||
}
|
||||
|
@ -5,33 +5,23 @@ export class RdDRollTables {
|
||||
const pack = game.packs.get("foundryvtt-reve-de-dragon.tables-diverses");
|
||||
const index = await pack.getIndex();
|
||||
const entry = index.find(e => e.name === tableName);
|
||||
const table = await pack.getEntity(entry._id);
|
||||
const table = await pack.getDocument(entry._id);
|
||||
const draw = await table.draw({ displayChat: toChat, rollMode: "gmroll"});
|
||||
console.log("RdDRollTables", tableName, toChat, ":", draw);
|
||||
return draw;
|
||||
return draw.results.length > 0 ? draw.results[0] : undefined;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async drawItemFromRollTable(tableName, toChat) {
|
||||
const draw = await RdDRollTables.genericGetTableResult(tableName, toChat);
|
||||
const drawnItemRef = draw.results.length > 0 ? draw.results[0] : undefined;
|
||||
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 drawItemFromRollTable(tableName, toChat = false) {
|
||||
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
|
||||
const pack = game.packs.get(drawResult.data.collection);
|
||||
return await pack.getDocument(drawResult.data.resultId);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async drawTextFromRollTable(tableName, toChat) {
|
||||
const draw = await RdDRollTables.genericGetTableResult(tableName, toChat);
|
||||
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;
|
||||
const drawResult = await RdDRollTables.genericGetTableResult(tableName, toChat);
|
||||
return drawResult.data.text;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -10,8 +10,10 @@ import { Poetique } from "./poetique.js";
|
||||
import { EffetsDraconiques } from "./tmr/effets-draconiques.js";
|
||||
import { PixiTMR } from "./tmr/pixi-tmr.js";
|
||||
import { Draconique } from "./tmr/draconique.js";
|
||||
import { Grammar } from "./grammar.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 {
|
||||
@ -40,15 +42,16 @@ export class RdDTMRDialog extends Dialog {
|
||||
const dialogOptions = {
|
||||
classes: ["tmrdialog"],
|
||||
width: 920, height: 980,
|
||||
'z-index': 20
|
||||
'z-index': 40
|
||||
}
|
||||
super(dialogConf, dialogOptions);
|
||||
|
||||
|
||||
this.tmrdata = duplicate(tmrData);
|
||||
this.actor = actor;
|
||||
this.actor.tmrApp = this; // reference this app in the actor structure
|
||||
this.viewOnly = tmrData.mode == "visu"
|
||||
this.fatigueParCase = this.viewOnly ? 0 : this.actor.getTMRFatigue();
|
||||
this.fatigueParCase = this.viewOnly || !ReglesOptionelles.isUsing("appliquer-fatigue") ? 0 : this.actor.getTMRFatigue();
|
||||
this.cumulFatigue = 0;
|
||||
this.loadRencontres();
|
||||
this.loadSortsReserve();
|
||||
@ -58,24 +61,29 @@ export class RdDTMRDialog extends Dialog {
|
||||
this.pixiApp = new PIXI.Application({ width: 720, height: 860 });
|
||||
|
||||
this.pixiTMR = new PixiTMR(this, this.pixiApp);
|
||||
this.cacheTMR = (game.user.isGM) ? false : actor.isTMRCache();
|
||||
|
||||
this.callbacksOnAnimate = [];
|
||||
if (!this.viewOnly) {
|
||||
this.actor.setStatusDemiReve(true);
|
||||
this._tellToGM(this.actor.name + " monte dans les terres médianes (" + tmrData.mode + ")");
|
||||
}
|
||||
|
||||
// load the texture we need
|
||||
this.pixiTMR.load((loader, resources) => this.createPixiSprites());
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
loadCasesSpeciales() {
|
||||
this.casesSpeciales = this.actor.data.items.filter(item => Draconique.isCaseTMR(item));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
loadSortsReserve() {
|
||||
this.sortsReserves = Misc.data(this.actor).data.reve.reserve.list;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
loadRencontres() {
|
||||
this.rencontresExistantes = this.actor.getTMRRencontres();
|
||||
}
|
||||
@ -83,9 +91,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
/* -------------------------------------------- */
|
||||
createPixiSprites() {
|
||||
EffetsDraconiques.carteTmr.createSprite(this.pixiTMR);
|
||||
|
||||
this.updateTokens();
|
||||
|
||||
this.demiReve = this._tokenDemiReve();
|
||||
this._updateDemiReve();
|
||||
}
|
||||
@ -130,18 +136,50 @@ export class RdDTMRDialog extends Dialog {
|
||||
return EffetsDraconiques.rencontre.token(this.pixiTMR, rencontre, () => rencontre.coord);
|
||||
}
|
||||
_tokenCaseSpeciale(casetmr) {
|
||||
const draconique = Draconique.get(casetmr.data.specific);
|
||||
return draconique?.token(this.pixiTMR, casetmr, () => casetmr.data.coord);
|
||||
const caseData = Misc.data(casetmr);
|
||||
const draconique = Draconique.get(caseData.data.specific);
|
||||
return draconique?.token(this.pixiTMR, caseData, () => caseData.data.coord);
|
||||
}
|
||||
_tokenSortEnReserve(sortEnReserve) {
|
||||
return EffetsDraconiques.sortReserve.token(this.pixiTMR, sortEnReserve.sort, () => sortEnReserve.coord);
|
||||
}
|
||||
|
||||
_tokenDemiReve() {
|
||||
return EffetsDraconiques.demiReve.token(this.pixiTMR, this.actor, () => Misc.data(this.actor).data.reve.tmrpos.coord);
|
||||
const actorData = Misc.data(this.actor);
|
||||
return EffetsDraconiques.demiReve.token(this.pixiTMR, actorData, () => actorData.data.reve.tmrpos.coord);
|
||||
}
|
||||
|
||||
_updateDemiReve() {
|
||||
this._setTokenPosition(this.demiReve);
|
||||
this.notifierResonanceSigneDraconique(this._getActorCoord());
|
||||
|
||||
if (!this.cacheTMR) {
|
||||
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();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -151,41 +189,72 @@ export class RdDTMRDialog extends Dialog {
|
||||
document.getElementById("tmrrow1").insertCell(0).append(this.pixiApp.view);
|
||||
|
||||
if (this.viewOnly) {
|
||||
html.find('#lancer-sort').remove();
|
||||
}
|
||||
else {
|
||||
// Roll Sort
|
||||
html.find('#lancer-sort').click((event) => {
|
||||
this.actor.rollUnSort(Misc.data(this.actor).data.reve.tmrpos.coord);
|
||||
});
|
||||
}
|
||||
if (this.viewOnly) {
|
||||
html.find('.lancer-sort').remove();
|
||||
html.find('.lire-signe-draconique').remove();
|
||||
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
|
||||
let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1)
|
||||
- this.actor.countMonteeLaborieuse();
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
let reveCout = ((this.tmrdata.isRapide && !EffetsDraconiques.isDeplacementAccelere(this.actor)) ? -2 : -1) - this.actor.countMonteeLaborieuse();
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
}
|
||||
await this.actor.reveActuelIncDec(reveCout);
|
||||
|
||||
// Le reste...
|
||||
this.updateValuesDisplay();
|
||||
let tmr = TMRUtility.getTMR(Misc.data(this.actor).data.reve.tmrpos.coord);
|
||||
let tmr = TMRUtility.getTMR(this._getActorCoord());
|
||||
await this.manageRencontre(tmr, () => {
|
||||
this.postRencontre(tmr);
|
||||
});
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
updateValuesDisplay() {
|
||||
let ptsreve = document.getElementById("tmr-pointsreve-value");
|
||||
async 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");
|
||||
ptsreve.innerHTML = actorData.data.reve.reve.value;
|
||||
|
||||
let tmrpos = document.getElementById("tmr-pos");
|
||||
let tmr = TMRUtility.getTMR(actorData.data.reve.tmrpos.coord);
|
||||
tmrpos.innerHTML = actorData.data.reve.tmrpos.coord + " (" + tmr.label + ")";
|
||||
if (this.cacheTMR) {
|
||||
tmrpos.innerHTML = '?? (' + TMRUtility.getTMRType(coord) + ')';
|
||||
} else {
|
||||
tmrpos.innerHTML = coord + " (" + TMRUtility.getTMRLabel(coord) + ")";
|
||||
}
|
||||
|
||||
let etat = document.getElementById("tmr-etatgeneral-value");
|
||||
etat.innerHTML = this.actor.getEtatGeneral();
|
||||
@ -193,9 +262,11 @@ export class RdDTMRDialog extends Dialog {
|
||||
let refoulement = document.getElementById("tmr-refoulement-value");
|
||||
refoulement.innerHTML = actorData.data.reve.refoulement.value;
|
||||
|
||||
let fatigueItem = document.getElementById("tmr-fatigue-table");
|
||||
//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>";
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
let fatigueItem = document.getElementById("tmr-fatigue-table");
|
||||
//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>";
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -208,7 +279,6 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async derober() {
|
||||
await this.actor.addTMRRencontre(this.currentRencontre);
|
||||
@ -216,6 +286,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
this._tellToGM(this.actor.name + " s'est dérobé et quitte les TMR.");
|
||||
this.close();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async refouler() {
|
||||
this._tellToGM(this.actor.name + " a refoulé : " + this.currentRencontre.name);
|
||||
@ -259,12 +330,14 @@ export class RdDTMRDialog extends Dialog {
|
||||
this.rencontreState = state;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async choisirCasePortee(coord, portee) {
|
||||
// Récupère la liste des cases à portées
|
||||
let locList = TMRUtility.getTMRPortee(coord, portee);
|
||||
this.colorierZoneRencontre(locList);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async choisirCaseType(type) {
|
||||
const locList = TMRUtility.filterTMR(it => it.type == type).map(it => it.coord);
|
||||
this.colorierZoneRencontre(locList);
|
||||
@ -279,7 +352,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
return true;
|
||||
}
|
||||
const resteAvantInconscience = this.actor.getFatigueMax() - this.actor.getFatigueActuelle() - this.cumulFatigue;
|
||||
if (resteAvantInconscience <= 0) {
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue") && resteAvantInconscience <= 0) {
|
||||
this._tellToGM("Vous vous écroulez de fatigue : vous quittez les Terres médianes !");
|
||||
this.quitterLesTMRInconscient();
|
||||
return true;
|
||||
@ -292,6 +365,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async quitterLesTMRInconscient() {
|
||||
if (this.currentRencontre?.isPersistant) {
|
||||
await this.refouler();
|
||||
@ -312,35 +386,35 @@ export class RdDTMRDialog extends Dialog {
|
||||
rencontre: this.currentRencontre,
|
||||
nbRounds: 1,
|
||||
canClose: false,
|
||||
tmr: TMRUtility.getTMR(Misc.data(this.actor).data.reve.tmrpos.coord)
|
||||
tmr: TMRUtility.getTMR(this._getActorCoord())
|
||||
}
|
||||
|
||||
await this._tentativeMaitrise(rencontreData);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _tentativeMaitrise(rencontreData, presentCite) {
|
||||
console.log("-> matriser", rencontreData);
|
||||
async _tentativeMaitrise(rencData, presentCite) {
|
||||
console.log("-> matriser", rencData);
|
||||
|
||||
rencontreData.reve = this.actor.getReveActuel();
|
||||
rencontreData.etat = this.actor.getEtatGeneral();
|
||||
rencData.reve = this.actor.getReveActuel();
|
||||
rencData.etat = this.actor.getEtatGeneral();
|
||||
|
||||
RollDataAjustements.calcul(rencontreData, this.actor);
|
||||
RollDataAjustements.calcul(rencData, this.actor);
|
||||
|
||||
rencontreData.rolled = rencontreData.presentCite
|
||||
? this._rollPresentCite(rencontreData)
|
||||
: await RdDResolutionTable.roll(rencontreData.reve, RollDataAjustements.sum(rencontreData.ajustements));
|
||||
rencData.rolled = rencData.presentCite
|
||||
? this._rollPresentCite(rencData)
|
||||
: await RdDResolutionTable.roll(rencData.reve, RollDataAjustements.sum(rencData.ajustements));
|
||||
|
||||
let postProcess = await TMRRencontres.gererRencontre(this, rencontreData);
|
||||
let postProcess = await TMRRencontres.gererRencontre(this, rencData);
|
||||
|
||||
ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencontreData)
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-rencontre-tmr.html`, rencData)
|
||||
});
|
||||
|
||||
if (postProcess) {
|
||||
/** Gère les rencontres avec du post-processing (passeur, messagers, tourbillons, ...) */
|
||||
await postProcess(this, rencontreData);
|
||||
await postProcess(this, rencData);
|
||||
}
|
||||
else {
|
||||
this.currentRencontre = undefined;
|
||||
@ -350,16 +424,19 @@ export class RdDTMRDialog extends Dialog {
|
||||
if (this.checkQuitterTMR()) {
|
||||
return;
|
||||
}
|
||||
else if (rencontreData.rolled.isEchec && rencontreData.rencontre.isPersistant) {
|
||||
else if (rencData.rolled.isEchec && rencData.rencontre.isPersistant) {
|
||||
setTimeout(() => {
|
||||
rencontreData.nbRounds++;
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
this._tentativeMaitrise(rencontreData);
|
||||
this._deleteTmrMessages(rencontreData.actor, rencontreData.nbRounds);
|
||||
rencData.nbRounds++;
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
}
|
||||
this._tentativeMaitrise(rencData);
|
||||
this._deleteTmrMessages(rencData.actor, rencData.nbRounds);
|
||||
}, 2000);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_rollPresentCite(rencontreData) {
|
||||
let rolled = RdDResolutionTable.computeChances(rencontreData.reve, 0);
|
||||
mergeObject(rolled, { caracValue: rencontreData.reve, finalLevel: 0, roll: rolled.score });
|
||||
@ -383,17 +460,17 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_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) {
|
||||
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) {
|
||||
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")) });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -420,6 +497,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_presentCite(tmr, postRencontre) {
|
||||
const presentCite = this.casesSpeciales.find(c => EffetsDraconiques.presentCites.isCase(c, tmr.coord));
|
||||
if (presentCite) {
|
||||
@ -429,6 +507,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
return presentCite;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _utiliserPresentCite(presentCite, typeRencontre, tmr, postRencontre) {
|
||||
this.currentRencontre = TMRRencontres.getRencontre(typeRencontre);
|
||||
await TMRRencontres.evaluerForceRencontre(this.currentRencontre);
|
||||
@ -457,11 +536,12 @@ export class RdDTMRDialog extends Dialog {
|
||||
if (rencontre) {
|
||||
return rencontre;
|
||||
}
|
||||
let myRoll = new Roll("1d7").evaluate().total;
|
||||
let myRoll = await RdDDice.rollTotal("1d7");
|
||||
if (TMRUtility.isForceRencontre() || myRoll == 7) {
|
||||
return await this.rencontreTMRRoll(tmr, this.actor.isRencontreSpeciale());
|
||||
}
|
||||
this._tellToUser(myRoll + ": Pas de rencontre en " + tmr.label + " (" + tmr.coord + ")");
|
||||
let locTMR = (this.cacheTMR) ? "??" : tmr.label + " (" + tmr.coord + ")";
|
||||
this._tellToUser(myRoll + ": Pas de rencontre en " + locTMR);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -517,7 +597,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this._rollMaitriseCaseHumide(rollData);
|
||||
return;
|
||||
}
|
||||
rollData.poesie = Poetique.getExtrait();
|
||||
rollData.poesie = await Poetique.getExtrait();
|
||||
ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
|
||||
@ -627,13 +707,14 @@ export class RdDTMRDialog extends Dialog {
|
||||
await this._maitriserTMR(rollData, r => this._onResultatConquerir(r, options));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _onResultatConquerir(rollData, options) {
|
||||
if (rollData.rolled.isETotal) {
|
||||
rollData.souffle = await this.actor.ajouterSouffle({ chat: false });
|
||||
}
|
||||
this.toclose = rollData.rolled.isEchec;
|
||||
|
||||
rollData.poesie = Poetique.getExtrait();
|
||||
rollData.poesie = await Poetique.getExtrait();
|
||||
ChatMessage.create({
|
||||
whisper: ChatUtility.getWhisperRecipientsAndGMs(game.user.name),
|
||||
content: await renderTemplate(`systems/foundryvtt-reve-de-dragon/templates/chat-resultat-maitrise-tmr.html`, rollData)
|
||||
@ -653,7 +734,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
const dialog = await RdDRoll.create(this.actor, rollData,
|
||||
{
|
||||
html: 'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-maitrise-tmr.html',
|
||||
options: { height: 350 },
|
||||
options: { height: 420 },
|
||||
close: html => { this.maximize(); } // Re-display TMR
|
||||
},
|
||||
{
|
||||
@ -667,6 +748,7 @@ export class RdDTMRDialog extends Dialog {
|
||||
dialog.render(true);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async validerVisite(tmr) {
|
||||
await EffetsDraconiques.pelerinage.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr));
|
||||
await EffetsDraconiques.urgenceDraconique.onVisiteSupprimer(this.actor, tmr, (casetmr) => this.removeToken(tmr, casetmr));
|
||||
@ -781,8 +863,9 @@ export class RdDTMRDialog extends Dialog {
|
||||
await tmrObject._onClickTMRPos(eventPos); // Vérifier l'état des compteurs reve/fatigue/vie
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _onClickTMRPos(eventPos) {
|
||||
let currentPos = TMRUtility.convertToCellPos(Misc.data(this.actor).data.reve.tmrpos.coord);
|
||||
let currentPos = TMRUtility.convertToCellPos(this._getActorCoord());
|
||||
|
||||
console.log("deplacerDemiReve >>>>", currentPos, eventPos);
|
||||
|
||||
@ -826,24 +909,37 @@ export class RdDTMRDialog extends Dialog {
|
||||
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)
|
||||
*/
|
||||
this.notifierResonanceSigneDraconique(targetCoord);
|
||||
await this.actor.rollUnSort(targetCoord);
|
||||
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) {
|
||||
if (this.currentRencontre != 'normal') {
|
||||
this.nettoyerRencontre();
|
||||
}
|
||||
let tmr = TMRUtility.getTMR(targetCoord);
|
||||
console.log("deplacerDemiReve", tmr, this);
|
||||
//console.log("deplacerDemiReve", tmr, this);
|
||||
// Gestion cases spéciales type Trou noir, etc
|
||||
tmr = await this.manageTmrInnaccessible(tmr);
|
||||
|
||||
this.actor.updateCoordTMR(tmr.coord);
|
||||
await this.actor.updateCoordTMR(tmr.coord);
|
||||
|
||||
this._updateDemiReve();
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
this.cumulFatigue += this.fatigueParCase;
|
||||
}
|
||||
this.updateValuesDisplay();
|
||||
game.socket.emit("system.foundryvtt-reve-de-dragon", {
|
||||
msg: "msg_tmr_move", data: {
|
||||
@ -860,6 +956,16 @@ 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) {
|
||||
if (!(this.viewOnly || this.currentRencontre)) {
|
||||
await this.manageCaseHumide(tmr);
|
||||
@ -914,7 +1020,9 @@ export class RdDTMRDialog extends Dialog {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_setTokenPosition(token) {
|
||||
this.pixiTMR.setPosition(token.sprite, TMRUtility.convertToCellPos(token.coordTMR()));
|
||||
if (!this.cacheTMR) {
|
||||
this.pixiTMR.setPosition(token.sprite, TMRUtility.convertToCellPos(token.coordTMR()));
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@ -20,7 +20,7 @@ export class RdDTMRRencontreDialog extends Dialog {
|
||||
const dialogOptions = {
|
||||
classes: ["tmrrencdialog"],
|
||||
width: 320, height: 240,
|
||||
'z-index': 20
|
||||
'z-index': 50
|
||||
}
|
||||
super(dialogConf, dialogOptions);
|
||||
|
||||
|
@ -1,54 +1,57 @@
|
||||
/* -------------------------------------------- */
|
||||
import { HtmlUtility } from "./html-utility.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDCombatManager } from "./rdd-combat.js";
|
||||
import { RdDUtility } from "./rdd-utility.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RdDTokenHud {
|
||||
|
||||
static init(){
|
||||
// Integration du TokenHUD
|
||||
static init() {
|
||||
// Integration du TokenHUD
|
||||
Hooks.on('renderTokenHUD', (app, html, data) => { RdDTokenHud.addTokenHudExtensions(app, html, data._id) });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async removeExtensionHud( app, html, tokenId) {
|
||||
let combat = html.find('.control-icon.rdd-combat');
|
||||
combat.remove();
|
||||
let initiative = html.find('.control-icon.rdd-initiative');
|
||||
initiative.remove();
|
||||
static async removeExtensionHud(app, html, tokenId) {
|
||||
html.find('.control-icon.rdd-combat').remove();
|
||||
html.find('.control-icon.rdd-initiative').remove();
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async addExtensionHud( app, html, tokenId ) {
|
||||
static async addExtensionHud(app, html, tokenId) {
|
||||
|
||||
let token = canvas.tokens.get(tokenId);
|
||||
let actor = token.actor;
|
||||
let combatant = game.combat.data.combatants.find(c => c.tokenId == token.data._id);
|
||||
let combatant = game.combat.combatants.find(c => Misc.data(c).tokenId == tokenId);
|
||||
app.hasExtension = true;
|
||||
|
||||
let armesList = RdDCombatManager.buildListeActionsCombat(combatant) ;
|
||||
const hudData = { combatant: combatant, armes: armesList,
|
||||
commandes: [{ name: 'Initiative +1', command: 'inc', value: 0.01}, { name: 'Initiative -1',command: 'dec', value: -0.01}] };
|
||||
let armesList = RdDCombatManager.buildListeActionsCombat(combatant);
|
||||
const hudData = {
|
||||
combatant: combatant, armes: armesList,
|
||||
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
|
||||
await RdDTokenHud._configureSubMenu(html.find('.control-icon.combat'), 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', hudData,
|
||||
await RdDTokenHud._configureSubMenu(controlIconCombat, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html', hudData,
|
||||
(event) => {
|
||||
let initCommand = event.currentTarget.attributes['data-command'].value;
|
||||
let combatantId = event.currentTarget.attributes['data-combatant-id'].value;
|
||||
if ( !initCommand ) {
|
||||
if (!initCommand) {
|
||||
let armeIndex = event.currentTarget.attributes['data-arme-id'].value;
|
||||
let arme = armesList[armeIndex];
|
||||
RdDCombatManager.rollInitiativeCompetence(combatantId, arme);
|
||||
} else if (initCommand == 'inc') {
|
||||
RdDCombatManager.incDecInit( combatantId, 0.01 );
|
||||
} else if ( initCommand == 'dec') {
|
||||
RdDCombatManager.incDecInit( combatantId, -0.01 );
|
||||
RdDCombatManager.incDecInit(combatantId, 0.01);
|
||||
} else if (initCommand == 'dec') {
|
||||
RdDCombatManager.incDecInit(combatantId, -0.01);
|
||||
}
|
||||
});
|
||||
|
||||
const controlIconTarget = html.find('.control-icon[data-action=target]');
|
||||
// combat
|
||||
await RdDTokenHud._configureSubMenu(html.find('.control-icon.target'), 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData,
|
||||
await RdDTokenHud._configureSubMenu(controlIconTarget, 'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html', hudData,
|
||||
(event) => {
|
||||
let armeIndex = event.currentTarget.attributes['data-arme-id'].value;
|
||||
let arme = armesList[armeIndex];
|
||||
@ -58,38 +61,35 @@ export class RdDTokenHud {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async addTokenHudExtensions(app, html, tokenId) {
|
||||
|
||||
html.find('.control-icon.combat').click(event => {
|
||||
if ( event.currentTarget.className.includes('active')) {
|
||||
RdDTokenHud.removeExtensionHud( 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 );
|
||||
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);
|
||||
if (controlIconCombat.length>0 && controlIconCombat[0].className.includes('active')) {
|
||||
RdDTokenHud.addExtensionHud(app, html, tokenId);
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async _configureSubMenu(insertionPoint, template, hudData, onMenuItem) {
|
||||
const hud = $(await renderTemplate(template, hudData));
|
||||
const imgHud = hud.find('img.rdd-hud-togglebutton');
|
||||
const list = hud.find('div.rdd-hud-list');
|
||||
|
||||
hud.toggleClass('active');
|
||||
HtmlUtility._showControlWhen(list, hud.hasClass('active'));
|
||||
|
||||
imgHud.click(event => {
|
||||
hud.toggleClass('active');
|
||||
HtmlUtility._showControlWhen(list, hud.hasClass('active'));
|
||||
});
|
||||
RdDTokenHud._toggleHudListActive(hud, list);
|
||||
|
||||
hud.find('img.rdd-hud-togglebutton').click(event => RdDTokenHud._toggleHudListActive(hud, list));
|
||||
list.find('.rdd-hud-menu').click(onMenuItem);
|
||||
|
||||
insertionPoint.after(hud);
|
||||
}
|
||||
|
||||
static _toggleHudListActive(hud, list) {
|
||||
hud.toggleClass('active');
|
||||
HtmlUtility._showControlWhen(list, hud.hasClass('active'));
|
||||
}
|
||||
}
|
@ -4,6 +4,10 @@ import { ChatUtility } from "./chat-utility.js";
|
||||
import { RdDCombat } from "./rdd-combat.js";
|
||||
import { Misc } from "./misc.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";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
// This table starts at 0 -> niveau -10
|
||||
@ -92,6 +96,13 @@ const definitionsEncaissement = {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
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() {
|
||||
const templatePaths = [
|
||||
@ -101,6 +112,13 @@ export class RdDUtility {
|
||||
'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-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-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-editor-notes-mj.html',
|
||||
//Items
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item-competence-sheet.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/item-competencecreature-sheet.html',
|
||||
@ -122,6 +140,8 @@ export class RdDUtility {
|
||||
'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-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-base.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/enum-aspect-tarot.html',
|
||||
@ -130,6 +150,8 @@ export class RdDUtility {
|
||||
'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-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-rarete.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/sort-draconic.html',
|
||||
@ -137,7 +159,6 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/niveau-ethylisme.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/casetmr-specific-list.html',
|
||||
// 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-competence.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/dialog-roll-carac.html',
|
||||
@ -145,17 +166,22 @@ export class RdDUtility {
|
||||
'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-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-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
|
||||
'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/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
|
||||
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-init.html',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/hud-actor-attaque.html',
|
||||
@ -178,7 +204,10 @@ export class RdDUtility {
|
||||
'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-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'));
|
||||
@ -187,10 +216,21 @@ export class RdDUtility {
|
||||
Handlebars.registerHelper('un', str => Grammar.articleIndetermine(str));
|
||||
Handlebars.registerHelper('accord', (genre, ...args) => Grammar.accord(genre, args));
|
||||
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('equals', (a, b) => a == b);
|
||||
|
||||
return loadTemplates(templatePaths);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static buildListOptions(min, max) {
|
||||
let options = ""
|
||||
for (let i = min; i <= max; i++) {
|
||||
options += `<option value="${i}">${i}</option>`
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static checkNull(items) {
|
||||
@ -224,93 +264,73 @@ export class RdDUtility {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static filterItemsPerTypeForSheet(formData) {
|
||||
formData.data.materiel = this.checkNull(formData.itemsByType['objet']);
|
||||
formData.data.conteneurs = this.checkNull(formData.itemsByType['conteneur']);
|
||||
formData.data.armes = this.checkNull(formData.itemsByType['arme']);
|
||||
formData.data.armures = this.checkNull(formData.itemsByType['armure']);
|
||||
formData.data.livres = this.checkNull(formData.itemsByType['livre']);
|
||||
formData.data.potions = this.checkNull(formData.itemsByType['potion']);
|
||||
formData.data.ingredients = this.checkNull(formData.itemsByType['ingredient']);
|
||||
formData.data.munitions = this.checkNull(formData.itemsByType['munition']);
|
||||
formData.data.herbes = this.checkNull(formData.itemsByType['herbe']);
|
||||
formData.data.sorts = this.checkNull(formData.itemsByType['sort']);
|
||||
formData.data.queues = this.checkNull(formData.itemsByType['queue']);
|
||||
formData.data.souffles = this.checkNull(formData.itemsByType['souffle']);
|
||||
formData.data.ombres = this.checkNull(formData.itemsByType['ombre']);
|
||||
formData.data.tetes = this.checkNull(formData.itemsByType['tete']);
|
||||
formData.data.taches = this.checkNull(formData.itemsByType['tache']);
|
||||
formData.data.monnaie = this.checkNull(formData.itemsByType['monnaie']);
|
||||
formData.data.meditations = this.checkNull(formData.itemsByType['meditation']);
|
||||
formData.data.chants = this.checkNull(formData.itemsByType['chant']);
|
||||
formData.data.danses = this.checkNull(formData.itemsByType['danse']);
|
||||
formData.data.musiques = this.checkNull(formData.itemsByType['musique']);
|
||||
formData.data.oeuvres = this.checkNull(formData.itemsByType['oeuvre']);
|
||||
formData.data.jeux = this.checkNull(formData.itemsByType['jeu']);
|
||||
formData.data.recettescuisine = this.checkNull(formData.itemsByType['recettecuisine']);
|
||||
formData.data.recettesAlchimiques = this.checkNull(formData.itemsByType['recettealchimique']);
|
||||
formData.data.objets = formData.data.conteneurs.concat(formData.data.materiel)
|
||||
.concat(formData.data.armes)
|
||||
.concat(formData.data.armures)
|
||||
.concat(formData.data.munitions)
|
||||
.concat(formData.data.livres)
|
||||
.concat(formData.data.potions)
|
||||
.concat(formData.data.herbes)
|
||||
.concat(formData.data.ingredients);
|
||||
formData.data.competences = (formData.itemsByType.competence??[]).concat(formData.itemsByType.competencecreature??[]);
|
||||
formData.materiel = this.checkNull(formData.itemsByType['objet']);
|
||||
formData.conteneurs = this.checkNull(formData.itemsByType['conteneur']);
|
||||
formData.armes = this.checkNull(formData.itemsByType['arme']);
|
||||
formData.armures = this.checkNull(formData.itemsByType['armure']);
|
||||
formData.livres = this.checkNull(formData.itemsByType['livre']);
|
||||
formData.potions = this.checkNull(formData.itemsByType['potion']);
|
||||
formData.ingredients = this.checkNull(formData.itemsByType['ingredient']);
|
||||
formData.munitions = this.checkNull(formData.itemsByType['munition']);
|
||||
formData.herbes = this.checkNull(formData.itemsByType['herbe']);
|
||||
formData.sorts = this.checkNull(formData.itemsByType['sort']);
|
||||
formData.signesdraconiques = this.checkNull(formData.itemsByType['signedraconique']);
|
||||
formData.queues = this.checkNull(formData.itemsByType['queue']);
|
||||
formData.souffles = this.checkNull(formData.itemsByType['souffle']);
|
||||
formData.ombres = this.checkNull(formData.itemsByType['ombre']);
|
||||
formData.tetes = this.checkNull(formData.itemsByType['tete']);
|
||||
formData.taches = this.checkNull(formData.itemsByType['tache']);
|
||||
formData.monnaie = this.checkNull(formData.itemsByType['monnaie']);
|
||||
formData.nourritureboissons = this.checkNull(formData.itemsByType['nourritureboisson']);
|
||||
formData.meditations = this.checkNull(formData.itemsByType['meditation']);
|
||||
formData.chants = this.checkNull(formData.itemsByType['chant']);
|
||||
formData.danses = this.checkNull(formData.itemsByType['danse']);
|
||||
formData.musiques = this.checkNull(formData.itemsByType['musique']);
|
||||
formData.oeuvres = this.checkNull(formData.itemsByType['oeuvre']);
|
||||
formData.jeux = this.checkNull(formData.itemsByType['jeu']);
|
||||
formData.recettescuisine = this.checkNull(formData.itemsByType['recettecuisine']);
|
||||
formData.recettesAlchimiques = this.checkNull(formData.itemsByType['recettealchimique']);
|
||||
formData.objets = formData.conteneurs.concat(formData.materiel)
|
||||
.concat(formData.armes)
|
||||
.concat(formData.armures)
|
||||
.concat(formData.munitions)
|
||||
.concat(formData.livres)
|
||||
.concat(formData.potions)
|
||||
.concat(formData.herbes)
|
||||
.concat(formData.ingredients)
|
||||
.concat(formData.nourritureboissons);
|
||||
formData.competences = (formData.itemsByType.competence ?? []).concat(formData.itemsByType.competencecreature ?? []);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async processItemDropEvent(actorSheet, event) {
|
||||
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)
|
||||
static buildArbreDeConteneurs(conteneurs, objets) {
|
||||
let objetVersConteneur = {};
|
||||
// Attribution des objets aux conteneurs
|
||||
for (let conteneur of data.data.conteneurs) {
|
||||
for (let conteneur of conteneurs) {
|
||||
conteneur.subItems = [];
|
||||
if (!conteneur.data.encTotal) conteneur.data.encTotal = 0;
|
||||
if (!conteneur.data.encTotal)
|
||||
conteneur.data.encTotal = 0;
|
||||
//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));
|
||||
let objet = objets.find(objet => (id == objet._id));
|
||||
if (objet) {
|
||||
if (!objet.data.encombrement) objet.data.encombrement = 0; // Auto-fix
|
||||
if (!objet.data.encombrement)
|
||||
objet.data.encombrement = 0; // Auto-fix
|
||||
objet.estContenu = true; // Permet de filtrer ce qifui est porté dans le template
|
||||
actorSheet.objetVersConteneur[id] = conteneur._id;
|
||||
objetVersConteneur[id] = conteneur._id;
|
||||
conteneur.data.encTotal += Number(objet.data.encombrement) * Number(((objet.data.quantite) ? objet.data.quantite : 1));
|
||||
conteneur.subItems.push(objet);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Construit la liste des conteneurs de niveau 1 (c'est à dire non contenu eux-même dans un conteneur)
|
||||
let newConteneurs = data.data.conteneurs.filter(function (conteneur, index, arr) { return !conteneur.estContenu });
|
||||
data.data.conteneurs = newConteneurs;
|
||||
//console.log(newConteneurs);
|
||||
return objetVersConteneur;
|
||||
}
|
||||
|
||||
// Construit la liste des conteneurs de niveau 1 (c'est à dire non contenu eux-même dans un conteneur)
|
||||
static conteneursRacine(conteneurs) {
|
||||
return conteneurs.filter( (conteneur, index, arr) => !conteneur.estContenu);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -321,7 +341,7 @@ export class RdDUtility {
|
||||
if (!niveau) niveau = 1;
|
||||
objet.niveau = niveau;
|
||||
//console.log("OBJ:", objet);
|
||||
let str = Handlebars.partials['systems/foundryvtt-reve-de-dragon/templates/actor-inventaire-conteneur.html']({ item: objet });
|
||||
let str = Handlebars.partials['systems/foundryvtt-reve-de-dragon/templates/actor-sheet-inventaire-conteneur.html']({ item: objet });
|
||||
if (objet.type == 'conteneur') {
|
||||
//console.log("ITEM DISPLAYED", objet );
|
||||
if (this.getAfficheContenu(objet._id)) {
|
||||
@ -374,6 +394,14 @@ export class RdDUtility {
|
||||
}
|
||||
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.
|
||||
// max should be the endurance max value
|
||||
@ -417,8 +445,8 @@ export class RdDUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getLocalisation(type = 'personnage') {
|
||||
let result = new Roll("1d20").roll().total;
|
||||
static async getLocalisation(type = 'personnage') {
|
||||
let result = await RdDDice.rollTotal("1d20");
|
||||
let txt = ""
|
||||
if (type == 'personnage') {
|
||||
if (result <= 3) txt = "Jambe, genou, pied, jarret";
|
||||
@ -450,56 +478,35 @@ export class RdDUtility {
|
||||
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) {
|
||||
max = Math.max(1, Math.min(max, 60));
|
||||
value = Math.min(max * 2, Math.max(0, value));
|
||||
if (ReglesOptionelles.isUsing("appliquer-fatigue")) {
|
||||
max = Math.max(1, Math.min(max, 60));
|
||||
value = Math.min(max * 2, Math.max(0, value));
|
||||
|
||||
let fatigueTab = fatigueMatrix[max];
|
||||
let fatigueRem = value;
|
||||
for (let idx = 0; idx < fatigueTab.length; idx++) {
|
||||
fatigueRem -= fatigueTab[idx];
|
||||
if (fatigueRem <= 0) {
|
||||
return fatigueMalus[idx];
|
||||
let fatigueTab = fatigueMatrix[max];
|
||||
let fatigueRem = value;
|
||||
for (let idx = 0; idx < fatigueTab.length; idx++) {
|
||||
fatigueRem -= fatigueTab[idx];
|
||||
if (fatigueRem <= 0) {
|
||||
return fatigueMalus[idx];
|
||||
}
|
||||
}
|
||||
return -7; // This is the max !
|
||||
}
|
||||
return -7; // This is the max !
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async loadCompendiumNames(compendium) {
|
||||
static async loadCompendiumData(compendium) {
|
||||
const pack = game.packs.get(compendium);
|
||||
let competences;
|
||||
await pack.getIndex().then(index => competences = index);
|
||||
return competences;
|
||||
return await pack?.getDocuments() ?? [];
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async loadCompendium(compendium, filter = item => true) {
|
||||
if (!compendium){
|
||||
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;
|
||||
let compendiumData = await RdDUtility.loadCompendiumData(compendium);
|
||||
return compendiumData.filter(filter);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -521,16 +528,14 @@ export class RdDUtility {
|
||||
case "msg_response_nombre_astral":
|
||||
return RdDUtility.responseNombreAstral(sockmsg.data);
|
||||
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);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async chatListeners(html) {
|
||||
RdDCombat.registerChatCallbacks(html);
|
||||
@ -550,24 +555,78 @@ export class RdDUtility {
|
||||
let actor = game.actors.get(actorId);
|
||||
actor.tmrApp.lancerSortEnReserve(coord, sortId);
|
||||
});
|
||||
|
||||
// gestion bouton tchat Acheter
|
||||
html.on("click", '.button-acheter', event => DialogItemAchat.onButtonAcheter(event));
|
||||
|
||||
// Gestion du bouton payer
|
||||
html.on("click", '#payer-button', event => {
|
||||
let sumdenier = event.currentTarget.attributes['data-somme-denier'].value;
|
||||
let quantite = event.currentTarget.attributes['data-quantite'].value;
|
||||
html.on("click", '.payer-button', event => {
|
||||
let sumdenier = event.currentTarget.attributes['data-somme-denier']?.value ?? 0;
|
||||
let quantite = event.currentTarget.attributes['data-quantite']?.value ?? 1;
|
||||
let fromActorId = event.currentTarget.attributes['data-actor-id']?.value;
|
||||
let jsondata = event.currentTarget.attributes['data-jsondata']
|
||||
let objData
|
||||
if (jsondata) {
|
||||
objData = JSON.parse(jsondata.value)
|
||||
}
|
||||
if (game.user.character) {
|
||||
game.user.character.payerDenier(sumdenier, objData, quantite);
|
||||
} else {
|
||||
let msgPayer = "Vous devez avoir un acteur relié pour effectuer le paiement";
|
||||
ChatMessage.create({ content: msgPayer, whisper: [game.user] });
|
||||
let actor = RdDUtility.getSelectedActor("Pour effectuer le paiement:");
|
||||
if (actor) {
|
||||
actor.depenserDeniers(sumdenier, objData, quantite, fromActorId);
|
||||
// TODO: diminuer la quantité ou supprimer le message
|
||||
// message: => document.querySelector("#chat-log > li:nth-child(61) > div > div > span > a")
|
||||
// => ../../../..[@data-message-id]
|
||||
let chatMessageId = RdDUtility.findChatMessageId(event.currentTarget);
|
||||
if (chatMessageId) {
|
||||
ChatUtility.removeChatMessageId(chatMessageId);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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) {
|
||||
let piece = {
|
||||
@ -599,14 +658,14 @@ export class RdDUtility {
|
||||
|
||||
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>";
|
||||
msgPayer += "<a id='payer-button' class='chat-card-button' data-somme-denier='" + sumtotald + "'>Payer</a>"
|
||||
msgPayer += "<a class='payer-button chat-card-button' data-somme-denier='" + sumtotald + "'>Payer</a>"
|
||||
ChatMessage.create({ content: msgPayer });
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static chatDataSetup(content, modeOverride, isRoll = false, forceWhisper) {
|
||||
let chatData = {
|
||||
user: game.user._id,
|
||||
user: game.user.id,
|
||||
rollMode: modeOverride || game.settings.get("core", "rollMode"),
|
||||
content: content
|
||||
};
|
||||
@ -654,7 +713,7 @@ export class RdDUtility {
|
||||
/* -------------------------------------------- */
|
||||
static async confirmerSuppression(actorSheet, li) {
|
||||
let itemId = li.data("item-id");
|
||||
let objet = actorSheet.actor.items.find(item => item._id == itemId);
|
||||
let objet = actorSheet.actor.getObjet(itemId);
|
||||
let msgTxt = "<p>Etes vous certain de vouloir supprimer cet objet ?";
|
||||
let buttons = {
|
||||
delete: {
|
||||
@ -662,7 +721,7 @@ export class RdDUtility {
|
||||
label: "Supprimer l'objet",
|
||||
callback: () => {
|
||||
console.log("Delete : ", itemId);
|
||||
actorSheet.actor.deleteOwnedItem(itemId);
|
||||
actorSheet.actor.deleteEmbeddedDocuments('Item', [itemId]);
|
||||
li.slideUp(200, () => actorSheet.render(false));
|
||||
}
|
||||
},
|
||||
@ -671,8 +730,9 @@ export class RdDUtility {
|
||||
label: "Annuler"
|
||||
}
|
||||
}
|
||||
if (objet.data.type == 'conteneur' && objet.data.data.contenu.length > 0) {
|
||||
msgTxt += "<br>Cet objet est aussi un conteneur avec du contenu : choisissez l'option de suppression";
|
||||
const docData = Misc.data(objet);
|
||||
if (docData.type == 'conteneur' && docData.data.contenu.length > 0) {
|
||||
msgTxt += "<br>Ce conteneur n'est pas vide. Choisissez l'option de suppression";
|
||||
buttons['deleteall'] = {
|
||||
icon: '<i class="fas fa-check"></i>',
|
||||
label: "Supprimer le conteneur et tout son contenu",
|
||||
@ -699,7 +759,7 @@ export class RdDUtility {
|
||||
let ajustement = game.system.rdd.calendrier.getAjustementAstrologique(heureNaissance);
|
||||
ChatMessage.create({
|
||||
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("MJ")
|
||||
whisper: ChatMessage.getWhisperRecipients("GM")
|
||||
});
|
||||
}
|
||||
else {
|
||||
|
@ -1,12 +1,15 @@
|
||||
import { Misc } from "./misc.js";
|
||||
|
||||
const listeReglesOptionelles = [
|
||||
{name:'recul', group:'combat', descr:"Appliquer le recul en cas de particulière en force ou de charge"},
|
||||
{name:'resistanceArmeParade', group:'combat', descr:"Faire le jet de résistance des armes lors de parades pouvant les endommager"},
|
||||
{name:'deteriorationArmure', group:'combat', descr:"Tenir compte de la détérioration des armures"},
|
||||
{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:'combat', descr:"Le défenseur doit obtenir une significative en cas de parade avec des armes de catégories différentes"},
|
||||
{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:'generale', descr:"Appliquer les ajustements astrologiques aux jets de chance et aux rituels"}
|
||||
{ name: 'recul', group: 'Règles de 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: 'deteriorationArmure', group: 'Règles de 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: '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: '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: 'astrologie', group: 'Règles de générales', descr: "Appliquer les ajustements astrologiques aux jets de chance et aux rituels", default: true },
|
||||
{ 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 {
|
||||
@ -14,7 +17,7 @@ export class ReglesOptionelles extends FormApplication {
|
||||
for (const regle of listeReglesOptionelles) {
|
||||
const name = regle.name;
|
||||
const id = ReglesOptionelles._getIdRegle(name);
|
||||
game.settings.register("foundryvtt-reve-de-dragon", id, { name: id, scope: "world", config: false, default: regle.default??true, type: Boolean });
|
||||
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.registerMenu("foundryvtt-reve-de-dragon", "rdd-options-regles", {
|
||||
@ -38,25 +41,27 @@ export class ReglesOptionelles extends FormApplication {
|
||||
static get defaultOptions() {
|
||||
const options = super.defaultOptions;
|
||||
mergeObject(options, {
|
||||
id: "combat-settings",
|
||||
id: "optional-settings",
|
||||
template: "systems/foundryvtt-reve-de-dragon/templates/regles-optionelles.html",
|
||||
height: 600,
|
||||
width: 350,
|
||||
minimizable: false,
|
||||
closeOnSubmit: true,
|
||||
title: "Options de combat"
|
||||
title: "Règles optionnelles"
|
||||
});
|
||||
return options;
|
||||
}
|
||||
|
||||
getData() {
|
||||
let formData = super.getData();
|
||||
formData.regles = listeReglesOptionelles.map(it => {
|
||||
let r = duplicate(it);
|
||||
r.id = ReglesOptionelles._getIdRegle(r.name);
|
||||
r.active = ReglesOptionelles.isUsing(r.name);
|
||||
return r;
|
||||
})
|
||||
const regles = listeReglesOptionelles.map(it => {
|
||||
it = duplicate(it);
|
||||
it.id = ReglesOptionelles._getIdRegle(it.name);
|
||||
it.active = ReglesOptionelles.isUsing(it.name);
|
||||
return it;
|
||||
});
|
||||
formData.regles = regles;
|
||||
formData.groups = Misc.classify(regles, it => it.group);
|
||||
return formData;
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ export const referenceAjustements = {
|
||||
getValue: (rollData, actor) => actor.getEtatGeneral()
|
||||
},
|
||||
malusArmure: {
|
||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.competence),
|
||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac),
|
||||
isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerivee(rollData.selectedCarac),
|
||||
getLabel: (rollData, actor) => 'Malus armure',
|
||||
getValue: (rollData, actor) => actor.getMalusArmure()
|
||||
@ -131,6 +131,7 @@ export class RollDataAjustements {
|
||||
for (var key in referenceAjustements) {
|
||||
const reference = referenceAjustements[key];
|
||||
rollData.ajustements[key] = {
|
||||
visible: reference.isVisible && reference.isVisible(rollData, actor),
|
||||
used: reference.isUsed(rollData, actor),
|
||||
label: reference.getLabel && reference.getLabel(rollData, actor),
|
||||
value: reference.getValue && reference.getValue(rollData, actor),
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { DeDraconique } from "./de-draconique.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
import { TMRUtility } from "./tmr-utility.js";
|
||||
import { TMRType } from "./tmr-utility.js";
|
||||
|
||||
@ -8,11 +8,11 @@ import { TMRType } from "./tmr-utility.js";
|
||||
const typeRencontres = {
|
||||
|
||||
messager: {
|
||||
msgSucces: (data) => `Le ${data.rencontre.name} vous propose d'emmener le message de votre un sort à ${data.rencontre.force} cases ${data.tmr.label}.`,
|
||||
msgEchec: (data) => `Le ${data.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`,
|
||||
postSucces: (tmrDialog, data) => {
|
||||
tmrDialog.setStateRencontre(data.rencontre.type);
|
||||
tmrDialog.choisirCasePortee(data.tmr.coord, data.rencontre.force);
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} vous propose d'emmener le message de votre un sort à ${rencData.rencontre.force} cases ${rencData.tmr.label}.`,
|
||||
msgEchec: (rencData) => `Le ${rencData.rencontre.name} est pressé et continue son chemin d'une traite sans vous accorder un regard.`,
|
||||
postSucces: (tmrDialog, rencData) => {
|
||||
tmrDialog.setStateRencontre(rencData.rencontre.type);
|
||||
tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
|
||||
},
|
||||
poesieSucces: {
|
||||
reference: "La chevelure, Charles Baudelaire",
|
||||
@ -28,11 +28,11 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
passeur: {
|
||||
msgSucces: (data) => `Le ${data.rencontre.name} vous propose de vous transporter à ${data.rencontre.force} cases des ${data.tmr.label}.`,
|
||||
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, data) => {
|
||||
tmrDialog.setStateRencontre(data.rencontre.type);
|
||||
tmrDialog.choisirCasePortee(data.tmr.coord, data.rencontre.force);
|
||||
msgSucces: (rencData) => `Le ${rencData.rencontre.name} vous propose de vous transporter à ${rencData.rencontre.force} cases des ${rencData.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.`,
|
||||
postSucces: (tmrDialog, rencData) => {
|
||||
tmrDialog.setStateRencontre(rencData.rencontre.type);
|
||||
tmrDialog.choisirCasePortee(rencData.tmr.coord, rencData.rencontre.force);
|
||||
},
|
||||
poesieSucces: {
|
||||
reference: "Femmes damnées (2), Charles Baudelaire",
|
||||
@ -49,9 +49,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
fleur: {
|
||||
msgSucces: (data) => `Vous cueillez la ${data.rencontre.name}, son parfum vous apporte ${data.rencontre.force} points de Rêve.`,
|
||||
msgEchec: (data) => `La ${data.rencontre.name} se fâne et disparaît entre vos doigts.`,
|
||||
postSucces: (tmrDialog, data) => tmrDialog.actor.reveActuelIncDec(data.rencontre.force),
|
||||
msgSucces: (rencData) => `Vous cueillez la ${rencData.rencontre.name}, son parfum vous apporte ${rencData.rencontre.force} points de Rêve.`,
|
||||
msgEchec: (rencData) => `La ${rencData.rencontre.name} se fâne et disparaît entre vos doigts.`,
|
||||
postSucces: (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(rencData.rencontre.force),
|
||||
poesieSucces: {
|
||||
reference: "L'Ennemi, Charles Baudelaire",
|
||||
extrait: `Et qui sait si les fleurs nouvelles que je rêve
|
||||
@ -66,9 +66,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
mangeur: {
|
||||
msgSucces: (data) => `Le ${data.rencontre.name} claque de sa machoire dans le vide avant de fuir.`,
|
||||
msgEchec: (data) => `Le ${data.rencontre.name} croque votre Rêve ! Il emporte ${data.rencontre.force} de vos points de rêve actuels`,
|
||||
postEchec: (tmrDialog, data) => tmrDialog.actor.reveActuelIncDec(-data.rencontre.force),
|
||||
msgSucces: (rencData) => `Le ${rencData.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`,
|
||||
postEchec: (tmrDialog, rencData) => tmrDialog.actor.reveActuelIncDec(-rencData.rencontre.force),
|
||||
poesieSucces: {
|
||||
reference: "Conseil, Victor Hugo",
|
||||
extrait: `Rois ! la bure est souvent jalouse du velours.
|
||||
@ -85,16 +85,16 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
changeur: {
|
||||
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: (data) => {
|
||||
data.newTMR = TMRUtility.getTMRAleatoire(it => it.type = data.tmr.type);
|
||||
return `Le ${data.rencontre.name} vous embobine avec des promesses, et vous transporte en ${data.newTMR.label} sans attendre votre avis.`;
|
||||
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é.`,
|
||||
msgEchec: (rencData) => {
|
||||
rencData.newTMR = TMRUtility.getTMRAleatoire(it => it.type = rencData.tmr.type);
|
||||
return `Le ${rencData.rencontre.name} vous embobine avec des promesses, et vous transporte en ${rencData.newTMR.label} sans attendre votre avis.`;
|
||||
},
|
||||
postSucces: (tmrDialog, data) => {
|
||||
tmrDialog.setStateRencontre(data.rencontre.type);
|
||||
tmrDialog.choisirCaseType(data.tmr.type);
|
||||
postSucces: (tmrDialog, rencData) => {
|
||||
tmrDialog.setStateRencontre(rencData.rencontre.type);
|
||||
tmrDialog.choisirCaseType(rencData.tmr.type);
|
||||
},
|
||||
postEchec: (tmrDialog, data) => tmrDialog.forceDemiRevePosition(data.newTMR.coord),
|
||||
postEchec: (tmrDialog, rencData) => tmrDialog.forceDemiRevePosition(rencData.newTMR.coord),
|
||||
poesieSucces: {
|
||||
reference: "Caligula - IIIème chant, Gérard de Nerval",
|
||||
extrait: `Allez, que le caprice emporte
|
||||
@ -111,9 +111,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
briseur: {
|
||||
msgSucces: (data) => `Le ${data.rencontre.name} tente vainement de vous déconcentrer, avant de fuir sans demander son reste.`,
|
||||
msgEchec: (data) => `Le ${data.rencontre.name} vous déconcentre au point de briser votre demi-rêve.`,
|
||||
postEchec: (tmrDialog, data) => tmrDialog.close(),
|
||||
msgSucces: (rencData) => `Le ${rencData.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.`,
|
||||
postEchec: (tmrDialog, rencData) => tmrDialog.close(),
|
||||
poesieSucces: {
|
||||
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||
extrait: `La légende affirme que ce sont les Gnomes qui furent
|
||||
@ -134,8 +134,8 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
reflet: {
|
||||
msgSucces: (data) => `Le ${data.rencontre.name} s'estompe dans l'oubli.`,
|
||||
msgEchec: (data) => `Vous êtes submergé par un ${data.rencontre.name}, les souvenirs vous retiennent tant qu'il ne sera pas vaincu!`,
|
||||
msgSucces: (rencData) => `Le ${rencData.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!`,
|
||||
poesieSucces: {
|
||||
reference: "Une charogne, Charles Baudelaire",
|
||||
extrait: `Les formes s'effaçaient et n'étaient plus qu'un rêve,
|
||||
@ -152,9 +152,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
passeurfou: {
|
||||
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: (data) => TMRRencontres.msgEchecPasseurFou(data),
|
||||
postEchec: (tmrDialog, data) => TMRRencontres.postEchecPasseurFou(tmrDialog, data),
|
||||
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.`,
|
||||
msgEchec: (rencData) => TMRRencontres.msgEchecPasseurFou(rencData),
|
||||
postEchec: (tmrDialog, rencData) => TMRRencontres.postEchecPasseurFou(tmrDialog, rencData),
|
||||
poesieSucces: {
|
||||
reference: "Un Fou et un Sage, Jean de La Fontaine",
|
||||
extrait: `Certain Fou poursuivait à coups de pierre un Sage.
|
||||
@ -174,9 +174,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
tbblanc: {
|
||||
msgSucces: (data) => `Le ${data.rencontre.name} souleve une poussière blanche, vous tenez bon, et il tourbillonne en s'éloignant.`,
|
||||
msgEchec: (data) => `Le souffle du ${data.rencontre.name} vous déstabilise et vous emmène dans un nuage de poussière.`,
|
||||
postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecTourbillon(tmrDialog, data, 1),
|
||||
msgSucces: (rencData) => `Le ${rencData.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.`,
|
||||
postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillon(tmrDialog, rencData, 1),
|
||||
poesieSucces: {
|
||||
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||
extrait: `Le Premier Âge fut appelé l'Âge des Dragons. Ce fut le commencement
|
||||
@ -191,9 +191,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
tbnoir: {
|
||||
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: (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, data) => TMRRencontres.onPostEchecTourbillon(tmrDialog, data, 2),
|
||||
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.`,
|
||||
msgEchec: (rencData) => `Le ${rencData.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),
|
||||
poesieSucces: {
|
||||
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||
extrait: `Car le Second Âge fut bel et bien celui des Magiciens. Durant cette période, les
|
||||
@ -207,9 +207,9 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
tbrouge: {
|
||||
msgSucces: (data) => `Le ${data.rencontre.name} s'abat avec violence mais vous êtes plus rapide et parvenez à lui échapper.`,
|
||||
msgEchec: (data) => `Le ${data.rencontre.name} vous frappe de milliers de morsure et vous malmène à travers les terres médianes.`,
|
||||
postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, data),
|
||||
msgSucces: (rencData) => `Le ${rencData.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.`,
|
||||
postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecTourbillonRouge(tmrDialog, rencData),
|
||||
poesieSucces: {
|
||||
reference: "Qu'est-ce de votre vie ? une bouteille molle, Jean-Baptiste Chassignet",
|
||||
extrait: `Qu'est-ce de votre vie ? un tourbillon rouant
|
||||
@ -228,10 +228,10 @@ const typeRencontres = {
|
||||
},
|
||||
|
||||
rdd: {
|
||||
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: (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, data) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, data),
|
||||
postEchec: (tmrDialog, data) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, data),
|
||||
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`,
|
||||
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!`,
|
||||
postSucces: (tmrDialog, rencData) => TMRRencontres.onPostSuccessReveDeDragon(tmrDialog, rencData),
|
||||
postEchec: (tmrDialog, rencData) => TMRRencontres.onPostEchecReveDeDragon(tmrDialog, rencData),
|
||||
poesieSucces: {
|
||||
reference: "Rêve de Dragon, Denis Gerfaud",
|
||||
extrait: `Le monde est Rêve de Dragons, mais nous ne savons
|
||||
@ -269,7 +269,7 @@ const rencontresStandard = [
|
||||
{ code: "reflet", name: "Reflet d'ancien Rêve", type: "reflet", genre: "m", force: "2d6", isPersistant: true },
|
||||
{ code: "tbblanc", name: "Tourbillon blanc", type: "tbblanc", genre: "m", force: "2d6", isPersistant: true },
|
||||
{ code: "tbnoir", name: "Tourbillon noir", type: "tbnoir", genre: "m", force: "2d8", isPersistant: true },
|
||||
{ code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1ddr + 7", refoulement: 2, quitterTMR: true }
|
||||
{ code: "rdd", name: "Rêve de Dragon", type: "rdd", genre: "m", force: "1dr + 7", refoulement: 2, quitterTMR: true }
|
||||
];
|
||||
|
||||
const rencontresPresentCite = [
|
||||
@ -325,12 +325,12 @@ export class TMRRencontres {
|
||||
return false;
|
||||
}
|
||||
if (!roll || roll <= 0 || roll > 100) {
|
||||
roll = new Roll("1d100").evaluate().total;
|
||||
roll = await RdDDice.rollTotal("1d100");
|
||||
}
|
||||
let rencontre = await TMRRencontres.getRencontreAleatoire(terrain, roll);
|
||||
ChatMessage.create({
|
||||
user: game.user._id,
|
||||
whisper: [game.user._id],
|
||||
user: 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`
|
||||
});
|
||||
return false;
|
||||
@ -349,7 +349,7 @@ export class TMRRencontres {
|
||||
return duplicate(rencontre);
|
||||
}
|
||||
else {
|
||||
ui.notifications.info(`Pas de rencontre pour ${index}, seulement ${rencontresAll.length} rencontres sont connues.<br>Vous pouvez aussi essayer par type (ie: mangeur, fleur, fleur2d6, ...)`)
|
||||
ui.notifications.info(`Pas de rencontre pour ${index}, seulement ${rencontresAll.length} rencontres sont connues.<br>Vous pouvez aussi essayer par type (ie: mangeur, fleur, fleur2d6, ...)`)
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@ -357,15 +357,13 @@ export class TMRRencontres {
|
||||
/* -------------------------------------------- */
|
||||
static async getRencontreAleatoire(terrain, roll = undefined) {
|
||||
if (!roll || roll <= 0 || roll > 100) {
|
||||
roll = new Roll("1d100").evaluate().total;
|
||||
roll = await RdDDice.rollTotal("1d100");
|
||||
}
|
||||
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 rencontre = duplicate(rencontresStandard.find(it => it.code == code));
|
||||
rencontre.roll = roll;
|
||||
await TMRRencontres.evaluerForceRencontre(rencontre);
|
||||
//console.log(rencontre);
|
||||
return rencontre;
|
||||
}
|
||||
|
||||
@ -374,20 +372,14 @@ export class TMRRencontres {
|
||||
const rencontre = duplicate(
|
||||
(index && index >= 0 && index < mauvaisesRencontres.length)
|
||||
? mauvaisesRencontres[index]
|
||||
: Misc.rollOneOf(mauvaisesRencontres));
|
||||
: await RdDDice.rollOneOf(mauvaisesRencontres));
|
||||
await TMRRencontres.evaluerForceRencontre(rencontre);
|
||||
return rencontre;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async evaluerForceRencontre(rencontre) {
|
||||
if (TMRRencontres.isReveDeDragon(rencontre)) {
|
||||
const ddr = await DeDraconique.ddr("selfroll")
|
||||
rencontre.force = 7 + ddr.total;
|
||||
}
|
||||
else {
|
||||
rencontre.force = new Roll(rencontre.force).evaluate().total;
|
||||
}
|
||||
rencontre.force = await new Roll(rencontre.force).evaluate().total;
|
||||
return rencontre.force;
|
||||
}
|
||||
|
||||
@ -407,58 +399,59 @@ export class TMRRencontres {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async gererRencontre(tmrDialog, data) {
|
||||
let gestion = TMRRencontres.getGestionRencontre(data.rencontre.type);
|
||||
if (data.rolled.isSuccess) {
|
||||
data.message = gestion.msgSucces(data);
|
||||
if (data.nbRounds > 1) {
|
||||
data.message += ` Au total, vous avez passé ${data.nbRounds} rounds à vous battre!`;
|
||||
static async gererRencontre(tmrDialog, rencData) {
|
||||
let gestion = TMRRencontres.getGestionRencontre(rencData.rencontre.type);
|
||||
if (rencData.rolled.isSuccess) {
|
||||
rencData.message = gestion.msgSucces(rencData);
|
||||
if (rencData.nbRounds > 1) {
|
||||
rencData.message += ` Au total, vous avez passé ${rencData.nbRounds} rounds à vous battre!`;
|
||||
}
|
||||
data.poesie = gestion.poesieSucces;
|
||||
rencData.poesie = gestion.poesieSucces;
|
||||
return gestion.postSucces;
|
||||
}
|
||||
|
||||
data.message = gestion.msgEchec(data);
|
||||
if (data.nbRounds > 1) {
|
||||
data.message += ` Vous avez passé ${data.nbRounds} rounds à lutter!`;
|
||||
rencData.message = gestion.msgEchec(rencData);
|
||||
if (rencData.nbRounds > 1) {
|
||||
rencData.message += ` Vous avez passé ${rencData.nbRounds} rounds à lutter!`;
|
||||
}
|
||||
data.poesie = gestion.poesieEchec;
|
||||
rencData.poesie = gestion.poesieEchec;
|
||||
return gestion.postEchec;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static msgEchecPasseurFou(data) {
|
||||
data.sortReserve = data.actor.data.data.reve.reserve.list[0];
|
||||
if (data.sortReserve) {
|
||||
static async msgEchecPasseurFou(tmrData) {
|
||||
tmrData.sortReserve = Misc.templateData(tmrData.actor).reve.reserve.list[0];
|
||||
if (tmrData.sortReserve) {
|
||||
// Passeur fou positionne sur la case d'un ort en réserve // TODO : Choisir le sort le plus loin ou au hasard
|
||||
data.newTMR = TMRUtility.getTMR(data.sortReserve.coord);
|
||||
tmrData.newTMR = TMRUtility.getTMR(tmrData.sortReserve.coord);
|
||||
} else {
|
||||
// Déplacement aléatoire de la force du Passeur Fou
|
||||
const newCoord = Misc.rollOneOf(TMRUtility.getTMRPortee(data.tmr.coord, data.rencontre.force));
|
||||
data.newTMR = TMRUtility.getTMR(newCoord);
|
||||
const newCoord = await RdDDice.rollOneOf(TMRUtility.getTMRPortee(tmrData.tmr.coord, tmrData.rencontre.force));
|
||||
tmrData.newTMR = TMRUtility.getTMR(newCoord);
|
||||
}
|
||||
if (data.sortReserve) {
|
||||
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}.`;
|
||||
if (tmrData.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}.`;
|
||||
}
|
||||
else {
|
||||
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}`;
|
||||
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}`;
|
||||
}
|
||||
}
|
||||
|
||||
static async postEchecPasseurFou(tmrDialog, data) {
|
||||
if (data.sortReserve) {
|
||||
await tmrDialog.processSortReserve(data.sortReserve);
|
||||
/* -------------------------------------------- */
|
||||
static async postEchecPasseurFou(tmrDialog, tmrData) {
|
||||
if (tmrData.sortReserve) {
|
||||
await tmrDialog.processSortReserve(tmrData.sortReserve);
|
||||
}
|
||||
await tmrDialog.forceDemiRevePosition(data.newTMR.coord);
|
||||
if (data.sortReserve) {
|
||||
await tmrDialog.forceDemiRevePosition(tmrData.newTMR.coord);
|
||||
if (tmrData.sortReserve) {
|
||||
tmrDialog.close();
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async onPostEchecTourbillon(tmrDialog, data, cases) {
|
||||
await data.actor.reveActuelIncDec(-cases);
|
||||
await TMRRencontres._toubillonner(tmrDialog, data.actor, cases);
|
||||
static async onPostEchecTourbillon(tmrDialog, tmrData, cases) {
|
||||
await tmrData.actor.reveActuelIncDec(-cases);
|
||||
await TMRRencontres._toubillonner(tmrDialog, tmrData.actor, cases);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -468,23 +461,26 @@ export class TMRRencontres {
|
||||
await data.actor.santeIncDec("vie", -1); // Et -1 PV
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async _toubillonner(tmrDialog, actor, cases) {
|
||||
let coord = actor.data.data.reve.tmrpos.coord;
|
||||
let coord = Misc.templateData(actor).reve.tmrpos.coord;
|
||||
for (let i = 0; i < cases; i++) {
|
||||
coord = TMRUtility.deplaceTMRAleatoire(actor, coord).coord;
|
||||
coord = await TMRUtility.deplaceTMRAleatoire(actor, coord).coord;
|
||||
}
|
||||
await tmrDialog.forceDemiRevePosition(coord)
|
||||
}
|
||||
|
||||
static async onPostSuccessReveDeDragon(tmrDialog, data) {
|
||||
if (data.rolled.isPart) {
|
||||
await data.actor.appliquerExperience(data.rolled, 'reve', data.competence);
|
||||
/* -------------------------------------------- */
|
||||
static async onPostSuccessReveDeDragon(tmrDialog, tmrData) {
|
||||
if (tmrData.rolled.isPart) {
|
||||
await tmrData.actor.appliquerExperience(tmrData.rolled, 'reve', tmrData.competence);
|
||||
}
|
||||
await data.actor.resultCombatReveDeDragon(data);
|
||||
await tmrData.actor.resultCombatReveDeDragon(tmrData);
|
||||
}
|
||||
|
||||
static async onPostEchecReveDeDragon(tmrDialog, data) {
|
||||
await data.actor.resultCombatReveDeDragon(data);
|
||||
/* -------------------------------------------- */
|
||||
static async onPostEchecReveDeDragon(tmrDialog, tmrData) {
|
||||
await tmrData.actor.resultCombatReveDeDragon(tmrData);
|
||||
tmrDialog.close();
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,7 @@
|
||||
import { TMRRencontres } from "./tmr-rencontres.js";
|
||||
import { Misc } from "./misc.js";
|
||||
import { Grammar } from "./grammar.js";
|
||||
import { RdDDice } from "./rdd-dice.js";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
const TMRMapping = {
|
||||
@ -335,9 +337,20 @@ export class TMRUtility {
|
||||
return TMRMapping[coord]?.label ?? (coord + ": case inconnue");
|
||||
}
|
||||
|
||||
static getTMRType(coord) {
|
||||
const tmr = TMRMapping[coord];
|
||||
return Misc.upperFirst(TMRType[tmr.type].name);
|
||||
}
|
||||
|
||||
static getTMRDescr(coord) {
|
||||
const tmr = TMRMapping[coord];
|
||||
return Grammar.articleDetermine(tmr.genre) + ' ' + tmr.label;
|
||||
return Grammar.articleDetermine(tmr.type) + ' ' + tmr.label;
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -374,12 +387,13 @@ export class TMRUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static getDirectionPattern() {
|
||||
return Misc.rollOneOf(tmrRandomMovePatten);
|
||||
static async getDirectionPattern() {
|
||||
return await RdDDice.rollOneOf(tmrRandomMovePatten);
|
||||
}
|
||||
|
||||
static deplaceTMRAleatoire(actor, coord) {
|
||||
return TMRUtility.deplaceTMRSelonPattern(actor, coord, TMRUtility.getDirectionPattern(), 1);
|
||||
/* -------------------------------------------- */
|
||||
static async deplaceTMRAleatoire(actor, coord) {
|
||||
return TMRUtility.deplaceTMRSelonPattern(actor, coord, await TMRUtility.getDirectionPattern(), 1);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -411,8 +425,8 @@ export class TMRUtility {
|
||||
return TMRUtility.filterTMR(filter).map(it => it.coord);
|
||||
}
|
||||
|
||||
static getTMRAleatoire(filter = it => true) {
|
||||
return Misc.rollOneOf(TMRUtility.filterTMR(filter))
|
||||
static async getTMRAleatoire(filter = it => true) {
|
||||
return await RdDDice.rollOneOf(TMRUtility.filterTMR(filter))
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@ -465,12 +479,14 @@ export class TMRUtility {
|
||||
return caseList;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static distanceTMR(coord1, coord2) {
|
||||
let pos1 = this.convertToCellPos(coord1);
|
||||
let pos2 = this.convertToCellPos(coord2);
|
||||
return this.distancePosTMR(pos1, pos2);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static distancePosTMR(pos1, pos2) {
|
||||
const dx = pos2.x - pos1.x;
|
||||
const dy = pos2.y - pos1.y;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Grammar } from "../grammar.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDDice } from "../rdd-dice.js";
|
||||
import { tmrColors, tmrConstants, tmrTokenZIndex, TMRUtility } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
@ -15,7 +16,7 @@ export class Conquete extends Draconique {
|
||||
async onActorCreateOwned(actor, item) { await this._creerConquete(actor, item); }
|
||||
|
||||
code() { return 'conquete' }
|
||||
tooltip(linkData) { return `La ${this.tmrLabel(linkData)} doit être conquise` }
|
||||
tooltip(linkData) { return `${this.tmrLabel(linkData)}: doit être conquis` }
|
||||
img() { return 'icons/svg/combat.svg' }
|
||||
|
||||
createSprite(pixiTMR) {
|
||||
@ -29,14 +30,14 @@ export class Conquete extends Draconique {
|
||||
}
|
||||
|
||||
async _creerConquete(actor, queue) {
|
||||
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 => Misc.data(it).data.coord);
|
||||
let possibles = TMRUtility.filterTMR(tmr => !TMRUtility.isCaseHumide(tmr) && !existants.includes(tmr.coord));
|
||||
let conquete = Misc.rollOneOf(possibles);
|
||||
await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue._id);
|
||||
let conquete =await RdDDice.rollOneOf(possibles);
|
||||
await this.createCaseTmr(actor, 'Conquête: ' + conquete.label, conquete, queue.id);
|
||||
}
|
||||
|
||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||
await actor.deleteOwnedItem(casetmr.data.sourceid);
|
||||
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -13,20 +13,20 @@ export class Debordement extends Draconique {
|
||||
manualMessage() { return false }
|
||||
async onActorCreateOwned(actor, souffle) {
|
||||
const existants = actor.data.items.filter(it => this.isCase(it)).map(it => it.data.coord);
|
||||
const tmr = TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord)));
|
||||
await this.createCaseTmr(actor, 'Debordement: ' + tmr.label, tmr, souffle._id);
|
||||
const tmr = await TMRUtility.getTMRAleatoire(it => !(TMRUtility.isCaseHumide(it) || existants.includes(it.coord)));
|
||||
await this.createCaseTmr(actor, 'Debordement: ' + tmr.label, tmr, souffle.id);
|
||||
}
|
||||
|
||||
code() { return 'debordement' }
|
||||
tooltip(linkData) { return `Débordement en ${this.tmrLabel(linkData)}` }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/wave.svg' }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/wave.webp' }
|
||||
|
||||
createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(), {
|
||||
color: tmrColors.casehumide,
|
||||
zIndex: tmrTokenZIndex.casehumide,
|
||||
taille: tmrConstants.twoThird,
|
||||
decallage: tmrConstants.bottom
|
||||
alpha: 0.6,
|
||||
taille: tmrConstants.full,
|
||||
decallage: tmrConstants.center
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Grammar } from "../grammar.js";
|
||||
import { Misc } from "../misc.js";
|
||||
import { RdDDice } from "../rdd-dice.js";
|
||||
import { tmrColors, tmrConstants, tmrTokenZIndex, TMRType, TMRUtility } from "../tmr-utility.js";
|
||||
import { Draconique } from "./draconique.js";
|
||||
|
||||
@ -13,7 +14,7 @@ export class Desorientation extends Draconique {
|
||||
manualMessage() { return false }
|
||||
|
||||
async onActorCreateOwned(actor, souffle) {
|
||||
const type = Misc.rollOneOf(this._typesPossibles(actor));
|
||||
const type = await RdDDice.rollOneOf(this._typesPossibles(actor));
|
||||
console.log("désorientation", type);
|
||||
souffle.name += ": " + TMRType[type].name;
|
||||
await this._creerCasesTmr(actor, type, souffle);
|
||||
@ -43,7 +44,7 @@ export class Desorientation extends Draconique {
|
||||
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));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,4 @@
|
||||
import { Misc } from "../misc.js";
|
||||
import { TMRUtility } from "../tmr-utility.js";
|
||||
import { PixiTMR } from "./pixi-tmr.js";
|
||||
|
||||
@ -8,11 +9,11 @@ const registeredEffects = [
|
||||
* Définition des informations d'une "draconique" (queue, ombre, tête, souffle) qui influence les TMR
|
||||
*/
|
||||
export class Draconique {
|
||||
static isCaseTMR(element) { return element.type == 'casetmr'; }
|
||||
static isQueueDragon(element) { return element.type == 'queue' || element.type == 'ombre'; }
|
||||
static isSouffleDragon(element) { return element.type == 'souffle'; }
|
||||
static isTeteDragon(element) { return element.type == 'tete'; }
|
||||
static isQueueSouffle(it) { return Draconique.isQueueDragon(it) || Draconique.isSouffleDragon(it); }
|
||||
static isCaseTMR(itemData) { return itemData.type == 'casetmr'; }
|
||||
static isQueueDragon(itemData) { return itemData.type == 'queue' || itemData.type == 'ombre'; }
|
||||
static isSouffleDragon(itemData) { return itemData.type == 'souffle'; }
|
||||
static isTeteDragon(itemData) { return itemData.type == 'tete'; }
|
||||
static isQueueSouffle(itemData) { return Draconique.isQueueDragon(itemData) || Draconique.isSouffleDragon(itemData); }
|
||||
|
||||
tmrLabel(linkData) { return TMRUtility.getTMRLabel(linkData.data.coord); }
|
||||
|
||||
@ -37,7 +38,8 @@ export class Draconique {
|
||||
* @returns true si l'item correspond
|
||||
*/
|
||||
match(item) {
|
||||
return Draconique.isQueueDragon(item) || Draconique.isSouffleDragon(item) || Draconique.isTeteDragon(item);
|
||||
const itemData = Misc.data(item);
|
||||
return Draconique.isQueueDragon(itemData) || Draconique.isSouffleDragon(itemData) || Draconique.isTeteDragon(itemData);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -110,35 +112,40 @@ export class Draconique {
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {*} it un item à tester
|
||||
* @param {*} item un item à tester
|
||||
* @param {*} coord les coordonnées d'une case. Si undefined toute case du type correspondra,
|
||||
*/
|
||||
isCase(it, coord = undefined) {
|
||||
return Draconique.isCaseTMR(it) && it.data.specific == this.code() && (coord ? it.data.coord == coord : true);
|
||||
isCase(item, coord = undefined) {
|
||||
const itemData = Misc.data(item);
|
||||
return Draconique.isCaseTMR(itemData) && itemData.data.specific == this.code() && (coord ? itemData.data.coord == coord : true);
|
||||
}
|
||||
|
||||
find(list, coord = undefined) {
|
||||
return list.find(c => this.isCase(c, coord));
|
||||
return list.find(c => this.isCase(Misc.data(c), coord));
|
||||
}
|
||||
|
||||
async createCaseTmr(actor, label, tmr, sourceId = undefined) {
|
||||
await actor.createOwnedItem({
|
||||
name: label, type: 'casetmr', img: this.img(), _id: randomID(16),
|
||||
const casetmrData = {
|
||||
name: label, type: 'casetmr', img: this.img(),
|
||||
data: { coord: tmr.coord, specific: this.code(), sourceid: sourceId }
|
||||
});
|
||||
};
|
||||
await actor.createEmbeddedDocuments('Item', [casetmrData]);
|
||||
}
|
||||
|
||||
async deleteCasesTmr(actor, draconique) {
|
||||
let caseTmrs = actor.data.items.filter(it => this.isCase(it) && it.data.sourceid == draconique._id);
|
||||
for (let casetmr of caseTmrs) {
|
||||
await actor.deleteOwnedItem(casetmr._id);
|
||||
}
|
||||
let caseTmrs = actor.data.items.filter(it => this.isCaseForSource(it, draconique));
|
||||
await actor.deleteEmbeddedDocuments('Item', caseTmrs.map(it => it.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) {
|
||||
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) {
|
||||
await actor.deleteOwnedItem(casetmr._id);
|
||||
onRemoveToken(tmr, casetmr);
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +186,7 @@ export class EffetsDraconiques {
|
||||
}
|
||||
|
||||
static toItems(item) {
|
||||
return (item?.entity === 'Actor') ? item.data.items : (item?.entity === 'Item') ? [Misc.data(item)] : [];
|
||||
return (item?.documentName === 'Actor') ? item.data.items : (item?.documentName === 'Item') ? [Misc.data(item)] : [];
|
||||
}
|
||||
|
||||
}
|
@ -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 ouvertes = TMRUtility.filterTMR(it => it.type == 'cite' && !existants.includes(it.coord));
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,26 +13,26 @@ export class Pelerinage extends Draconique {
|
||||
manualMessage() { return false }
|
||||
|
||||
async onActorCreateOwned(actor, queue) {
|
||||
let tmr = TMRUtility.getTMRAleatoire();
|
||||
await this.createCaseTmr(actor, 'Pèlerinage: ' + tmr.label, tmr, queue._id);
|
||||
let tmr = await TMRUtility.getTMRAleatoire();
|
||||
await this.createCaseTmr(actor, 'Pèlerinage: ' + tmr.label, tmr, queue.id);
|
||||
}
|
||||
|
||||
|
||||
code() { return 'pelerinage' }
|
||||
tooltip(linkData) { return `Votre pèlerinage en ${this.tmrLabel(linkData)}` }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/pelerin.svg' }
|
||||
img() { return 'systems/foundryvtt-reve-de-dragon/icons/tmr/pelerin.webp' }
|
||||
|
||||
createSprite(pixiTMR) {
|
||||
return pixiTMR.sprite(this.code(), {
|
||||
zIndex: tmrTokenZIndex.conquete,
|
||||
alpha: 1,
|
||||
taille: tmrConstants.twoThird,
|
||||
decallage: tmrConstants.right
|
||||
taille: tmrConstants.full,
|
||||
decallage: tmrConstants.center
|
||||
});
|
||||
}
|
||||
|
||||
async onActorDeleteCaseTmr(actor, casetmr) {
|
||||
await actor.deleteOwnedItem(casetmr.data.sourceid);
|
||||
await actor.deleteEmbeddedDocuments('Item', [casetmr.data.sourceid]);
|
||||
}
|
||||
|
||||
}
|
||||
|