Nouvelle fenêtre de jets de dés
1
assets/actions/attaque.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,0)" style=""><path d="m214.02 19.115-.02.06a433.415 433.415 0 0 1 106.393 58.446L368.02 158.4C292.254 72.063 181.72 20.678 64.66 20.604c-14.96-.01-30.027.834-45.14 2.535v18.8c108.174-12.774 213.91 21.292 293.527 88.554l42.314 97.416C290.887 132.486 182.425 73.885 66.395 73.21a349.119 349.119 0 0 0-46.879 2.906v18.85c98.998-13.552 196.12 18.532 267.11 82.264l30.708 87.82c-53.922-85.58-148.482-138.656-249.986-139.69a297.451 297.451 0 0 0-47.83 3.398v18.914c93.33-15.18 185.38 18.05 247.677 83.27l20.694 83.917C246.555 230.42 160.67 176.716 67.7 175.423a248.202 248.202 0 0 0-48.182 4.06v19.036c89.513-17.794 178.655 19.16 230.357 89.468l4.62 73.348c-28.973-83.013-107.888-136.692-193.257-135.87a201.938 201.938 0 0 0-41.72 4.78v19.188c77.22-18.904 155.333 13.983 197.095 77.14l5.873 57.49c23.33-6.283 47.534-13.218 68.727-20.873 19.194-6.93 35.884-14.525 46.596-22.038 5.354-3.756 9.142-7.478 11.174-10.574 2.033-3.096 2.47-5.184 2.098-7.59l-1.252-8.123 137.074-39.556C446.897 159.92 363.67 69.964 260.654 19.114H214.02zm278.86 273.922-40.196 11.6c1.63 18.66-4.666 36.567-16.397 52.043-14.18 18.707-35.934 34.627-62.363 48.257-45.23 23.33-104.45 39.877-164.397 47.97l4.38 16.35c68.63-7.66 143.34-22.038 198.17-48.538 30.517-14.75 54.633-33.123 68.722-55.33 12.74-20.084 17.775-43.384 12.08-72.353zm-58.513 16.885-65.027 18.765c-.736 4.345-2.345 8.51-4.733 12.147-3.925 5.98-9.462 10.986-16.068 15.62-13.213 9.266-30.996 17.098-50.978 24.316-31.927 11.53-68.41 20.998-99.558 29.134l6.644 24.79c59.027-7.79 117.64-24.153 160.71-46.366 24.828-12.805 44.388-27.573 56.037-42.94 8.804-11.614 13.283-23.135 12.972-35.466zm-261.754 77.43-33.033 8.85 8.197 30.59c10.812 3.95 18.623 14.38 18.623 26.485 0 6.87-2.52 13.2-6.673 18.114l4.716 17.6 33.034-8.85-24.864-92.788zM138.22 443.79c-1.49 0-2.88.33-4.12.91l-75.6 20.255a30.49 30.49 0 0 1 4.625 16.14c0 .67-.03 1.33-.072 1.987l75.96-20.352c4.96-.386 8.698-4.37 8.698-9.453 0-5.35-4.138-9.488-9.49-9.488zM32.327 468.985c-6.798 0-12.11 5.312-12.11 12.11 0 6.798 5.312 12.11 12.11 12.11 6.798 0 12.111-5.312 12.111-12.11 0-6.798-5.313-12.11-12.11-12.11z" fill="#fff" fill-opacity="1"></path></g></svg>
|
After Width: | Height: | Size: 2.2 KiB |
1
assets/actions/comp.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,0)" style=""><path d="M119.1 25v.1c-25 3.2-47.1 32-47.1 68.8 0 20.4 7.1 38.4 17.5 50.9L99.7 157 84 159.9c-13.7 2.6-23.8 9.9-32.2 21.5-8.5 11.5-14.9 27.5-19.4 45.8-8.2 33.6-9.9 74.7-10.1 110.5h44l11.9 158.4h96.3L185 337.7h41.9c0-36.2-.3-77.8-7.8-111.7-4-18.5-10.2-34.4-18.7-45.9-8.6-11.4-19.2-18.7-34.5-21l-16-2.5L160 144c10-12.5 16.7-30.2 16.7-50.1 0-39.2-24.8-68.8-52.4-68.8-2.9 0-4.7-.1-5.2-.1zM440 33c-17.2 0-31 13.77-31 31s13.8 31 31 31 31-13.77 31-31-13.8-31-31-31zM311 55v48H208v18h103v158h-55v18h55v110H208v18h103v32h80.8c-.5-2.9-.8-5.9-.8-9 0-3.1.3-6.1.8-9H329V297h62.8c-.5-2.9-.8-5.9-.8-9 0-3.1.3-6.1.8-9H329V73h62.8c-.5-2.92-.8-5.93-.8-9 0-3.07.3-6.08.8-9H311zm129 202c-17.2 0-31 13.8-31 31s13.8 31 31 31 31-13.8 31-31-13.8-31-31-31zm0 160c-17.2 0-31 13.8-31 31s13.8 31 31 31 31-13.8 31-31-13.8-31-31-31z" fill="#fff" fill-opacity="1"></path></g></svg>
|
After Width: | Height: | Size: 996 B |
1
assets/actions/defense.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,0)" style=""><path d="M80 32c-64 256 48 416 176 464 128-48 240-208 176-464-112 32-240 32-352 0zm99.3 52.9c14.7 27.9 40.1 26.4 65 26.4l53.9 1.5 7.8 25 77.1 10.3 3.5 49.9c-27.9 7.4-83.7 5.9-83.8 17.7-.2 20.6 36.3 16.2 78.1 5.9L356.7 276l-61.4 4.4c3.8 46.4-1.2 77.6-35.6 110.7l-21.9-55.3c-12.6 22.6-30 38.8-57.3 41.4 10.6-26 19.1-46.7 9.7-76.3-13.5 13.3-35.1 18.7-64.8 16.7 31.6-49 48.3-101.9 62.1-151.9l-23.2-20.6c-6.6-23.5-1.3-44.1 15-60.2z" fill="#fff" fill-opacity="1"></path></g></svg>
|
After Width: | Height: | Size: 621 B |
1
assets/actions/defense1.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,0)" style=""><path d="M261.563 64.28A191.758 191.758 0 0 0 64.25 256a191.758 191.758 0 1 0 383.5 0A191.758 191.758 0 0 0 261.562 64.28zm-4.625 9.126 8.937 5.156v10.313l-8.938 5.156-8.906-5.155V78.562l8.907-5.156zm3.53 29.25A153.407 153.407 0 0 1 409.407 256a153.407 153.407 0 0 1-306.812 0A153.407 153.407 0 0 1 260.47 102.656zm-11.53 20.03a133.607 133.607 0 0 0-65.157 20.908V368.22a133.607 133.607 0 0 0 65.157 21.092V122.688zm17.687.314v266.125a133.607 133.607 0 0 0 63.438-22.03V145a133.607 133.607 0 0 0-63.438-22zm-100.5 34.344A133.607 133.607 0 0 0 122.405 256a133.607 133.607 0 0 0 43.72 98.78V157.345zm-60.72 1.625 8.907 5.155v10.28l-8.906 5.157-8.937-5.156v-10.28l8.936-5.157zm300.5 0 8.94 5.155v10.28l-8.94 5.157-8.905-5.156v-10.28l8.906-5.157zm-58.155.093V353.03A133.607 133.607 0 0 0 389.594 256a133.607 133.607 0 0 0-41.844-96.938zm57.813 173.125 8.937 5.156v10.312l-8.938 5.156-8.906-5.156v-10.312l8.906-5.156zm-299.813.718 8.938 5.156v10.313l-8.938 5.156-8.938-5.155v-10.313l8.938-5.156zm149.906 85.188 8.938 5.156v10.313l-8.938 5.156-8.906-5.158v-10.31l8.906-5.156z" fill="#fff" fill-opacity="1"></path></g></svg>
|
After Width: | Height: | Size: 1.2 KiB |
66
assets/actions/jeu.svg
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
viewBox="0 0 310.12469 310.12469"
|
||||
version="1.1"
|
||||
id="svg6"
|
||||
sodipodi:docname="jeu.svg"
|
||||
width="310.12469"
|
||||
height="310.12469"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs10" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="2532"
|
||||
inkscape:window-height="1492"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="1.4355469"
|
||||
inkscape:cx="155.06205"
|
||||
inkscape:cy="142.25079"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg6" />
|
||||
<g
|
||||
class=""
|
||||
transform="translate(-100.93795,-121.74921)"
|
||||
id="g4">
|
||||
<path
|
||||
d="m 477.518,181.966 a 25,25 0 0 1 -34.91,23 l -62.29,150.26 h -248.92 l -62.24,-150.19 a 25,25 0 1 1 9.73,-7.29 l 87,71.2 20.92,-126.4 a 25,25 0 1 1 14.7,-1.85 l 54.31,117 54.42,-117.3 a 25,25 0 1 1 14.58,2.08 l 20.93,126.42 87.26,-71.3 a 25,25 0 1 1 44.51,-15.63 z m -71.66,241.25 h -300 v 60 h 300 z m -27.75,-52 h -244.22 v 36 h 244.22 z"
|
||||
fill="#ffffff"
|
||||
fill-opacity="1"
|
||||
transform="matrix(0.7,0,0,0.7,76.8,76.8)"
|
||||
id="path2" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 2.1 KiB |
63
assets/actions/meditation.svg
Normal file
@@ -0,0 +1,63 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
viewBox="0 0 512 512"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
sodipodi:docname="meditation1.svg"
|
||||
width="512"
|
||||
height="512"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<metadata
|
||||
id="metadata14">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs12" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="1"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="3840"
|
||||
inkscape:window-height="2054"
|
||||
id="namedview10"
|
||||
showgrid="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="1.4355469"
|
||||
inkscape:cx="254.56378"
|
||||
inkscape:cy="255.99978"
|
||||
inkscape:window-x="-11"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg8">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid856" />
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
id="polygon2"
|
||||
style="fill:#ffffff;fill-opacity:1;stroke:none"
|
||||
d="M 256,0 0,256 256,512 512,256 Z m 5.11719,62.361328 c 8.239,0 15.89463,4.297288 21.83203,12.054688 5.2108,6.811 8.83798,16.231192 9.64648,26.841794 -8.4868,-3.970403 -17.26742,-6.37191 -26.14062,-7.13281 v 12.81836 c 8.5484,0.9429 17.03537,3.85822 25.48437,8.64062 -1.442,8.41469 -4.67333,15.84043 -8.99023,21.48243 -5.9367,7.7574 -13.59443,12.05468 -21.83203,12.05468 -8.2376,0 -15.8726,-4.29728 -21.8086,-12.05468 -4.452,-5.8184 -7.76497,-13.52864 -9.14257,-22.26953 7.8043,-4.21541 15.53348,-6.75681 23.20898,-7.72071 V 94.191406 c -7.938,0.763 -15.87192,2.852576 -23.66992,6.300784 0.9261,-10.297007 4.51857,-19.430374 9.60547,-26.076174 5.936,-7.7581 13.57099,-12.052735 21.80859,-12.052735 z M 228.50391,144.4375 c 0.14,0.1883 0.27391,0.38286 0.41601,0.56836 7.8876,10.3082 19.34232,17.19336 32.19922,17.19336 12.8569,0 24.31162,-6.88586 32.19922,-17.19336 0.1421,-0.1862 0.27797,-0.37936 0.41797,-0.56836 7.2765,3.3453 12.81763,7.79108 15.76953,12.86328 h 0.0449 l 29.11524,45.10547 35.48046,-15.37891 c 20.5632,-11.2833 43.10446,16.80074 21.43946,29.18164 l -66.12891,30.84571 -25.74609,-33.90821 c -11.6662,23.2505 -11.80448,46.48779 6.66992,69.73829 37.3275,-3.0275 65.31156,3.90026 69.47656,19.44726 3.4104,12.7316 -9.91357,28.42679 -33.35937,42.45899 l -66.10743,-21.9629 33.66602,-11.17773 -4.11328,-12.4043 -50.29102,16.69141 -50.26757,-16.69141 -4.11133,12.4043 126.1289,41.89063 15.53321,37.60351 -64.44532,-20.10351 0.0234,-0.22071 c -0.2989,-0.0168 -0.5782,-0.0463 -0.875,-0.0645 l -0.30664,-0.0879 h -1.09375 c -43.1116,-2.7132 -70.90445,-9.13273 -109.87695,-29.64063 -19.6938,-13.027 -30.49667,-27.09126 -27.38867,-38.69726 h -0.0215 c 3.4755,-12.9682 23.51598,-19.95189 51.73438,-20.14649 5.3179,-0.0364 10.93654,0.18537 16.77734,0.63477 19.418,-23.6082 20.76969,-47.21649 7.67969,-70.80859 l -26.6211,35.04296 -66.1289,-30.84375 c -21.665,-12.3816 0.87304,-40.46424 21.43554,-29.18164 l 35.46094,15.37891 29.13672,-45.10547 0.26172,0.0664 c 2.9421,-5.1016 8.50701,-9.56969 15.81641,-12.92969 z m -44.58008,217.70117 c 12.7582,5.6602 24.87218,9.90172 37.20898,13.10352 l -48.91406,15.24609 z" />
|
||||
</svg>
|
After Width: | Height: | Size: 3.8 KiB |
1
assets/actions/oeuvre.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(2,-1)" style=""><path d="m375.2 23.61-12.7 12.7 24.5 24.5c.5-1.2 1-2.3 1.5-3.5 2.4-6.6 4.1-12.4 4.9-15.5zm33.3 30.5c-.9 3-1.9 5.9-3.3 9.6-4 10.8-9.1 23.4-20.2 30.4-4 2.4-8.1 2.6-11.2 2.3-3.1-.3-5.6-1.1-7.5-1.6-1.7-.4-2.6-.6-3.2-.7-.6.9-1.2 2.2-1.6 4.5-.8 3.19-1 7.49-.8 11.59.1 6 .7 10.5 1.2 13.1l26.8 26.8c2.6.4 7.1 1 13 1.2 7.5.1 14.3-1.8 16-2.7-.1-.8-.2-1.4-.6-2.9-.5-2-1.3-4.5-1.7-7.6-.3-3.1 0-7.3 2.3-11.2 7-11.1 19.6-16.2 30.5-20.3 3.6-1.4 6.6-2.2 9.6-3.1l-16.4-32.89zm-67.2 3.4-12.7 12.7 17.4 17.5c1.3-2.9 3-5.6 5.6-7.9 2.5-2.2 5.6-3.3 8.3-3.7zm128.9 60.99c-3.2.8-9.1 2.4-15.7 5-1.1.4-2.2.8-3.4 1.3l24.6 24.6 12.7-12.7zm-120.7 17.9L217.4 262.3l9.8 9.8 129-129zm86.3 15.5c-.4 2.8-1.5 6-3.8 8.5s-4.8 4.3-7.5 5.6l17.3 17.3 12.7-12.7zm-66.9 3.9L240 284.9l9.7 9.6 125.9-132zm-226.3 94.5c-30.4 0-60.87 11.6-84.13 34.9-46.53 46.5-46.53 121.7 0 168.3C105 500 180.2 500 226.8 453.5c35.8-35.9 43.9-88.5 24.7-132.2L156.8 416l14.9 14.9-12.8 12.7-90.46-90.5 12.73-12.7 14.75 14.7 94.78-94.7c-15.3-6.8-31.7-10.1-48.1-10.1zm60.6 23.2-94.5 94.4 11.3 11.3 94.5-94.4zm24 24L132.7 392l11.2 11.2 94.6-94.4z" fill="#fff" fill-opacity="1"></path></g></svg>
|
After Width: | Height: | Size: 1.2 KiB |
65
assets/actions/sort.svg
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="66.69709mm"
|
||||
height="66.69709mm"
|
||||
viewBox="0 0 378.10574 378.10571"
|
||||
version="1.1"
|
||||
id="svg3"
|
||||
sodipodi:docname="sort.svg"
|
||||
inkscape:version="1.0.1 (3bc2e813f5, 2020-09-07)">
|
||||
<metadata
|
||||
id="metadata9">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs7" />
|
||||
<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="2054"
|
||||
id="namedview5"
|
||||
showgrid="false"
|
||||
inkscape:zoom="3.887601"
|
||||
inkscape:cx="72.254869"
|
||||
inkscape:cy="97.300114"
|
||||
inkscape:window-x="-11"
|
||||
inkscape:window-y="-11"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3"
|
||||
inkscape:document-rotation="0"
|
||||
inkscape:snap-text-baseline="true"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" />
|
||||
<path
|
||||
id="Sélection #2"
|
||||
fill="none"
|
||||
stroke="black"
|
||||
stroke-width="1"
|
||||
d="M 189.05286,0 378.10571,189.05286 189.05285,378.10571 0,189.05286 Z m 98.94184,241.93328 c -0.88,-10.41 -2.89,-10.17 -9.87,-16.75 l -5.39,-5.72 c -2.61,-2.12 -6.9,-3.02 -8.72,-5.91 -1.19,-1.9 -0.91,-4.46 -1.28,-6.62 -3.40308,-4.90559 -2.01923,-20.20245 -2.01923,-26.63889 3.88586,-9.60746 4.36923,-1.69111 7.45923,-14.36111 0.62,-2.55 2.32,-6.14 1.21,-8.69 -1.07,-2.43 -3.44,-2.03 -6.71,-5.17 -5.66937,-7.30653 -11.39498,-14.88252 -18.68,-20.92 -23.49144,-15.67176 -34.12005,-20.68725 -60,-20.32 -8.54383,0.23148 -13.2432,0.66798 -20,2.68 -19.05,6.09 -27.58,11.85 -41.76999,25.79 -8.08,7.96 -7.17,10.3 -10.91,14.41 -3.1,3.4 -6.12,3.44 -6.73,7.27 -0.64,1.83 -0.09,3.98 0,5.78 1.91418,8.65633 2.50026,3.00305 7.73101,9.8295 1.38405,9.6854 0.3222,25.26042 -0.70608,33.05113 -2.53556,2.89228 -2.29493,5.91937 -3.63493,7.97937 -1.62,2.49 -4.35,2.16 -7.77,5.03 -5.170004,4.32 -4.470004,8.06 -13.210004,13.28 1.78,5.5 4.63,5.91 10,6 z M 195.6316,118.20709 c 11.22808,5.82176 1.31866,21.02928 -11.27386,31.1911 13.0336,5.31132 -0.79998,6.64062 23.09132,6.48796 l 32.86359,-0.54563 13.5005,1.22254 7.27084,3.68304 c -4.13,5.49 -2.71929,1.23718 -2.08929,8.68718 h -4 c -0.28,-1.68 -0.54282,-4.85331 -1.87282,-6.17331 -3.32127,-0.17387 -9.61514,-0.5831 -13.55025,0.47743 -0.17052,3.22972 -0.29693,4.01588 -0.57693,5.69588 l -3.40923,-0.34102 c -0.28,-1.68 0.27564,-3.83025 -1.05436,-5.15025 -3.7305,-0.17387 -10.29718,-0.7195 -13.48204,0.40923 -1.33,1.32 -0.77437,3.40204 -1.05437,5.08204 h -3 c -0.28,-1.68 0.071,-3.08 -0.91796,-5.08204 -2.83922,-1.53335 -14.39204,-0.93796 -18.08204,-0.91796 -1.96,0.01 -5.02,-0.11 -6.68,1.02 -0.19823,6.27508 -0.4088,8.38327 1.52129,9.86916 l 20.15871,0.0399 v 37.07089 h -19.09 c 0.0887,-5.45486 2.17,-22.09 0,-25.77 -2.24,-3.53 -10.37,-4.58 -13.31,-1.63 -0.59765,14.41964 -0.37159,20.85123 -0.92619,27.34486 -16.5374,0 -13.4074,0.42 -16.5374,0 l -0.13641,-21.94486 c -0.0284,-4.56991 -0.5617,-9.93269 1.12488,-14.46674 3.57532,-2.18241 14.40143,0.2341 20.38143,-0.7259 1.06669,-3.31458 1.12908,-6.5781 0.80651,-10.05451 -2.74793,-0.83105 -4.76282,-0.70285 -7.31282,-0.75285 h -11 c -7.39,0.05 -9.43418,2.79797 -7.61418,10.68797 l -6.48228,0.24114 c 0.72,-2.06 1.97646,-7.02474 0.81646,-9.16474 -1.7,-3.14 -11.93127,-2.75719 -14.21127,-0.43719 -2.03,2.07 -1.8049,7.64421 -1.24493,10.08421 l -7.37013,0.12387 c -0.24405,12.94493 0.23633,18.13752 0.10633,29.28752 -0.09,7.42 0.28,6.88722 -7.99999,7.17722 v -28 c 0,-2.48 0.22,-6.59 -1.17,-8.69 -1.62,-2.42 -4.26,-2.22 -6.83,-2.31 2.73,-7.8 6.25917,-8.9 -1.27083,-9 10.53404,-8.39725 16.12632,-16.70355 22.85717,-22.49183 5.05278,-4.9362 12.06169,-10.2231 15.11169,-11.61765 14.97984,-6.56268 20.63207,-10.69702 43.93886,-10.61671 z m -73.26379,44.49619 c -0.79548,4.04536 -1.9331,12.40663 2.6469,12.48663 10.50353,0.43469 11.50999,-8.2279 8.90999,-11.7879 -1.43,-1.96 -9.22689,-0.64873 -11.55689,-0.69873 z m 19.62689,11.59316 9.01278,-0.14468 0.91722,5.78152 c 0.10638,11.6222 0,0 0.0146,31.52202 -8.59422,-0.32911 -7.4946,-0.52202 -9.9446,-0.52202 z m 80.95177,-0.77164 8.14469,0.22835 -0.0965,36.18013 h -8 z m 19.38582,0.5305 7.6014,-0.33759 0.061,36.21557 h -8 z m -129.12528,49.01235 11.33333,-0.31493 45.72718,-0.54563 59.09028,-0.81845 33.54662,-0.27282 c 7.10809,1.39089 4.61048,5.28283 13.46463,11.36941 -49.05198,-0.38776 -122.72138,-0.48241 -173.42548,-0.8649 z"
|
||||
style="fill:#d6d2d0;fill-opacity:1;stroke:none"
|
||||
sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccccccccccccccccccccccscccccccccccccsccccccccccccccccccccccccccccccccccc" />
|
||||
</svg>
|
After Width: | Height: | Size: 5.2 KiB |
1
assets/actions/surprise-demi.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,-28)" style=""><path d="M355.102 21.097c-33.682.164-64.173 18.585-74.615 50.5 21.357-.79 23.203 53.922 23.203 53.922l41.619 6.262c-13.41 12.963-50.025 5.967-50.025 5.967-17.14 19.182-33.124 40.966-47.758 57.578-15.952 18.127-35.2 38.103-57.018 60.086-6.79 6.823 41.594-9.821 34.342-2.604-24.567 12.751-42.297 16.097-61.764 32.069-31.312 25.674-62.853 60.71-81.146 79.431-7.711 7.91-44.362 37.674 20.469 34.74 2.404 7.52-1.621 9.456-7.493 15.293-4.327 4.303-18.082.283-22.263 2.828-22.172 35.055-17.246 37.975-27.43 58.047-4.252 11.635 41.68-14.404 64.305-34.18 13.974-7.58 25.147-21.652 35.002-17.202 43.11 18.984 129.826 35.53 141.328 27.619 18.368-12.646-10.321-46.343 3.832-97.912 23.47 5.817 43.825 13.657 66.767 11.459-1.581 49.307 3.56 55.306-3.888 104.777l59.129 21.127 1.91-13.809-33.815-22.478c14.568-50.659 16.809-72.578 15.227-121.719-.16-5.372-45.168-24.325-74.492-33.133l18.593-30.412c30.393-44.788 124.141-62.055 127.932-88.258-13.02-19.676 3.022-27.384-25.092-21.912-6.295 1.318-13.771 24.346-18.023 27.213-7.843 5.276-40.655 24.477-51.951 18.377-1.9-1.026 7.246-33.441 6.85-44.78-.116-3.205-1.19-6.625-2.866-10.001.185-.64 15.24-52.482 54.809-94.016-43.978 25.134-65.332 79.925-65.354 79.98-2.207-2.134-4.476-3.983-6.639-5.423-1.916-14.7-4.819-73.02 68.598-78.776-21.427-21.177-47.704-30.78-72.283-30.66z" fill="#fff" fill-opacity="1" transform="translate(76.8, 76.8) scale(0.7, 0.7) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>
|
After Width: | Height: | Size: 1.6 KiB |
1
assets/actions/surprise-totale.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,-28)" style=""><path d="M332.031 66.13c-28.807-.01-55.439 14.149-67.88 40.65 20.79 1.744 16 55.07 16 55.07-11.814 16.687-24.73 33.186-36.589 50.146 0 0-99.046 132.283-178.378 168.025-28.049 22.593-33.305 36.532-44.137 52.649-4.877 9.54 9.257 14.324 11.701 13.2 22.726-10.461 25.176-20.866 47.07-35.675 12.805-5.026 23.839-15.9 31.854-11.049 34.962 20.86 107.556 44.28 118.271 38.706 17.857-9.263-5.78-43.585 16.174-89.057 31.97-3.352 58.916-.885 88.332-12.094 3.483 50.279 10.106 54.59 6.766 107.092l71.2 1.045.698-14.61-41.814-11.105c11.528-56.054 11.816-78.996 4.672-127.996-.956-6.622-53.746-8.275-81.012-3.79 24.449-24.202 40.274-45.24 47.506-68.44l.027.189c7.637 15.923 30.083 33.958 35.336 37.125 27.704 11.048 38.214 7.982 62.955 3.887 4.907-.784 27.47 24.537 44.807 9.597 2.642-20.238 16.522-20.369-4.938-32.71-4.847-2.73-27.063 7.462-31.418 6.898-20.21-2.481-30.954-5.211-58.45-12.703-10.23-13.187-32.676-56.136-55.43-59.744 6.535-14.15 28.226-53.108 73.664-66.237-20.943-26.54-49.925-39.057-76.987-39.068zm82.405 46.722c-46.658 19.516-58.266 50.4-58.266 50.4l9.916 7.644s9.646-4.765 48.35-58.044zm23.04 160.005-4.658 11.418c5.233-.083 10.425.47 15.328 1.608-12.774 30.856-23.938 59.635-28.181 93.094l-.908 7.558 4.863-5.889c20.805-25.671 32.303-55.25 44.95-85.78 4.203 2.656 8.24 5.885 12.071 9.35l4.78-11.374-20.518-8.526-31.767 66.579 24.062-69.713-20.021-8.325z" fill="#fff" fill-opacity="1" transform="translate(76.8, 76.8) scale(0.7, 0.7) rotate(0, 256, 256) skewX(0) skewY(0)"></path></g></svg>
|
After Width: | Height: | Size: 1.6 KiB |
1
assets/actions/tache.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" style="height: 256px; width: 256px;"><g class="" transform="translate(0,0)" style=""><path d="M56.813 18.438c-.47-.005-.938.014-1.407.03-.625.023-1.252.066-1.875.126-7.468.72-14.682 4.148-22.31 11.125-9.985 9.128-12.863 17.66-11.407 27.718 1.455 10.056 8.353 22.236 21.125 34.906 2.895 2.872 6.126 5.737 9.593 8.625 1.27 1.055 2.565 2.13 3.907 3.186a200.62 200.62 0 0 0 3.438 2.656c.232.175.454.358.688.532C74.71 119.38 95.558 131.28 120.25 142.22c159.723 161.31 288.815 297.553 374.594 352.124-51.11-85.624-187.432-214.62-350-375.531-10.23-23.802-21.115-43.71-32.094-59.282 35.46-10.19 82.517-2.294 125.75 40.94 40.243 40.242 52.642 90.776 41.375 128.343 4.89 4.914 9.883 9.913 14.688 14.75 19.07-46.1 4.573-108.895-42.844-156.313-35.694-35.693-75.48-50.324-111.032-50.22-1.147.005-2.3.03-3.438.064-21.844.65-41.957 6.898-58.344 17.187a102.302 102.302 0 0 0-8.312 5.814c1.33 3.094 2.758 5.884 4.406 8.218 1.92 2.72 4.004 4.936 6.906 6.688 2.202-1.717 4.498-3.375 6.938-4.906a88.727 88.727 0 0 1 3.25-1.97c8.196 10.088 15.465 24.624 25.47 47.25-23.907-10.568-38.822-18.04-49.033-27 .024-.03.04-.063.064-.093-.433-.33-.867-.655-1.28-1-.013-.008-.022-.02-.033-.03-11.215-10.375-16.532-22.934-22.31-44.5 5.988 1.605 11.256 3.19 16 4.844a137.13 137.13 0 0 1 26.81-15.875c-9.5-7.738-18.552-11.93-26.686-12.97-1.443-.185-2.87-.3-4.282-.313zM493.28 64.374c-77.985 0-125.587 28.886-146.124 69.406-20.536 40.52-13.994 90.39 9.688 131.407 11.385 19.72 17.807 40.687 19.187 61.22a4329.64 4329.64 0 0 1 18.47 19.187c2.31-29.955-5.072-61.35-21.47-89.75-21.13-36.602-26.155-80.112-9.186-113.594 16.97-33.481 55.94-59.188 129.437-59.188V64.376zM37.907 114.938c-2.894 23.925 6.18 50.21 29.532 73.562l13.218-13.188c-15.97-15.97-23.188-31.833-24.437-46.593-6.646-4.51-12.754-9.102-18.314-13.782zM124.062 277c-24.466-.028-45.04 4.92-61.343 13.656-24.842 13.31-39.363 35.865-40.75 60.47-2.78 49.207 44.38 102.65 140.405 118.28 101.63 16.544 170.303-9.184 205.406-54.062 1.01-1.29 1.988-2.59 2.94-3.906-4.552-4.232-9.148-8.52-13.783-12.875-1.233 1.79-2.52 3.55-3.875 5.28-29.97 38.315-90.355 62.97-187.687 47.126-90.394-14.715-126.796-62.527-124.75-98.783 1.023-18.127 10.982-34.37 30.938-45.062 19.955-10.692 50.267-15.364 90.5-7.47 34.077 6.69 62.938 3.47 85.437-6.936-4.72-4.65-9.49-9.33-14.28-14.064-17.545 6.452-39.89 8.088-67.564 2.656-14.895-2.923-28.778-4.297-41.594-4.312z" fill="#fff" fill-opacity="1"></path></g></svg>
|
After Width: | Height: | Size: 2.4 KiB |
12
changelog.md
@@ -1,5 +1,17 @@
|
||||
# 13.0
|
||||
|
||||
## 13.0.8 - Le renouveau d'Illysis
|
||||
|
||||
- Fix Foundry V13
|
||||
- Les états sont de nouveau affichés en ligne dans la feuille de personnage
|
||||
- les icones spécifiques Rêve de Dragon de la barre de droite sont de nouveau utilisées
|
||||
|
||||
- Nouvelle fenêtre de jets de dés
|
||||
- uniquement pour les oeuvres (chant, danse, musique, cuisine,...)
|
||||
- à activer dans les options avancées
|
||||
|
||||
## 13.0.7 - Sous le signe d'Illysis
|
||||
|
||||
- Fix Foundry V13
|
||||
- les tooltips des ajustements sont correctement visible
|
||||
- correction des affichages des signes d'heures dans la fenêtre d'astrologie
|
||||
|
@@ -50,6 +50,7 @@
|
||||
--actor-label-color: #464331c4;
|
||||
}
|
||||
/* Global styles & Font */
|
||||
.application,
|
||||
.window-app {
|
||||
font-family: CaslonAntique;
|
||||
text-align: justify;
|
||||
@@ -80,14 +81,14 @@ select,
|
||||
/* =================== 2. DEBUGGING HIGHLIGHTERS ============ */
|
||||
/* =================== 3. some constants ============ */
|
||||
--fieldset-background: url(/ui/parchment.jpg);
|
||||
--rdd-color-text-primary: rgba(10, 10, 10, 0.9);
|
||||
--rdd-input-background: rgba(0, 0, 0, 0.05);
|
||||
--rdd-color-border-input: rgba(0, 0, 0, 0.2);
|
||||
--rdd-bg-input: rgba(255, 255, 255, 0.1);
|
||||
--color-controls: rgba(0, 0, 0, 0.9);
|
||||
--rdd-color-text-primary: hsla(0, 0%, 4%, 0.9);
|
||||
--rdd-input-background: hsla(0, 0%, 0%, 0.1);
|
||||
--rdd-color-border-input: hsla(0, 0%, 0%, 0.2);
|
||||
--rdd-bg-input: hsla(0, 0%, 100%, 0.1);
|
||||
--color-controls: hsla(0, 0%, 0%, 0.9);
|
||||
--color-controls-light: hsla(0, 0%, 20%, 0.8);
|
||||
--color-controls-hover: hsla(60, 100%, 75%, 0.7);
|
||||
--color-control-border-hover: rgba(255, 128, 0, 0.8);
|
||||
--color-control-border-hover: hsla(30, 100%, 50%, 0.8);
|
||||
--color-gold: rgba(191, 149, 63, 0.8);
|
||||
--gradient-gold: linear-gradient(30deg, rgba(191, 149, 63, 0.3), rgba(252, 246, 186, 0.3), rgba(179, 135, 40, 0.3), rgba(251, 245, 183, 0.3), rgba(170, 119, 28, 0.3));
|
||||
--gradient-silver: linear-gradient(30deg, rgba(61, 55, 93, 0.3), rgba(178, 179, 196, 0.3), rgba(59, 62, 63, 0.6), rgba(206, 204, 199, 0.3), rgba(61, 46, 49, 0.3));
|
||||
@@ -97,14 +98,17 @@ select,
|
||||
--gradient-purple-black: linear-gradient(150deg, rgba(0, 0, 0, 0.7), rgba(100, 45, 124, 0.4), rgba(82, 17, 131, 0.3), rgba(100, 45, 124, 0.4), rgba(0, 0, 0, 0.7));
|
||||
--gradient-silver-light: linear-gradient(30deg, rgba(61, 55, 93, 0.2), rgba(178, 179, 196, 0.1), rgba(59, 62, 63, 0.2), rgba(206, 204, 199, 0.1), rgba(61, 46, 49, 0.2));
|
||||
--gradient-daylight: conic-gradient(from 0deg, hsla(50, 100%, 80%, 0.7), hsla(30, 30%, 40%, 0.1) 25%, hsla(250, 50%, 40%, 0.1) 25%, hsla(250, 30%, 30%, 0.7) 50%, hsla(250, 50%, 40%, 0.1) 75%, hsla(30, 30%, 40%, 0.1) 75%, hsla(50, 100%, 80%, 0.7));
|
||||
--background-custom-button: linear-gradient(to bottom, rgba(33, 55, 74, 0.988) 5%, rgba(21, 40, 51, 0.671) 100%);
|
||||
--background-custom-button-hover: linear-gradient(to bottom, #800000 5%, #3e0101 100%);
|
||||
--background-custom-button: linear-gradient(to bottom, hsla(208, 38%, 21%, 0.988) 5%, hsla(202, 42%, 14%, 0.671) 100%);
|
||||
--background-custom-button-hover: linear-gradient(to bottom, hsl(0, 100%, 25%) 5%, hsl(0, 97%, 12%) 100%);
|
||||
--background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%);
|
||||
--background-tooltip: hsla(60, 12%, 85%, 0.95);
|
||||
--background-tooltip-alt: hsla(60, 12%, 74%, 0.95);
|
||||
--color-tooltip: hsla(282, 47%, 33%, 0.9);
|
||||
--color-tooltip-faint: hsla(282, 47%, 66%, 0.5);
|
||||
--background-error: hsla(16, 100%, 50%, 0.8);
|
||||
--color-profile-border: hsla(0, 0%, 80%, 0.05);
|
||||
--color-background-chat-message: hsla(60, 12%, 85%, 0.9);
|
||||
--color-background-chat-whisper: repeating-linear-gradient(120deg, hsla(60, 12%, 85%, 0.75), hsla(60, 12%, 85%, 0.75) 1rem, hsla(60, 12%, 85%, 0.8) 1rem, hsla(60, 12%, 85%, 0.75) 1.5rem);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon {
|
||||
/* =================== En-têtes de feuilles ============ */
|
||||
@@ -417,6 +421,222 @@ select,
|
||||
border: 0 none;
|
||||
margin-bottom: 0.2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog {
|
||||
font-family: CaslonAntique;
|
||||
display: grid;
|
||||
grid-template-areas: "header header header header header header header" "action action action action action action action" "mode separation separation separation separation separation separation" "mode carac carac carac comp comp resume" "mode choix choix choix choix choix modifiers" "mode resolution resolution resolution resolution resolution modifiers" "mode chances chances chances chances chances buttons" "footer footer footer footer footer footer footer";
|
||||
grid-template-columns: 2rem 1rem 1fr 1fr 2fr 2fr 3fr;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-header {
|
||||
grid-area: header;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-line {
|
||||
grid-area: separation;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action {
|
||||
grid-area: action;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-carac {
|
||||
grid-area: carac;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-comp {
|
||||
grid-area: comp;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix {
|
||||
grid-area: choix;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-table {
|
||||
grid-area: resolution;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions {
|
||||
grid-area: modifiers;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-chances {
|
||||
grid-area: chances;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-resume {
|
||||
grid-area: resume;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-buttons {
|
||||
grid-area: buttons;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode {
|
||||
grid-area: mode;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button[data-checked="true"],
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button[data-checked="true"] {
|
||||
background-color: var(--color-text-selection-bg);
|
||||
color: var(--color-controls);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button[data-checked="true"] i,
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button[data-checked="true"] i {
|
||||
filter: invert(0.8);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button[data-checked="true"] img,
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button[data-checked="true"] img {
|
||||
filter: invert(0.2);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button,
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button {
|
||||
height: 1.8rem;
|
||||
width: 1.8rem;
|
||||
gap: 0.5rem;
|
||||
padding: 0.2rem;
|
||||
background-color: var(--button-background-color);
|
||||
color: var(--color-controls);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button i,
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button i {
|
||||
filter: invert(0.2);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="rollmode"] button img,
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-mode button img {
|
||||
filter: invert(0.8);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog :is(roll-carac, roll-comp) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-section,
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-section div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: anchor-center;
|
||||
margin: 0 0.2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-resume {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-resume img.button-effect-img {
|
||||
filter: invert(0.8);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section {
|
||||
display: grid;
|
||||
grid-template-areas: "selection selection" "img roll-part";
|
||||
grid-template-columns: 3.2rem 1fr;
|
||||
gap: 0.2rem;
|
||||
align-items: start;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section subline {
|
||||
grid-area: selection;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-img {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
grid-area: img;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-img img {
|
||||
border: 0;
|
||||
padding: 1px;
|
||||
max-height: 3rem;
|
||||
max-width: 3rem;
|
||||
object-fit: contain;
|
||||
height: 100%;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-detail {
|
||||
grid-area: roll-part;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: normal;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-detail subline {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-choix roll-section roll-part-detail subline div.poesie-extrait {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-section selected-numeric-value {
|
||||
display: flow;
|
||||
width: 2.5rem;
|
||||
text-align: right;
|
||||
margin: 0 0.2rem 0 0.5rem;
|
||||
padding: 0 0.2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action {
|
||||
flex-basis: content;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
border-bottom: 0.2rem solid;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section img.action-img {
|
||||
float: left;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-action roll-section img {
|
||||
max-width: 3rem;
|
||||
max-height: 3rem;
|
||||
margin: 0 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog :is(roll-action, roll-carac, roll-comp) roll-section {
|
||||
flex-basis: content;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog :is(roll-choix, roll-conditions, roll-carac, roll-comp) select {
|
||||
max-height: 1.6rem;
|
||||
margin: 0 0.2rem;
|
||||
padding: 0 0.2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog :is(roll-choix, roll-conditions, roll-carac, roll-comp) input[type="number"] {
|
||||
max-height: 1.6rem;
|
||||
max-width: 2.5rem;
|
||||
margin: 0 0.2rem;
|
||||
padding: 0 0.2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog :is(roll-choix, roll-conditions, roll-carac, roll-comp) img {
|
||||
max-width: 1.8rem;
|
||||
max-height: 1.8rem;
|
||||
margin: 0 0.2rem;
|
||||
padding: 0;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-carac select[name="select-carac"] {
|
||||
max-width: 6rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-comp select[name="select-comp"] {
|
||||
min-width: 8rem;
|
||||
max-width: 11rem;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="coeur"] select[name="coeur"] {
|
||||
max-width: 4rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-conditions roll-section[name="tricher"] img {
|
||||
/* image de d100 */
|
||||
max-width: 2.5rem;
|
||||
max-height: 2.5rem;
|
||||
gap: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
filter: invert(0.8);
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-buttons {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .roll-dialog roll-table table tr :is(th, td) {
|
||||
padding: 0.1rem;
|
||||
width: 1.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .window-header {
|
||||
background: rgba(0, 0, 0, 0.75);
|
||||
}
|
||||
@@ -1191,7 +1411,7 @@ select,
|
||||
padding: 5px;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .poesie-extrait {
|
||||
max-height: 12rem;
|
||||
max-height: 8rem;
|
||||
font-size: 0.8rem;
|
||||
font-style: italic;
|
||||
color: rgba(82, 17, 131, 0.9);
|
||||
@@ -1202,9 +1422,6 @@ select,
|
||||
overflow: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .poesie-extrait.poesie-overflow {
|
||||
max-height: 2rem;
|
||||
}
|
||||
.system-foundryvtt-reve-de-dragon .poesie-reference {
|
||||
font-size: 0.7rem;
|
||||
text-align: right;
|
||||
|
@@ -12,14 +12,14 @@
|
||||
|
||||
/* =================== 3. some constants ============ */
|
||||
--fieldset-background: url(/ui/parchment.jpg);
|
||||
--rdd-color-text-primary: rgba(10, 10, 10, 0.9);
|
||||
--rdd-input-background:rgba(0, 0, 0, 0.05);
|
||||
--rdd-color-border-input: rgba(0, 0, 0, 0.2);
|
||||
--rdd-bg-input: rgba(255, 255, 255, 0.1);
|
||||
--color-controls:rgba(0, 0, 0, 0.9);
|
||||
--rdd-color-text-primary: hsla(0, 0%, 4%, 0.9);
|
||||
--rdd-input-background:hsla(0, 0%, 0%, 0.1);
|
||||
--rdd-color-border-input: hsla(0, 0%, 0%, 0.2);
|
||||
--rdd-bg-input: hsla(0, 0%, 100%, 0.1);
|
||||
--color-controls:hsla(0, 0%, 0%, 0.9);
|
||||
--color-controls-light:hsla(0, 0%, 20%, 0.8);
|
||||
--color-controls-hover:hsla(60, 100%, 75%, 0.7);
|
||||
--color-control-border-hover:rgba(255, 128, 0, 0.8);
|
||||
--color-control-border-hover:hsla(30, 100%, 50%, 0.8);
|
||||
--color-gold: rgba(191, 149, 63, 0.8);
|
||||
--gradient-gold: linear-gradient(30deg, rgba(191, 149, 63, 0.3), rgba(252, 246, 186, 0.3), rgba(179, 135, 40, 0.3), rgba(251, 245, 183, 0.3), rgba(170, 119, 28, 0.3));
|
||||
--gradient-silver: linear-gradient(30deg, rgba(61, 55, 93, 0.3), rgba(178, 179, 196, 0.3), rgba(59, 62, 63, 0.6), rgba(206, 204, 199, 0.3), rgba(61, 46, 49, 0.3));
|
||||
@@ -39,12 +39,20 @@
|
||||
hsla(50, 100%, 80%, 0.7)
|
||||
);
|
||||
|
||||
--background-custom-button: linear-gradient(to bottom, rgba(33, 55, 74, 0.988) 5%, rgba(21, 40, 51, 0.671) 100%);
|
||||
--background-custom-button-hover: linear-gradient(to bottom, rgb(128, 0, 0) 5%, rgb(62, 1, 1) 100%);
|
||||
--background-custom-button: linear-gradient(to bottom, hsla(208, 38%, 21%, 0.988) 5%, hsla(202, 42%, 14%, 0.671) 100%);
|
||||
--background-custom-button-hover: linear-gradient(to bottom, hsla(0, 100%, 25%, 1) 5%, hsla(0, 97%, 12%, 1) 100%);
|
||||
--background-control-selected: linear-gradient(to bottom, hsla(0, 100%, 25%, 0.5) 5%, hsla(0, 100%, 12%, 0.5) 100%);
|
||||
--background-tooltip: hsla(60, 12%, 85%, 0.95);
|
||||
--background-tooltip-alt: hsla(60, 12%, 74%, 0.95);
|
||||
--color-tooltip:hsla(282, 47%, 33%, 0.9);
|
||||
--color-tooltip-faint:hsla(282, 47%, 66%, 0.5);
|
||||
--background-error:hsla(16, 100%, 50%, 0.8);
|
||||
--color-profile-border: hsla(0, 0%, 80%, 0.05);
|
||||
|
||||
--color-background-chat-message: hsla(60, 12%, 85%, 0.9);
|
||||
--color-background-chat-whisper: repeating-linear-gradient(120deg,
|
||||
hsla(60, 12%, 85%, 0.75),
|
||||
hsla(60, 12%, 85%, 0.75) 1rem,
|
||||
hsla(60, 12%, 85%, 0.8) 1rem,
|
||||
hsla(60, 12%, 85%, 0.75) 1.5rem);
|
||||
}
|
||||
|
@@ -59,6 +59,7 @@
|
||||
}
|
||||
|
||||
/* Global styles & Font */
|
||||
.application,
|
||||
.window-app {
|
||||
font-family: CaslonAntique;
|
||||
text-align: justify;
|
||||
|
@@ -6,7 +6,7 @@
|
||||
@import "item/monnaie.less";
|
||||
@import "item/munition.less";
|
||||
@import "item/tarot.less";
|
||||
|
||||
@import "roll-dialog.less";
|
||||
.window-header{
|
||||
background: rgba(0,0,0,0.75);
|
||||
}
|
||||
@@ -833,20 +833,18 @@
|
||||
}
|
||||
|
||||
.poesie-extrait {
|
||||
max-height: 12rem;
|
||||
max-height: 8rem;
|
||||
font-size: 0.8rem;
|
||||
font-style: italic;
|
||||
color: rgba(82, 17, 131, 0.9);
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.poesie-extrait:hover {
|
||||
max-height: unset;
|
||||
overflow: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
.poesie-extrait.poesie-overflow {
|
||||
max-height: 2rem;
|
||||
}
|
||||
|
||||
.poesie-reference {
|
||||
font-size: 0.7rem;
|
||||
|
220
less/roll-dialog.less
Normal file
@@ -0,0 +1,220 @@
|
||||
.roll-dialog {
|
||||
font-family: CaslonAntique;
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"header header header header header header header"
|
||||
"action action action action action action action"
|
||||
"mode separation separation separation separation separation separation"
|
||||
"mode carac carac carac comp comp resume"
|
||||
"mode choix choix choix choix choix modifiers"
|
||||
"mode resolution resolution resolution resolution resolution modifiers"
|
||||
"mode chances chances chances chances chances buttons"
|
||||
"footer footer footer footer footer footer footer";
|
||||
grid-template-columns: 2rem 1rem 1fr 1fr 2fr 2fr 3fr;
|
||||
gap: 0.2rem;
|
||||
|
||||
roll-header { grid-area: header; }
|
||||
roll-line { grid-area: separation; }
|
||||
roll-action { grid-area: action; }
|
||||
roll-carac { grid-area: carac; }
|
||||
roll-comp { grid-area: comp; }
|
||||
|
||||
roll-choix { grid-area: choix; }
|
||||
|
||||
roll-table { grid-area: resolution; }
|
||||
roll-conditions { grid-area: modifiers; }
|
||||
roll-chances { grid-area: chances; }
|
||||
roll-resume { grid-area: resume; }
|
||||
roll-buttons { grid-area: buttons; }
|
||||
|
||||
roll-mode {
|
||||
grid-area: mode;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
roll-conditions roll-section[name="rollmode"],
|
||||
roll-mode {
|
||||
button[data-checked="true"] {
|
||||
background-color: var(--color-text-selection-bg);
|
||||
color: var(--color-controls);
|
||||
i { filter: invert(0.8); }
|
||||
img { filter: invert(0.2); }
|
||||
}
|
||||
button {
|
||||
height: 1.8rem;
|
||||
width: 1.8rem;
|
||||
gap: 0.5rem;
|
||||
padding: 0.2rem;
|
||||
background-color: var(--button-background-color);
|
||||
color: var(--color-controls);
|
||||
i { filter: invert(0.2); }
|
||||
img { filter: invert(0.8); }
|
||||
}
|
||||
}
|
||||
|
||||
:is(roll-carac, roll-comp) {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
roll-section,
|
||||
roll-section div {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: anchor-center;
|
||||
margin: 0 0.2rem;
|
||||
}
|
||||
|
||||
roll-resume {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
img.button-effect-img {
|
||||
filter: invert(0.8);
|
||||
}
|
||||
}
|
||||
|
||||
roll-choix roll-section {
|
||||
display: grid;
|
||||
grid-template-areas:
|
||||
"selection selection"
|
||||
"img roll-part";
|
||||
grid-template-columns: 3.2rem 1fr;
|
||||
gap: 0.2rem;
|
||||
align-items: start;
|
||||
|
||||
subline {
|
||||
grid-area: selection;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
roll-part-img {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
grid-area: img;
|
||||
img{
|
||||
border: 0;
|
||||
padding: 1px;
|
||||
max-height: 3rem;
|
||||
max-width: 3rem;
|
||||
object-fit: contain;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
roll-part-detail {
|
||||
grid-area: roll-part;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: normal;
|
||||
|
||||
subline {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
div.poesie-extrait{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
roll-section selected-numeric-value {
|
||||
display: flow;
|
||||
width: 2.5rem;
|
||||
text-align: right;
|
||||
margin: 0 0.2rem 0 0.5rem;
|
||||
padding: 0 0.2rem;
|
||||
}
|
||||
|
||||
roll-action {
|
||||
flex-basis: content;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
border-bottom: 0.2rem solid;
|
||||
font-size: 1.2rem;
|
||||
font-weight: bold;
|
||||
|
||||
roll-section {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
|
||||
img.action-img {
|
||||
float: left;
|
||||
}
|
||||
img {
|
||||
max-width: 3rem;
|
||||
max-height: 3rem;
|
||||
margin: 0 1rem;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
roll-conditions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
:is(roll-action, roll-carac, roll-comp) roll-section {
|
||||
flex-basis: content;
|
||||
}
|
||||
|
||||
:is(roll-choix, roll-conditions, roll-carac, roll-comp) {
|
||||
select {
|
||||
max-height: 1.6rem;
|
||||
margin: 0 0.2rem;
|
||||
padding: 0 0.2rem;
|
||||
}
|
||||
input[type="number"] {
|
||||
max-height: 1.6rem;
|
||||
max-width: 2.5rem;
|
||||
margin: 0 0.2rem;
|
||||
padding: 0 0.2rem;
|
||||
}
|
||||
img {
|
||||
max-width: 1.8rem;
|
||||
max-height: 1.8rem;
|
||||
margin: 0 0.2rem;
|
||||
padding: 0;
|
||||
}
|
||||
}
|
||||
|
||||
roll-carac select[name="select-carac"] {
|
||||
max-width: 6rem;
|
||||
|
||||
}
|
||||
roll-comp select[name="select-comp"] {
|
||||
min-width: 8rem;
|
||||
max-width: 11rem;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
roll-conditions roll-section[name="coeur"] select[name="coeur"] {
|
||||
max-width: 4rem;
|
||||
}
|
||||
|
||||
roll-conditions roll-section[name="tricher"] img {
|
||||
/* image de d100 */
|
||||
max-width: 2.5rem;
|
||||
max-height: 2.5rem;
|
||||
gap: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
filter: invert(0.8);
|
||||
}
|
||||
|
||||
roll-buttons {
|
||||
display: flex;
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
roll-table {
|
||||
table tr :is(th, td) {
|
||||
padding: 0.1rem;
|
||||
width: 1.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -90,7 +90,7 @@ export class RdDActorSheet extends RdDBaseActorSangSheet {
|
||||
formData.difficultesLibres = CONFIG.RDD.difficultesLibres;
|
||||
|
||||
formData.hautreve = {
|
||||
isDemiReve: this.actor.getEffect(STATUSES.StatusDemiReve),
|
||||
isDemiReve: this.actor.isDemiReve(),
|
||||
cacheTMR: this.actor.isTMRCache()
|
||||
}
|
||||
|
||||
|
40
module/actor-token.mjs
Normal file
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
* class providing the actor and token, and choosing the name and image from the token if available.
|
||||
*/
|
||||
export class ActorToken {
|
||||
|
||||
static fromActorId(actorId, onError = () => undefined) {
|
||||
actorId = actorId ?? (canvas.tokens.controlled.length > 0
|
||||
? canvas.tokens.controlled[0].actor.id
|
||||
: undefined)
|
||||
const actor = actorId ? game.actors.get(actorId) : undefined
|
||||
if (actor) {
|
||||
return this.fromActor(actor)
|
||||
}
|
||||
return onError()
|
||||
}
|
||||
|
||||
static fromActor(actor) {
|
||||
const token = actor.isToken ? actor.token : actor.prototypeToken
|
||||
return ActorToken.fromToken(token)
|
||||
}
|
||||
|
||||
static fromTokenId(tokenId, sceneId = undefined) {
|
||||
const tokensList = sceneId ? game.scenes.get(sceneId).tokens : canvas.tokens.placeables
|
||||
const token = tokensList.get(tokenId)
|
||||
return ActorToken.fromToken(token)
|
||||
}
|
||||
|
||||
static fromToken(token) {
|
||||
return new ActorToken(token)
|
||||
}
|
||||
|
||||
constructor(token) {
|
||||
this.name = token.name ?? token.actor.name
|
||||
this.img = token.texture.src ?? token.actor.img
|
||||
this.actor = token.actor
|
||||
this.id = token.actor?.id
|
||||
this.token = token
|
||||
this.tokenId = token?.id
|
||||
}
|
||||
}
|
407
module/actor.js
@@ -19,7 +19,7 @@ import { DialogConsommer } from "./dialog-item-consommer.js";
|
||||
import { DialogFabriquerPotion } from "./dialog-fabriquer-potion.js";
|
||||
import { RollDataAjustements } from "./rolldata-ajustements.js";
|
||||
import { RdDPossession } from "./rdd-possession.js";
|
||||
import { SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||
import { ACTOR_TYPES, SHOW_DICE, SYSTEM_RDD, SYSTEM_SOCKET_ID } from "./constants.js";
|
||||
import { RdDConfirm } from "./rdd-confirm.js";
|
||||
import { DialogRepos } from "./sommeil/dialog-repos.js";
|
||||
import { RdDBaseActor } from "./actor/base-actor.js";
|
||||
@@ -46,6 +46,8 @@ import { PAS_DE_DRACONIC, POSSESSION_SANS_DRACONIC } from "./item/base-items.js"
|
||||
|
||||
import { RdDRollResult } from "./rdd-roll-result.js";
|
||||
import { RdDInitiative } from "./initiative.mjs";
|
||||
import RollDialog from "./roll/roll-dialog.mjs";
|
||||
import { OptionsAvancees, ROLL_DIALOG_V2 } from "./settings/options-avancees.js";
|
||||
|
||||
export const MAINS_DIRECTRICES = ['Droitier', 'Gaucher', 'Ambidextre']
|
||||
|
||||
@@ -108,7 +110,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
return Number.isNumeric(this.system.compteurs.chance.value) ?
|
||||
Misc.toInt(this.system.compteurs.chance.value) : this.getChance()
|
||||
}
|
||||
getMoralTotal() { return this.system.compteurs.moral?.value ?? 0 }
|
||||
getMoralTotal() { return parseInt(this.system.compteurs.moral?.value ?? 0) }
|
||||
|
||||
getEnduranceMax() { return Math.max(1, Math.max(this.getTaille() + this.getConstitution(), this.getVieMax() + this.getVolonte())) }
|
||||
|
||||
@@ -116,8 +118,10 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
getEtatGeneral(options = { ethylisme: false }) {
|
||||
const etatGeneral = this.system.compteurs.etat?.value ?? 0
|
||||
// Pour les jets d'Ethylisme, on retire le malus d'éthylisme (p.162)
|
||||
const annuleMalusEthylisme = options.ethylisme ? this.malusEthylisme() : 0
|
||||
return etatGeneral - annuleMalusEthylisme
|
||||
if (options.ethylisme) {
|
||||
return etatGeneral - this.malusEthylisme()
|
||||
}
|
||||
return etatGeneral
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -972,8 +976,14 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
ethylisme() {
|
||||
return this.system.compteurs.ethylisme?.value ?? 1;
|
||||
}
|
||||
malusEthylisme() {
|
||||
return Math.min(0, (this.system.compteurs.ethylisme?.value ?? 0));
|
||||
return Math.min(0, this.ethylisme())
|
||||
}
|
||||
isAlcoolise() {
|
||||
return this.ethylisme() < 1
|
||||
}
|
||||
|
||||
|
||||
@@ -1559,7 +1569,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
/* -------------------------------------------- */
|
||||
createCallbackAppelAuMoral() { /* Si l'appel au moral est utilisé, on l'affiche dans le chat et on diminue éventuellement le moral */
|
||||
return {
|
||||
action: r => this._appliquerAppelMoral(r)
|
||||
action: r => this.appliquerAppelMoral(r)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1655,7 +1665,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _appliquerAppelMoral(rollData) {
|
||||
async appliquerAppelMoral(rollData) {
|
||||
if (!rollData.use.moral || game.settings.get("core", "rollMode") == 'selfroll') {
|
||||
return
|
||||
}
|
||||
@@ -1668,20 +1678,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
|
||||
/* -------------------------------------------- */
|
||||
$filterSortList(sortList, coord) {
|
||||
let tmr = TMRUtility.getTMR(coord);
|
||||
let filtered = []
|
||||
for (let sort of sortList) {
|
||||
if (sort.system.caseTMR.toLowerCase().includes('variable')) {
|
||||
filtered.push(sort);
|
||||
} else if (sort.system.caseTMRspeciale.toLowerCase().includes('variable')) {
|
||||
filtered.push(sort);
|
||||
} else if (sort.system.caseTMR.toLowerCase() == tmr.type) {
|
||||
filtered.push(sort);
|
||||
} else if (sort.system.caseTMR.toLowerCase().includes('special') && sort.system.caseTMRspeciale.toLowerCase().includes(coord.toLowerCase())) {
|
||||
filtered.push(sort);
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
return sortList.filter(it => RdDItemSort.isSortOnCoord(it, coord))
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -1707,8 +1704,8 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
ui.notifications.error("Une queue ou un souffle vous empèche de lancer de sort!")
|
||||
return
|
||||
}
|
||||
// Duplication car les pts de reve sont modifiés dans le sort
|
||||
let sorts = foundry.utils.duplicate(this.$filterSortList(this.itemTypes['sort'], coord));
|
||||
// Duplication car les pts de reve sont modifiés dans le sort!
|
||||
let sorts = foundry.utils.duplicate(this.itemTypes[ITEM_TYPES.sort].filter(it => RdDItemSort.isSortOnCoord(it, coord)))
|
||||
if (sorts.length == 0) {
|
||||
ui.notifications.info(`Aucun sort disponible en ${TMRUtility.getTMR(coord).label} !`);
|
||||
return;
|
||||
@@ -1996,153 +1993,6 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _rollArt(artData, selected, oeuvre, callbackAction = async r => await this._resultArt(r)) {
|
||||
oeuvre.system.niveau = oeuvre.system.niveau ?? 0;
|
||||
foundry.utils.mergeObject(artData,
|
||||
{
|
||||
oeuvre: oeuvre,
|
||||
art: oeuvre.type,
|
||||
competence: foundry.utils.duplicate(this.getCompetence(artData.compName ?? oeuvre.system.competence ?? artData.art)),
|
||||
diffLibre: - oeuvre.system.niveau,
|
||||
diffConditions: 0,
|
||||
use: { libre: false, conditions: true, surenc: false },
|
||||
selectedCarac: foundry.utils.duplicate(this.system.carac[selected])
|
||||
},
|
||||
{ overwrite: false });
|
||||
artData.competence.system.defaut_carac = selected;
|
||||
if (!artData.forceCarac) {
|
||||
artData.forceCarac = {};
|
||||
artData.forceCarac[selected] = foundry.utils.duplicate(this.system.carac[selected]);
|
||||
}
|
||||
|
||||
await this.openRollDialog({
|
||||
name: `jet-${artData.art}`,
|
||||
label: `${artData.verbe} ${oeuvre.name}`,
|
||||
template: `systems/foundryvtt-reve-de-dragon/templates/dialog-roll-${oeuvre.type}.hbs`,
|
||||
rollData: artData,
|
||||
callbacks: [{ action: callbackAction }],
|
||||
})
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _resultArt(artData) {
|
||||
const niveau = artData.oeuvre.system.niveau ?? 0;
|
||||
const baseQualite = (artData.rolled.isSuccess ? niveau : artData.competence.system.niveau);
|
||||
artData.qualiteFinale = Math.min(baseQualite, niveau) + artData.rolled.ptQualite;
|
||||
|
||||
await RdDRollResult.displayRollData(artData, this.name, `chat-resultat-${artData.art}.hbs`);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollChant(id) {
|
||||
const artData = { art: 'chant', verbe: 'Chanter' };
|
||||
const oeuvre = foundry.utils.duplicate(this.getChant(id));
|
||||
await this._rollArt(artData, "ouie", oeuvre);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollDanse(id) {
|
||||
const artData = { art: 'danse', verbe: 'Danser', forceCarac: {} };
|
||||
const oeuvre = foundry.utils.duplicate(this.findItemLike(id, artData.art));
|
||||
if (oeuvre.system.agilite) {
|
||||
artData.forceCarac['agilite'] = foundry.utils.duplicate(this.system.carac.agilite);
|
||||
}
|
||||
if (oeuvre.system.apparence) {
|
||||
artData.forceCarac['apparence'] = foundry.utils.duplicate(this.system.carac.apparence);
|
||||
}
|
||||
const selectedCarac = this._getCaracDanse(oeuvre);
|
||||
await this._rollArt(artData, selectedCarac, oeuvre);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
_getCaracDanse(oeuvre) {
|
||||
if (oeuvre.system.agilite) { return "agilite"; }
|
||||
else if (oeuvre.system.apparence) { return "apparence"; }
|
||||
const compData = this.getCompetence(oeuvre.system.competence);
|
||||
return compData.system.defaut_carac;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollMusique(id) {
|
||||
const artData = { art: 'musique', verbe: 'Jouer' };
|
||||
const oeuvre = this.findItemLike(id, artData.art);
|
||||
await this._rollArt(artData, "ouie", oeuvre);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollRecetteCuisine(id) {
|
||||
const oeuvre = this.getRecetteCuisine(id);
|
||||
const artData = {
|
||||
verbe: 'Cuisiner',
|
||||
compName: 'cuisine',
|
||||
proportions: 1,
|
||||
ajouterEquipement: false
|
||||
};
|
||||
await this._rollArt(artData, 'odoratgout', oeuvre, r => this._resultRecetteCuisine(r));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _resultRecetteCuisine(cuisine) {
|
||||
const niveauRecette = cuisine.oeuvre.system.niveau ?? 0;
|
||||
const baseQualite = (cuisine.rolled.isSuccess ? niveauRecette : cuisine.competence.system.niveau);
|
||||
cuisine.qualiteFinale = Math.min(baseQualite, niveauRecette) + cuisine.rolled.ptQualite;
|
||||
cuisine.exotismeFinal = Math.min(Math.min(cuisine.qualiteFinale, cuisine.oeuvre.system.exotisme ?? 0), 0);
|
||||
cuisine.sust = cuisine.oeuvre.system.sust * Math.min(cuisine.proportions, cuisine.proportionsMax ?? cuisine.proportions)
|
||||
const platCuisine = {
|
||||
name: cuisine.oeuvre.name,
|
||||
type: 'nourritureboisson',
|
||||
img: 'systems/foundryvtt-reve-de-dragon/icons/objets/provision_cuite.webp',
|
||||
system: {
|
||||
"description": cuisine.oeuvre.system.description,
|
||||
"sust": 1,
|
||||
"qualite": cuisine.qualiteFinale,
|
||||
"exotisme": cuisine.exotismeFinal,
|
||||
"encombrement": 0.1,
|
||||
"quantite": Math.max(1, Math.floor(cuisine.sust)),
|
||||
"cout": Math.max(cuisine.qualiteFinale) * 0.01
|
||||
}
|
||||
}
|
||||
if (cuisine.ajouterEquipement) {
|
||||
await this.createEmbeddedDocuments('Item', [platCuisine]);
|
||||
ui.notifications.info(`${platCuisine.system.quantite} rations de ${platCuisine.name} ont été ajoutés à votre équipement`);
|
||||
}
|
||||
cuisine.platCuisine = platCuisine;
|
||||
await RdDRollResult.displayRollData(cuisine, this.name, `chat-resultat-${cuisine.art}.hbs`);
|
||||
}
|
||||
|
||||
async preparerNourriture(item) {
|
||||
if (item.getUtilisationCuisine() == 'brut') {
|
||||
const nourriture = {
|
||||
name: 'Plat de ' + item.name,
|
||||
type: 'recettecuisine',
|
||||
img: item.img,
|
||||
system: {
|
||||
sust: item.system.sust,
|
||||
exotisme: item.system.exotisme,
|
||||
ingredients: item.name
|
||||
}
|
||||
};
|
||||
const artData = {
|
||||
verbe: 'Préparer',
|
||||
compName: 'cuisine',
|
||||
proportions: 1,
|
||||
proportionsMax: Math.min(50, item.system.quantite),
|
||||
ajouterEquipement: true
|
||||
};
|
||||
await this._rollArt(artData, 'odoratgout', nourriture, async (cuisine) => {
|
||||
await this._resultRecetteCuisine(cuisine);
|
||||
const remaining = Math.max(item.system.quantite - cuisine.proportions, 0);
|
||||
if (remaining > 0) {
|
||||
await item.update({ 'system.quantite': remaining })
|
||||
}
|
||||
else {
|
||||
await this.deleteEmbeddedDocuments('Item', [item.id]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollJeu(id) {
|
||||
const oeuvre = this.getJeu(id);
|
||||
@@ -2158,14 +2008,9 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
listCarac.forEach(c => artData.forceCarac[c] = this.system.carac[c]);
|
||||
artData.competence.system.niveauReel = artData.competence.system.niveau;
|
||||
artData.competence.system.niveau = Math.max(artData.competence.system.niveau, oeuvre.system.base);
|
||||
await this._rollArt(artData, carac, oeuvre);
|
||||
await this._rollArtV1(artData, carac, oeuvre);
|
||||
}
|
||||
|
||||
async rollOeuvre(id) {
|
||||
const artData = { art: 'oeuvre', verbe: 'Interpréter' }
|
||||
const oeuvre = foundry.utils.duplicate(this.findItemLike(id, artData.art))
|
||||
await this._rollArt(artData, oeuvre.system.default_carac, oeuvre)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollMeditation(id) {
|
||||
@@ -2199,7 +2044,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
if (meditationRoll.rolled.isSuccess) {
|
||||
await this.createEmbeddedDocuments("Item", [RdDItemSigneDraconique.prepareSigneDraconiqueMeditation(meditationRoll.meditation, meditationRoll.rolled)]);
|
||||
}
|
||||
if (meditationRoll.rolled.isEPart){
|
||||
if (meditationRoll.rolled.isEPart) {
|
||||
await this.updateEmbeddedDocuments('Item', [{ _id: meditationRoll.meditation._id, 'system.malus': meditationRoll.meditation.system.malus - 1 }]);
|
||||
}
|
||||
await this.santeIncDec("fatigue", 2);
|
||||
@@ -2509,7 +2354,7 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
this.tmrApp.forceTMRDisplay()
|
||||
return
|
||||
}
|
||||
if (mode != 'visu' && this.getEffect(STATUSES.StatusDemiReve)) {
|
||||
if (mode != 'visu' && this.isDemiReve()) {
|
||||
ui.notifications.warn("Les personnage est déjà dans les Terres Médianes, elles s'affichent en visualisation")
|
||||
mode = "visu"; // bascule le mode en visu automatiquement
|
||||
}
|
||||
@@ -2789,8 +2634,11 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
|
||||
listeSuivants(filter = suivant => true) {
|
||||
return RdDActor.$buildSubActorLinks(
|
||||
this.system.subacteurs.suivants.filter(filter), RdDActor.$transformSubActeurSuivant
|
||||
)
|
||||
this.system.subacteurs.suivants, RdDActor.$transformSubActeurSuivant
|
||||
).filter(filter)
|
||||
}
|
||||
listeAmoureux() {
|
||||
return this.listeSuivants(it => it.coeur > 0 && it.type == ACTOR_TYPES.personnage)
|
||||
}
|
||||
|
||||
getSuivant(subActorId) {
|
||||
@@ -3200,5 +3048,204 @@ export class RdDActor extends RdDBaseActorSang {
|
||||
await incarnation.remiseANeuf();
|
||||
incarnation.sheet.render(true);
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _rollArtV2(oeuvreId, callbackAction = async (actor, rd) => await actor._resultArtV2(rd)) {
|
||||
const oeuvre = this.items.get(oeuvreId)
|
||||
const rollData = {
|
||||
title: `Interpretation de ${oeuvre.name} par ${this.name}`,
|
||||
mode: {
|
||||
allowed: ["oeuvre"]
|
||||
},
|
||||
selected: {
|
||||
mode: "oeuvre",
|
||||
oeuvre: { key: oeuvre.id },
|
||||
},
|
||||
ids: {
|
||||
actorId: this.id
|
||||
}
|
||||
}
|
||||
await RollDialog.create(rollData, {
|
||||
onRoll: (dialog) => {
|
||||
this._onCloseRollDialog(),
|
||||
dialog.close()
|
||||
},
|
||||
customChatMessage: true,
|
||||
callbacks: [callbackAction]
|
||||
})
|
||||
}
|
||||
|
||||
async _resultArtV2(artData) {
|
||||
const niveau = artData.oeuvre.system.niveau ?? 0;
|
||||
const baseQualite = (artData.rolled.isSuccess ? niveau : artData.competence.system.niveau);
|
||||
artData.qualiteFinale = Math.min(baseQualite, niveau) + artData.rolled.ptQualite;
|
||||
|
||||
await RdDRollResult.displayRollData(artData, this.name, `chat-resultat-${artData.art}.hbs`);
|
||||
}
|
||||
/* -------------------------------------------- */
|
||||
|
||||
async rollOeuvre(id) {
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
return await this._rollArtV2(id)
|
||||
}
|
||||
else {
|
||||
const artData = { art: 'oeuvre', verbe: 'Interpréter' }
|
||||
const oeuvre = foundry.utils.duplicate(this.findItemLike(id, artData.art))
|
||||
await this._rollArtV1(artData, oeuvre.system.default_carac, oeuvre)
|
||||
}
|
||||
}
|
||||
|
||||
async rollChant(id) {
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
await this._rollArtV2(id)
|
||||
}
|
||||
else {
|
||||
const artData = { art: 'chant', verbe: 'Chanter' }
|
||||
const oeuvre = foundry.utils.duplicate(this.getChant(id))
|
||||
await this._rollArtV1(artData, "ouie", oeuvre)
|
||||
}
|
||||
}
|
||||
|
||||
async rollDanse(id) {
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
await this._rollArtV2(id)
|
||||
}
|
||||
else {
|
||||
const artData = { art: 'danse', verbe: 'Danser', forceCarac: {} }
|
||||
const oeuvre = foundry.utils.duplicate(this.findItemLike(id, artData.art))
|
||||
let selectedCarac = this.getCompetence(oeuvre.system.competence)?.system.defaut_carac
|
||||
if (oeuvre.system.apparence) {
|
||||
artData.forceCarac['apparence'] = foundry.utils.duplicate(this.system.carac.apparence)
|
||||
selectedCarac = "apparence"
|
||||
}
|
||||
if (oeuvre.system.agilite) {
|
||||
artData.forceCarac['agilite'] = foundry.utils.duplicate(this.system.carac.agilite)
|
||||
selectedCarac = "agilite"
|
||||
}
|
||||
await this._rollArtV1(artData, selectedCarac, oeuvre)
|
||||
}
|
||||
}
|
||||
|
||||
async rollMusique(id) {
|
||||
if (OptionsAvancees.isUsing(ROLL_DIALOG_V2)) {
|
||||
await this._rollArtV2(id)
|
||||
}
|
||||
else {
|
||||
const artData = { art: 'musique', verbe: 'Jouer' }
|
||||
const oeuvre = this.findItemLike(id, artData.art)
|
||||
await this._rollArtV1(artData, "ouie", oeuvre)
|
||||
}
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _rollArtV1(artData, selected, oeuvre, callbackAction = async r => await this._resultArt(r)) {
|
||||
oeuvre.system.niveau = oeuvre.system.niveau ?? 0;
|
||||
foundry.utils.mergeObject(artData,
|
||||
{
|
||||
oeuvre: oeuvre,
|
||||
art: oeuvre.type,
|
||||
competence: foundry.utils.duplicate(this.getCompetence(artData.compName ?? oeuvre.system.competence ?? artData.art)),
|
||||
diffLibre: - oeuvre.system.niveau,
|
||||
diffConditions: 0,
|
||||
use: { libre: false, conditions: true, surenc: false },
|
||||
selectedCarac: foundry.utils.duplicate(this.system.carac[selected])
|
||||
},
|
||||
{ overwrite: false });
|
||||
artData.competence.system.defaut_carac = selected;
|
||||
if (!artData.forceCarac) {
|
||||
artData.forceCarac = {};
|
||||
artData.forceCarac[selected] = foundry.utils.duplicate(this.system.carac[selected]);
|
||||
}
|
||||
|
||||
await this.openRollDialog({
|
||||
name: `jet-${artData.art}`,
|
||||
label: `${artData.verbe} ${oeuvre.name}`,
|
||||
template: `systems/foundryvtt-reve-de-dragon/templates/dialog-roll-${oeuvre.type}.hbs`,
|
||||
rollData: artData,
|
||||
callbacks: [{ action: callbackAction }],
|
||||
})
|
||||
}
|
||||
|
||||
async _resultArt(artData) {
|
||||
const niveau = artData.oeuvre.system.niveau ?? 0;
|
||||
const baseQualite = (artData.rolled.isSuccess ? niveau : artData.competence.system.niveau);
|
||||
artData.qualiteFinale = Math.min(baseQualite, niveau) + artData.rolled.ptQualite;
|
||||
|
||||
await RdDRollResult.displayRollData(artData, this.name, `chat-resultat-${artData.art}.hbs`);
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async rollRecetteCuisine(id) {
|
||||
const oeuvre = this.getRecetteCuisine(id);
|
||||
const artData = {
|
||||
verbe: 'Cuisiner',
|
||||
compName: 'cuisine',
|
||||
proportions: 1,
|
||||
ajouterEquipement: false
|
||||
};
|
||||
await this._rollArtV1(artData, 'odoratgout', oeuvre, r => this._resultRecetteCuisine(r));
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
async _resultRecetteCuisine(cuisine) {
|
||||
const niveauRecette = cuisine.oeuvre.system.niveau ?? 0;
|
||||
const baseQualite = (cuisine.rolled.isSuccess ? niveauRecette : cuisine.competence.system.niveau);
|
||||
cuisine.qualiteFinale = Math.min(baseQualite, niveauRecette) + cuisine.rolled.ptQualite;
|
||||
cuisine.exotismeFinal = Math.min(Math.min(cuisine.qualiteFinale, cuisine.oeuvre.system.exotisme ?? 0), 0);
|
||||
cuisine.sust = cuisine.oeuvre.system.sust * Math.min(cuisine.proportions, cuisine.proportionsMax ?? cuisine.proportions)
|
||||
const platCuisine = {
|
||||
name: cuisine.oeuvre.name,
|
||||
type: 'nourritureboisson',
|
||||
img: 'systems/foundryvtt-reve-de-dragon/icons/objets/provision_cuite.webp',
|
||||
system: {
|
||||
"description": cuisine.oeuvre.system.description,
|
||||
"sust": 1,
|
||||
"qualite": cuisine.qualiteFinale,
|
||||
"exotisme": cuisine.exotismeFinal,
|
||||
"encombrement": 0.1,
|
||||
"quantite": Math.max(1, Math.floor(cuisine.sust)),
|
||||
"cout": Math.max(cuisine.qualiteFinale) * 0.01
|
||||
}
|
||||
}
|
||||
if (cuisine.ajouterEquipement) {
|
||||
await this.createEmbeddedDocuments('Item', [platCuisine]);
|
||||
ui.notifications.info(`${platCuisine.system.quantite} rations de ${platCuisine.name} ont été ajoutés à votre équipement`);
|
||||
}
|
||||
cuisine.platCuisine = platCuisine;
|
||||
await RdDRollResult.displayRollData(cuisine, this.name, `chat-resultat-${cuisine.art}.hbs`);
|
||||
}
|
||||
|
||||
async preparerNourriture(item) {
|
||||
if (item.getUtilisationCuisine() == 'brut') {
|
||||
const nourriture = {
|
||||
name: 'Plat de ' + item.name,
|
||||
type: 'recettecuisine',
|
||||
img: item.img,
|
||||
system: {
|
||||
sust: item.system.sust,
|
||||
exotisme: item.system.exotisme,
|
||||
ingredients: item.name
|
||||
}
|
||||
};
|
||||
const artData = {
|
||||
verbe: 'Préparer',
|
||||
compName: 'cuisine',
|
||||
proportions: 1,
|
||||
proportionsMax: Math.min(50, item.system.quantite),
|
||||
ajouterEquipement: true
|
||||
};
|
||||
await this._rollArtV1(artData, 'odoratgout', nourriture, async (cuisine) => {
|
||||
await this._resultRecetteCuisine(cuisine);
|
||||
const remaining = Math.max(item.system.quantite - cuisine.proportions, 0);
|
||||
if (remaining > 0) {
|
||||
await item.update({ 'system.quantite': remaining })
|
||||
}
|
||||
else {
|
||||
await this.deleteEmbeddedDocuments('Item', [item.id]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@ import { RdDUtility } from "../rdd-utility.js";
|
||||
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||
import { RdDBaseActor } from "./base-actor.js";
|
||||
import { ITEM_TYPES } from "../constants.js";
|
||||
import { StatusEffects } from "../settings/status-effects.js";
|
||||
import { StatusEffects, STATUSES } from "../settings/status-effects.js";
|
||||
import { Targets } from "../targets.js";
|
||||
import { RdDConfirm } from "../rdd-confirm.js";
|
||||
import { RdDCarac } from "../rdd-carac.js";
|
||||
@@ -172,8 +172,11 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
idOrName, options)
|
||||
}
|
||||
|
||||
getCompetences(name, options = { onMessage: message => { } }) {
|
||||
return RdDItemCompetence.findCompetences(this.items, name, options)
|
||||
getCompetences(name = undefined, options = { onMessage: message => { } }) {
|
||||
if (name == undefined) {
|
||||
return this.itemTypes[ITEM_TYPES.competence]
|
||||
}
|
||||
return RdDItemCompetence.findCompetences(this.itemTypes[ITEM_TYPES.competence], name, options)
|
||||
}
|
||||
|
||||
getCompetenceCorpsACorps(options = { onMessage: message => { } }) {
|
||||
@@ -223,27 +226,24 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
return this.getEmbeddedCollection("ActiveEffect").filter(filter);
|
||||
}
|
||||
|
||||
getEffect(effectId) {
|
||||
return this.getEmbeddedCollection("ActiveEffect").find(it => it.statuses?.has(effectId));
|
||||
getEffectByStatus(statusId) {
|
||||
return this.getEffects().find(it => it.statuses.has(statusId));
|
||||
}
|
||||
|
||||
async setEffect(effectId, status) {
|
||||
if (this.isEffectAllowed(effectId)) {
|
||||
const effect = this.getEffect(effectId);
|
||||
async setEffect(statusId, status) {
|
||||
if (this.isEffectAllowed(statusId)) {
|
||||
const effect = this.getEffectByStatus(statusId);
|
||||
if (!status && effect) {
|
||||
await this.deleteEmbeddedDocuments('ActiveEffect', [effect.id]);
|
||||
}
|
||||
if (status && !effect) {
|
||||
await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.prepareActiveEffect(effectId)]);
|
||||
await this.createEmbeddedDocuments("ActiveEffect", [StatusEffects.prepareActiveEffect(statusId)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async removeEffect(id) {
|
||||
const effect = this.getEmbeddedCollection("ActiveEffect").find(it => it.id == id);
|
||||
if (effect) {
|
||||
await this.deleteEmbeddedDocuments('ActiveEffect', [id]);
|
||||
}
|
||||
this.removeEffects(it => it.id == id)
|
||||
}
|
||||
|
||||
async removeEffects(filter = e => true) {
|
||||
@@ -254,17 +254,16 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
isDemiReve() {
|
||||
return this.getEffectByStatus(STATUSES.StatusDemiReve) != undefined
|
||||
}
|
||||
|
||||
getSurprise(isCombat = undefined) {
|
||||
let niveauSurprise = this.getEffects()
|
||||
.map(effect => StatusEffects.valeurSurprise(effect, isCombat))
|
||||
.reduce(Misc.sum(), 0);
|
||||
if (niveauSurprise > 1) {
|
||||
return 'totale';
|
||||
}
|
||||
if (niveauSurprise == 1) {
|
||||
return 'demi';
|
||||
}
|
||||
return '';
|
||||
return StatusEffects.typeSurprise(
|
||||
this.getEffects()
|
||||
.map(it => StatusEffects.niveauSurprise(it, isCombat))
|
||||
.reduce(Misc.sum(), 0)
|
||||
)
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
@@ -282,8 +281,20 @@ export class RdDBaseActorReve extends RdDBaseActor {
|
||||
return dialog
|
||||
}
|
||||
|
||||
createCallbackExperience() { return { action: r => { } } }
|
||||
createCallbackAppelAuMoral() { return { action: r => { } } }
|
||||
|
||||
/* -------------------------------------------- */
|
||||
createCallbackExperience() {
|
||||
return { action: r => this.appliquerAjoutExperience(r) }
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
createCallbackAppelAuMoral() {
|
||||
/* Si l'appel au moral est utilisé, on l'affiche dans le chat et on diminue éventuellement le moral */
|
||||
return { action: r => this.appliquerAppelMoral(r) }
|
||||
}
|
||||
|
||||
async appliquerAjoutExperience(rollData, hideChatMessage = 'show') { }
|
||||
async appliquerAppelMoral(rollData) { }
|
||||
|
||||
async _onCloseRollDialog(html) { }
|
||||
|
||||
|
@@ -292,7 +292,7 @@ export class RdDBaseActorSang extends RdDBaseActorReve {
|
||||
}
|
||||
|
||||
isSonne() {
|
||||
return this.getEffect(STATUSES.StatusStunned)
|
||||
return this.getEffectByStatus(STATUSES.StatusStunned)
|
||||
}
|
||||
|
||||
isEffectAllowed(effectId) { return true }
|
||||
|
@@ -27,6 +27,7 @@ export class RdDBaseActor extends Actor {
|
||||
}
|
||||
return entry && entry.length > 0 ? carac[entry[0]] : undefined;
|
||||
}
|
||||
|
||||
static getDefaultValue(actorType, path) {
|
||||
if (path.includes('.')) {
|
||||
path = path.split('.')
|
||||
@@ -743,6 +744,7 @@ export class RdDBaseActor extends Actor {
|
||||
ui.notifications.info(`${this.getAlias()} ne peut pas faire cette action: ${action}`)
|
||||
}
|
||||
|
||||
isAlcoolise() { return false }
|
||||
async jetEthylisme() { this.actionImpossible("jet d'éthylisme") }
|
||||
async rollAppelChance() { this.actionImpossible("appel à la chance") }
|
||||
async jetDeMoral() { this.actionImpossible("jet de moral") }
|
||||
|
@@ -256,8 +256,8 @@ export class Mapping {
|
||||
static descriptionSort(sort) {
|
||||
const ptSeuil = Array(sort.system.coutseuil).map(it => '*')
|
||||
const caseTMR = sort.system.caseTMRspeciale.length > 0 ? Mapping.toVar(sort.system.caseTMRspeciale) : Misc.upperFirst(TMRType[sort.system.caseTMR].name)
|
||||
const coutReve = 'r' + RdDItemSort.addSpaceToNonNumeric(sort.system.ptreve)
|
||||
const diff = 'R' + RdDItemSort.addSpaceToNonNumeric(sort.system.difficulte)
|
||||
const coutReve =RdDItemSort.coutReve(sort)
|
||||
const diff = RdDItemSort.diffReve(sort)
|
||||
return `${sort.name}${ptSeuil} (${caseTMR}) ${diff} ${coutReve}`
|
||||
}
|
||||
static toVar(caseSpeciale) {
|
||||
|
@@ -83,8 +83,8 @@ export class ChatUtility {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static async createChatWithRollMode(messageData, actor = undefined) {
|
||||
switch (game.settings.get("core", "rollMode")) {
|
||||
static async createChatWithRollMode(messageData, actor = undefined, rollMode = game.settings.get("core", "rollMode")) {
|
||||
switch (rollMode) {
|
||||
case "blindroll": // GM only
|
||||
if (!game.user.isGM) {
|
||||
ChatUtility.blindMessageToGM(messageData)
|
||||
|
@@ -103,8 +103,8 @@ export class RdDItemCompetence extends Item {
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
static isMalusEncombrementTotal(competence) {
|
||||
return competence?.name.toLowerCase().match(/(natation|acrobatie)/) || 0;
|
||||
static isMalusEncombrementTotal(competenceName) {
|
||||
return competenceName?.toLowerCase().match(/(natation|acrobatie)/) || 0;
|
||||
}
|
||||
|
||||
/* -------------------------------------------- */
|
||||
|
@@ -16,13 +16,10 @@ export const VOIES_DRACONIC = [
|
||||
/* -------------------------------------------- */
|
||||
export class RdDItemSort extends Item {
|
||||
static preloadHandlebars() {
|
||||
Handlebars.registerHelper('itemSort-spaceIfText', val => RdDItemSort.addSpaceToNonNumeric(val))
|
||||
Handlebars.registerHelper('itemSort-codeDraconic', voie => RdDItemSort.getCode(voie))
|
||||
Handlebars.registerHelper('itemSort-shortDraconic', voie => RdDItemSort.getShortVoie(voie))
|
||||
}
|
||||
|
||||
static addSpaceToNonNumeric(value) {
|
||||
return Number.isNumeric(value) || ['-', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'].includes(String(value).charAt[0]) ? value : ' ' + RdDItemSort.toVar(value)
|
||||
Handlebars.registerHelper('itemSort-diffReve', sort => RdDItemSort.diffReve(sort))
|
||||
Handlebars.registerHelper('itemSort-coutReve', sort => RdDItemSort.coutReve(sort))
|
||||
}
|
||||
|
||||
static lancements(sort) { return sort?.system.lancements.length ?? 0 }
|
||||
@@ -43,21 +40,44 @@ export class RdDItemSort extends Item {
|
||||
return value ? value.replace('variable', 'var') : ''
|
||||
}
|
||||
|
||||
static isSortOnCoord(sort, coord) {
|
||||
let tmr = TMRUtility.getTMR(coord)
|
||||
const caseTMR = sort.system.caseTMR.toLowerCase();
|
||||
const caseTMRspeciale = sort.system.caseTMRspeciale.toLowerCase();
|
||||
|
||||
return caseTMR.includes('variable')
|
||||
|| caseTMRspeciale.includes('variable')
|
||||
|| (caseTMR == tmr.type)
|
||||
|| (caseTMR.includes('special') && caseTMRspeciale.includes(coord.toLowerCase()))
|
||||
}
|
||||
|
||||
static getCaseTMR(sort) {
|
||||
const caseTMR = sort.system.caseTMR.toLowerCase();
|
||||
const caseTMRspeciale = sort.system.caseTMRspeciale.toLowerCase();
|
||||
if (caseTMR.includes('variable') || caseTMRspeciale.includes('variable') || caseTMR.includes('special')) {
|
||||
return sort.system.caseTMRspeciale
|
||||
}
|
||||
return sort.system.caseTMR
|
||||
}
|
||||
|
||||
|
||||
static diffReve(sort) { return RdDItemSort.toVar((sort.system.difficulte.match(/\-?(\d)+/) ? 'R' : 'R ') + sort.system.difficulte) }
|
||||
static coutReve(sort) { return RdDItemSort.toVar((sort.system.ptreve.match(/(\d)+\+?/) ? 'r' : 'r ') + sort.system.ptreve) }
|
||||
static getDraconicsSort(competencesDraconic, sort) {
|
||||
// se baser sur la voie du sort?
|
||||
switch (Grammar.toLowerCaseNoAccent(sort.name)) {
|
||||
case "lecture d'aura":
|
||||
case "detection d'aura":
|
||||
return competencesDraconic;
|
||||
return competencesDraconic
|
||||
case "annulation de magie":
|
||||
return competencesDraconic.filter(it => !RdDItemCompetence.isThanatos(it));
|
||||
return competencesDraconic.filter(it => !RdDItemCompetence.isThanatos(it))
|
||||
}
|
||||
const voies = sort.system.draconic.split('/')
|
||||
return voies.map(voie => RdDItemCompetence.getVoieDraconic(competencesDraconic, voie))
|
||||
}
|
||||
|
||||
static getBestDraconicSort(competencesDraconic, sort) {
|
||||
return RdDItemSort.getDraconicsSort(competencesDraconic, sort).sort(Misc.descending(it => it.system.niveau)).find(it=>true)
|
||||
return RdDItemSort.getDraconicsSort(competencesDraconic, sort).sort(Misc.descending(it => it.system.niveau)).find(it => true)
|
||||
}
|
||||
|
||||
static getOrdreCode(code) {
|
||||
|
@@ -38,6 +38,12 @@ export class Misc {
|
||||
return (a, b) => Number(a) + Number(b);
|
||||
}
|
||||
|
||||
static and(predicates) {
|
||||
return value => predicates.map(predicate => predicate(value))
|
||||
.reduce((v1, v2) => v1 && v2, true);
|
||||
}
|
||||
|
||||
|
||||
static ascending(orderFunction = x => x) {
|
||||
return (a, b) => Misc.sortingBy(orderFunction(a), orderFunction(b));
|
||||
}
|
||||
@@ -60,6 +66,11 @@ export class Misc {
|
||||
static arrayOrEmpty(items) {
|
||||
return items?.length ? items : [];
|
||||
}
|
||||
|
||||
static findOrFirst(list, predicate) {
|
||||
return list.find(predicate) ?? list[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
|
||||
@@ -75,13 +86,17 @@ export class Misc {
|
||||
return Math.round(num * power10n) / power10n;
|
||||
}
|
||||
|
||||
static getFractionHtml(diviseur) {
|
||||
if (!diviseur || diviseur <= 1) return undefined;
|
||||
switch (diviseur || 1) {
|
||||
case 2: return '½';
|
||||
case 4: return '¼';
|
||||
default: return '1/' + diviseur;
|
||||
|
||||
static getFractionOneN(divider) {
|
||||
if (!divider || divider == 1) {
|
||||
return 1
|
||||
}
|
||||
switch (divider) {
|
||||
case 2: return '½'
|
||||
case 4: return '¼'
|
||||
case 8: return '⅛'
|
||||
}
|
||||
return `1/${divider}`
|
||||
}
|
||||
|
||||
static indexLowercase(list) {
|
||||
|
@@ -37,21 +37,37 @@ const TABLE_CARACTERISTIQUES_DERIVEES = {
|
||||
32: { xp: 180, niveau: 11, poids: "1501-2000", poidsMin: 1501, poidsMax: 2000, plusdom: +11, sconst: 10, sust: 17 }
|
||||
};
|
||||
|
||||
export const CARACS = {
|
||||
TAILLE: 'taille',
|
||||
APPARENCE: 'apparence',
|
||||
CONSTITUTION: 'constitution',
|
||||
FORCE: 'force',
|
||||
AGILITE: 'agilite',
|
||||
DEXTERITE: 'dexterite',
|
||||
VUE: 'vue',
|
||||
OUIE: 'ouie',
|
||||
ODORATGOUT: 'odoratgout',
|
||||
VOLONTE: 'volonte',
|
||||
INTELLECT: 'intellect',
|
||||
EMPATHIE: 'empathie',
|
||||
REVE: 'reve',
|
||||
CHANCE: 'chance',
|
||||
}
|
||||
export const LIST_CARAC_PERSONNAGE = {
|
||||
'taille': { code: 'taille', label: 'Taille', isCarac: true, path: 'system.carac.taille.value' },
|
||||
'apparence': { code: 'apparence', label: 'Apparence', isCarac: true, path: 'system.carac.apparence.value' },
|
||||
'constitution': { code: 'constitution', label: 'Constitution', isCarac: true, path: 'system.carac.constitution.value' },
|
||||
'force': { code: 'force', label: 'Force', isCarac: true, path: 'system.carac.force.value' },
|
||||
'agilite': { code: 'agilite', label: 'Agilité', isCarac: true, path: 'system.carac.agilite.value' },
|
||||
'dexterite': { code: 'dexterite', label: 'Dextérité', isCarac: true, path: 'system.carac.dexterite.value' },
|
||||
'vue': { code: 'vue', label: 'Vue', isCarac: true, path: 'system.carac.vue.value' },
|
||||
'ouie': { code: 'ouie', label: 'Ouïe', isCarac: true, path: 'system.carac.ouie.value' },
|
||||
'odoratgout': { code: 'odoratgout', label: 'Odorat-Goût', isCarac: true, path: 'system.carac.odoratgout.value' },
|
||||
'volonte': { code: 'volonte', label: 'Volonté', isCarac: true, path: 'system.carac.volonte.value' },
|
||||
'intellect': { code: 'intellect', label: 'Intellect', isCarac: true, path: 'system.carac.intellect.value' },
|
||||
'empathie': { code: 'empathie', label: 'Empathie', isCarac: true, path: 'system.carac.empathie.value' },
|
||||
'reve': { code: 'reve', label: 'Rêve', isCarac: true, path: 'system.carac.reve.value' },
|
||||
'chance': { code: 'chance', label: 'Chance', isCarac: true, path: 'system.carac.chance.value' },
|
||||
[CARACS.TAILLE]: { code: CARACS.TAILLE, label: 'Taille', isCarac: true, path: 'system.carac.taille.value' },
|
||||
[CARACS.APPARENCE]: { code: CARACS.APPARENCE, label: 'Apparence', isCarac: true, path: 'system.carac.apparence.value' },
|
||||
[CARACS.CONSTITUTION]: { code: CARACS.CONSTITUTION, label: 'Constitution', isCarac: true, path: 'system.carac.constitution.value' },
|
||||
[CARACS.FORCE]: { code: CARACS.FORCE, label: 'Force', isCarac: true, path: 'system.carac.force.value' },
|
||||
[CARACS.AGILITE]: { code: CARACS.AGILITE, label: 'Agilité', isCarac: true, path: 'system.carac.agilite.value' },
|
||||
[CARACS.DEXTERITE]: { code: CARACS.DEXTERITE, label: 'Dextérité', isCarac: true, path: 'system.carac.dexterite.value' },
|
||||
[CARACS.VUE]: { code: CARACS.VUE, label: 'Vue', isCarac: true, path: 'system.carac.vue.value' },
|
||||
[CARACS.OUIE]: { code: CARACS.OUIE, label: 'Ouïe', isCarac: true, path: 'system.carac.ouie.value' },
|
||||
[CARACS.ODORATGOUT]: { code: CARACS.ODORATGOUT, label: 'Odorat-Goût', isCarac: true, path: 'system.carac.odoratgout.value' },
|
||||
[CARACS.VOLONTE]: { code: CARACS.VOLONTE, label: 'Volonté', isCarac: true, path: 'system.carac.volonte.value' },
|
||||
[CARACS.INTELLECT]: { code: CARACS.INTELLECT, label: 'Intellect', isCarac: true, path: 'system.carac.intellect.value' },
|
||||
[CARACS.EMPATHIE]: { code: CARACS.EMPATHIE, label: 'Empathie', isCarac: true, path: 'system.carac.empathie.value' },
|
||||
[CARACS.REVE]: { code: CARACS.REVE, label: 'Rêve', isCarac: true, path: 'system.carac.reve.value' },
|
||||
[CARACS.CHANCE]: { code: CARACS.CHANCE, label: 'Chance', isCarac: true, path: 'system.carac.chance.value' },
|
||||
'protection': { code: 'protection', label: 'Protection naturelle', isCarac: false, path: 'system.attributs.protection.value' },
|
||||
'beaute': { code: 'beaute', label: 'Beauté', isCarac: false, path: 'system.background.beaute.value' }
|
||||
}
|
||||
@@ -69,7 +85,7 @@ const LIST_CARAC_DERIVEE = {
|
||||
'reve-actuel': { code: "reve-actuel", label: 'Rêve actuel', path: 'system.reve.reve.value' },
|
||||
}
|
||||
|
||||
const LIST_CARAC_ROLL = Object.values(LIST_CARAC_PERSONNAGE).filter(it => it.isCarac && it.code != 'taille')
|
||||
export const LIST_CARAC_ROLL = Object.values(LIST_CARAC_PERSONNAGE).filter(it => it.isCarac && it.code != 'taille')
|
||||
.concat(Object.values(LIST_CARAC_AUTRES))
|
||||
.concat(Object.values(LIST_CARAC_DERIVEE))
|
||||
|
||||
@@ -95,27 +111,41 @@ export class RdDCarac {
|
||||
return Object.values(LIST_CARAC_PERSONNAGE).filter(filter)
|
||||
}
|
||||
|
||||
static isAgiliteOuDerobee(selectedCarac) {
|
||||
return selectedCarac?.label.match(/(Agilité|Dérobée)/);
|
||||
static isAgiliteOuDerobee(caracLabel) {
|
||||
return RdDCarac.isAgilite(caracLabel)
|
||||
|| RdDCarac.isDerobee(caracLabel)
|
||||
}
|
||||
|
||||
static isVolonte(selectedCarac) {
|
||||
return selectedCarac?.label == 'Volonté';
|
||||
static isDerobee(caracLabel) {
|
||||
return Grammar.equalsInsensitive(caracLabel, LIST_CARAC_PERSONNAGE.agilite.code);
|
||||
}
|
||||
static isChance(selectedCarac) {
|
||||
return selectedCarac?.label?.toLowerCase()?.match(/chance( actuelle)?/);
|
||||
|
||||
static isAgilite(caracLabel) {
|
||||
return Grammar.equalsInsensitive(caracLabel, LIST_CARAC_DERIVEE.derobee.code);
|
||||
}
|
||||
static isReve(selectedCarac) {
|
||||
return selectedCarac?.label?.toLowerCase()?.match(/r(e|ê)ve(( |-)actuel)?/);
|
||||
|
||||
static isIntellect(caracLabel) {
|
||||
return Grammar.toLowerCaseNoAccent(caracLabel) == 'intellect';
|
||||
}
|
||||
|
||||
static isVolonte(caracLabel) {
|
||||
return Grammar.toLowerCaseNoAccent(caracLabel) == 'volonte';
|
||||
}
|
||||
static isChance(caracLabel) {
|
||||
return Grammar.toLowerCaseNoAccent(caracLabel)?.match(/chance(( |-)?actuelle)?/);
|
||||
}
|
||||
static isReve(caracLabel) {
|
||||
return Grammar.toLowerCaseNoAccent(caracLabel)?.match(/reve(( |-)?actuel)?/);
|
||||
}
|
||||
|
||||
/**
|
||||
* L’appel à la chance n’est possible que pour recommencer les jets d’actions physiques :
|
||||
* tous les jets de combat, de FORCE, d’AGILITÉ, de DEXTÉRITÉ, de Dérobée, d’APPARENCE,
|
||||
* ainsi que de Perception active et volontaire.
|
||||
* Le moral ne s'utilise aussi que sur les actions physiques
|
||||
*/
|
||||
static isActionPhysique(selectedCarac) {
|
||||
return Grammar.toLowerCaseNoAccent(selectedCarac?.label)
|
||||
static isActionPhysique(caracLabel) {
|
||||
return Grammar.toLowerCaseNoAccent(caracLabel)
|
||||
?.match(/(apparence|force|agilite|dexterite|vue|ouie|gout|odorat|empathie|melee|tir|lancer|derobee)/) != null
|
||||
}
|
||||
|
||||
|
@@ -635,8 +635,9 @@ export class RdDCombat {
|
||||
if (taille <= 20) return { msg: "ogre", diff: 2 };
|
||||
return { msg: "gigantesque", diff: 4 };
|
||||
}
|
||||
|
||||
_ajustementMouvement(defender) {
|
||||
if (defender.getSurprise(true)) return { msg: "immobile (surprise)", diff: 0 };
|
||||
if (defender.getSurprise(true) != '') return { msg: "immobile (surprise)", diff: 0 };
|
||||
if (game.combat?.combatants.find(it => it.actorId == defender.id)) return { msg: "en mouvement (combat)", diff: -4 };
|
||||
return { msg: "à déterminer (0 immobile, -3 actif, -4 en mouvement, -5 en zig-zag)", diff: -3 };
|
||||
}
|
||||
|
@@ -85,6 +85,7 @@ import { RdDJournalSheet } from "./journal/journal-sheet.js"
|
||||
import { RdDCombatManager, RdDCombat } from "./rdd-combat.js"
|
||||
import { Migrations } from './migrations.js'
|
||||
|
||||
import RollDialog from "./roll/roll-dialog.mjs"
|
||||
|
||||
/**
|
||||
* RdD system
|
||||
@@ -290,6 +291,7 @@ export class SystemReveDeDragon {
|
||||
RdDPossession.init()
|
||||
TMRRencontres.init()
|
||||
ExportScriptarium.init()
|
||||
RollDialog.init()
|
||||
}
|
||||
|
||||
initSettings() {
|
||||
@@ -373,7 +375,7 @@ export class SystemReveDeDragon {
|
||||
|
||||
StatusEffects.onReady()
|
||||
RdDDice.onReady()
|
||||
|
||||
RollDialog.onReady()
|
||||
RdDStatBlockParser.parseStatBlock()
|
||||
/* -------------------------------------------- */
|
||||
/* Affiche/Init le calendrier */
|
||||
@@ -402,6 +404,10 @@ export class SystemReveDeDragon {
|
||||
` })
|
||||
}
|
||||
}
|
||||
|
||||
roll(rollData, actors, options){
|
||||
RollDialog.create(rollData, actors, options)
|
||||
}
|
||||
}
|
||||
|
||||
SystemReveDeDragon.start()
|
||||
|
@@ -109,7 +109,7 @@ export class RdDResolutionTable {
|
||||
rolled.caracValue = caracValue;
|
||||
rolled.finalLevel = finalLevel;
|
||||
rolled.bonus = rollData.bonus;
|
||||
rolled.factorHtml = Misc.getFractionHtml(rollData.diviseurSignificative);
|
||||
rolled.factorHtml = Misc.getFractionOneN(rollData.diviseurSignificative);
|
||||
|
||||
if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) {
|
||||
rolled.niveauNecessaire = this.findNiveauNecessaire(caracValue, rolled.roll);
|
||||
|
@@ -123,7 +123,7 @@ export class RdDRollResolutionTable extends Dialog {
|
||||
|
||||
// Mise à jour valeurs
|
||||
this.html.find("[name='carac']").val(rollData.caracValue);
|
||||
this.html.find(".roll-param-resolution").text(rollData.selectedCarac.value + " / " + Misc.toSignedString(rollData.finalLevel));
|
||||
this.html.find(".roll-part-resolution").text(rollData.selectedCarac.value + " / " + Misc.toSignedString(rollData.finalLevel));
|
||||
this.html.find("div.placeholder-resolution").empty().append(htmlTable)
|
||||
|
||||
}
|
||||
|
@@ -5,7 +5,8 @@ export class RdDRollResult {
|
||||
static async displayRollData(rollData, actor = undefined, template = 'chat-resultat-general.hbs') {
|
||||
const chatMessage = await ChatUtility.createChatWithRollMode(
|
||||
{ content: await RdDRollResult.buildRollDataHtml(rollData, template) },
|
||||
actor
|
||||
actor,
|
||||
rollData.current?.rollmode?.key
|
||||
)
|
||||
return chatMessage
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ export class RdDRoll extends Dialog {
|
||||
difficultesLibres: CONFIG.RDD.difficultesLibres,
|
||||
etat: actor.getEtatGeneral(),
|
||||
moral: actor.getMoralTotal(), /* La valeur du moral pour les jets de volonté */
|
||||
amoureux: actor.listeSuivants(it => it.coeur > 0),
|
||||
amoureux: actor.listeAmoureux(),
|
||||
carac: foundry.utils.duplicate(actor.system.carac),
|
||||
finalLevel: 0,
|
||||
diffConditions: 0,
|
||||
@@ -54,7 +54,7 @@ export class RdDRoll extends Dialog {
|
||||
surenc: actor.isSurenc(),
|
||||
encTotal: true
|
||||
},
|
||||
isMalusEncombrementTotal: RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
||||
isMalusEncombrementTotal: RdDItemCompetence.isMalusEncombrementTotal(rollData.competence?.name),
|
||||
encTotal: actor.getEncTotal(),
|
||||
ajustementAstrologique: actor.ajustementAstrologique(),
|
||||
surprise: actor.getSurprise(false),
|
||||
@@ -314,15 +314,15 @@ export class RdDRoll extends Dialog {
|
||||
rollData.dmg = rollData.attackerRoll?.dmg ?? RdDBonus.dmg(rollData, this.actor)
|
||||
rollData.caracValue = parseInt(rollData.selectedCarac.value)
|
||||
rollData.dmg.mortalite = rollData.dmg.mortalite ?? 'mortel';
|
||||
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac);
|
||||
rollData.use.appelAuMoral = this.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac?.label);
|
||||
|
||||
RollDataAjustements.calcul(rollData, this.actor);
|
||||
|
||||
const resolutionTable = await RdDResolutionTable.buildHTMLTable(RdDResolutionTable.subTable(rollData.caracValue, rollData.finalLevel))
|
||||
const adjustements = await this.buildAjustements(rollData);
|
||||
|
||||
HtmlUtility.showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac));
|
||||
HtmlUtility.showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac));
|
||||
HtmlUtility.showControlWhen(this.html.find(".use-encTotal"), rollData.ajustements.encTotal.visible && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac?.label));
|
||||
HtmlUtility.showControlWhen(this.html.find(".use-surenc"), rollData.ajustements.surenc.visible && RdDCarac.isActionPhysique(rollData.selectedCarac?.label));
|
||||
HtmlUtility.showControlWhen(this.html.find(".use-astrologique"), rollData.ajustements.astrologique.visible);
|
||||
HtmlUtility.showControlWhen(this.html.find(".utilisation-moral"), rollData.use.appelAuMoral);
|
||||
HtmlUtility.showControlWhen(this.html.find(".divAppelAuMoral"), rollData.use.appelAuMoral);
|
||||
|
@@ -221,6 +221,7 @@ export class RdDUtility {
|
||||
'systems/foundryvtt-reve-de-dragon/templates/common/compendium-link.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-description-overflow.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-description-sort.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-description.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-ajustements.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-astrologique.hbs',
|
||||
'systems/foundryvtt-reve-de-dragon/templates/partial-roll-coeur.hbs',
|
||||
@@ -319,6 +320,7 @@ export class RdDUtility {
|
||||
// gestion des dates et heures
|
||||
Handlebars.registerHelper('timestamp-imgSigneHeure', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigneHeure(heure)) });
|
||||
Handlebars.registerHelper('timestamp-imgSigne', (heure) => { return new Handlebars.SafeString(RdDTimestamp.imgSigne(heure)) });
|
||||
Handlebars.registerHelper('timestamp-label', (heure) => RdDTimestamp.definition(heure)?.label ?? 'inconnue')
|
||||
Handlebars.registerHelper('timestamp-definition', (heure) => RdDTimestamp.definition(heure))
|
||||
Handlebars.registerHelper('timestamp-extract', timestamp => new RdDTimestamp(timestamp).toCalendrier());
|
||||
Handlebars.registerHelper('timestamp-formulesDuree', () => RdDTimestamp.formulesDuree());
|
||||
@@ -814,9 +816,8 @@ export class RdDUtility {
|
||||
|
||||
static getSelectedToken(actor) {
|
||||
if (canvas.tokens.controlled.length > 0) {
|
||||
const tokens = canvas.tokens.controlled
|
||||
.filter(it => it.actor.id == actor.id)
|
||||
return tokens[0]
|
||||
return canvas.tokens.controlled
|
||||
.find(it => it.actor.id == actor.id)
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
60
module/roll/roll-basic-parts.mjs
Normal file
@@ -0,0 +1,60 @@
|
||||
import { ActorToken } from "../actor-token.mjs"
|
||||
|
||||
export class RollBasicParts {
|
||||
|
||||
restore(rollData) {
|
||||
rollData.ids.sceneId = rollData.ids.sceneId ?? canvas.scene.id
|
||||
rollData.active = RollBasicParts.$getActor(rollData)
|
||||
rollData.opponent = RollBasicParts.$getOpponent(rollData)
|
||||
if (rollData.mode.opposed == undefined) {
|
||||
rollData.mode.opposed = rollData.opponent != null
|
||||
}
|
||||
}
|
||||
|
||||
initFrom(rollData) {
|
||||
return {
|
||||
selected: {},
|
||||
mode: {
|
||||
current: rollData.mode.current
|
||||
},
|
||||
ids: {
|
||||
sceneId: rollData.ids.sceneId,
|
||||
actorId: rollData.active.id,
|
||||
actorTokenId: rollData.active.tokenId,
|
||||
opponentId: rollData.mode.opposed ? rollData.opponent.id : undefined,
|
||||
opponentTokenId: rollData.mode.opposed ? rollData.opponent.tokenId : undefined,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static $getActor(rollData) {
|
||||
if (rollData.ids.actorTokenId) {
|
||||
return ActorToken.fromTokenId(rollData.ids.actorTokenId, rollData.ids.sceneId)
|
||||
}
|
||||
else {
|
||||
const actorId = rollData.ids.actorId ?? (canvas.tokens.controlled.length == 1
|
||||
/** TODO: jets de plusieurs personnages??? */
|
||||
? canvas.tokens.controlled[0]
|
||||
: undefined)
|
||||
return ActorToken.fromActorId(actorId, () => { throw new Error("Pas d'acteur sélectionné") })
|
||||
}
|
||||
}
|
||||
|
||||
static $getOpponent(rollData) {
|
||||
if (rollData.ids.opponentTokenId) {
|
||||
return ActorToken.fromTokenId(rollData.ids.opponentTokenId, rollData.ids.sceneId)
|
||||
}
|
||||
else if (rollData.ids.opponentId) {
|
||||
return ActorToken.fromActorId(rollData.ids.opponentId)
|
||||
}
|
||||
else {
|
||||
const targets = Array.from(game.user.targets)
|
||||
if (targets.length == 1) {
|
||||
return ActorToken.fromToken(targets[0])
|
||||
}
|
||||
else {
|
||||
return undefined
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
28
module/roll/roll-constants.mjs
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
export const ROLL_MODE_ATTAQUE = 'attaque'
|
||||
export const ROLL_MODE_COMP = 'comp'
|
||||
export const ROLL_MODE_DEFENSE = 'defense'
|
||||
export const ROLL_MODE_JEU = 'jeu'
|
||||
export const ROLL_MODE_MEDITATION = 'meditation'
|
||||
export const ROLL_MODE_OEUVRE = 'oeuvre'
|
||||
export const ROLL_MODE_SORT = 'sort'
|
||||
export const ROLL_MODE_TACHE = 'tache'
|
||||
|
||||
export const DIFF_MODE = {
|
||||
LIBRE: 'libre',
|
||||
ATTAQUE: 'attaque',
|
||||
IMPOSEE: 'imposee',
|
||||
DEFENSE: 'defense',
|
||||
DEFAUT: 'defaut',
|
||||
AUCUN: 'aucun'
|
||||
}
|
||||
|
||||
export const DIFF_MODES = {
|
||||
[DIFF_MODE.LIBRE]: { key: DIFF_MODE.LIBRE, label: "Difficulté libre", libre: true, visible: true, max: 0 },
|
||||
[DIFF_MODE.ATTAQUE]: { key: DIFF_MODE.ATTAQUE, label: "Difficulté d'attaque", libre: true, visible: true, max: 0 },
|
||||
[DIFF_MODE.IMPOSEE]: { key: DIFF_MODE.IMPOSEE, label: "Diffficulté imposée", libre: false, visible: true, max: 0 },
|
||||
[DIFF_MODE.DEFENSE]: { key: DIFF_MODE.DEFENSE, label: "Diffficulté défense", libre: false, visible: true, max: 0 },
|
||||
[DIFF_MODE.DEFAUT]: { key: DIFF_MODE.DEFAUT, label: "Difficulté", libre: true, visible: true, max: 5 },
|
||||
[DIFF_MODE.AUCUN]: { key: DIFF_MODE.AUCUN, label: "", libre: false, visible: false, max: 0 },
|
||||
}
|
||||
|
90
module/roll/roll-dialog-adapter.mjs
Normal file
@@ -0,0 +1,90 @@
|
||||
import { Misc } from "../misc.js";
|
||||
import { PART_APPELMORAL } from "./roll-part-appelmoral.mjs";
|
||||
import { PART_COMP } from "./roll-part-comp.mjs";
|
||||
import { RdDResolutionTable } from "../rdd-resolution-table.js";
|
||||
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js";
|
||||
import { PART_OEUVRE } from "./roll-part-oeuvre.mjs";
|
||||
|
||||
/* -------------------------------------------- */
|
||||
export class RollDialogAdapter {
|
||||
|
||||
async rollDice(rollData, rollTitle) {
|
||||
const chances = this.computeChances({
|
||||
carac: rollData.current.carac.value,
|
||||
diff: rollData.current.totaldiff,
|
||||
bonus: rollData.current.bonus,
|
||||
sign: rollData.current.sign,
|
||||
showDice: rollData.options.showDice,
|
||||
rollMode: rollData.current.rollmode.key
|
||||
})
|
||||
|
||||
const rolled = await this.rollChances(rollData, chances)
|
||||
this.adjustRollDataForV1(rollData, rolled, rollTitle)
|
||||
|
||||
return rolled
|
||||
}
|
||||
|
||||
computeChances({ carac, diff, bonus, sign, showDice, rollMode }) {
|
||||
const chances = foundry.utils.duplicate(RdDResolutionTable.computeChances(carac, diff))
|
||||
RdDResolutionTable._updateChancesWithBonus(chances, bonus, diff)
|
||||
RdDResolutionTable._updateChancesFactor(chances, sign)
|
||||
chances.showDice = showDice
|
||||
chances.rollMode = rollMode
|
||||
return chances
|
||||
}
|
||||
|
||||
async rollChances(rollData, chances) {
|
||||
const rolled = await RdDResolutionTable.rollChances(chances, rollData.current.sign, rollData.current.resultat)
|
||||
rolled.caracValue = rollData.current.carac.value
|
||||
rolled.finalLevel = rollData.current.totaldiff
|
||||
rolled.bonus = rollData.current.bonus ?? 0
|
||||
rolled.factorHtml = Misc.getFractionOneN(rollData.current.sign.diviseur)
|
||||
return rolled
|
||||
}
|
||||
|
||||
adjustRollDataForV1(rollData, rolled, rollTitle) {
|
||||
// temporaire pour être homogène roll v1
|
||||
rollData.alias = rollData.active.actor.getAlias()
|
||||
// pour experience
|
||||
rollData.finalLevel = rollData.current.totaldiff
|
||||
if (rollData.use == undefined) { rollData.use = {} }
|
||||
if (rollData.show == undefined) { rollData.show = {} }
|
||||
if (rollData.ajustements == undefined) {
|
||||
rollData.ajustements = {}
|
||||
}
|
||||
rollData.selectedCarac = rollData.active.actor.system.carac[rollData.current.carac.key]
|
||||
|
||||
const compKey = rollData.current.comp?.key
|
||||
if (compKey) {
|
||||
rollData.competence = rollData.refs[PART_COMP].all.find(it => it.key == compKey)?.comp
|
||||
rollData.jetResistance = rollData.mode.jetResistance
|
||||
}
|
||||
const oeuvreKey = rollData.current.oeuvre?.key
|
||||
if (oeuvreKey) {
|
||||
const oeuvreCurrent = rollData.current[PART_OEUVRE];
|
||||
rollData.oeuvre = oeuvreCurrent.oeuvre
|
||||
// rollData.oeuvre = rollData.refs[PART_OEUVRE].oeuvres.find(it => it.key == oeuvreKey)?.oeuvre
|
||||
rollData.art = oeuvreCurrent.art.type
|
||||
}
|
||||
// pour appel moral
|
||||
rollData.diviseurSignificative = rollData.current.sign
|
||||
if (rollData.current[PART_APPELMORAL]?.checked) {
|
||||
rollData.use.moral = true
|
||||
}
|
||||
rollData.rolled = rolled
|
||||
if (ReglesOptionnelles.isUsing("afficher-colonnes-reussite")) {
|
||||
rolled.niveauNecessaire = this.findNiveauNecessaire(carac, rolled.roll)
|
||||
rolled.ajustementNecessaire = rolled.niveauNecessaire - diff
|
||||
}
|
||||
rollData.ajustements = rollData.ajustements.map(aj => {
|
||||
return {
|
||||
used: true,
|
||||
label: aj.label,
|
||||
value: aj.diff,
|
||||
descr: aj.diff == undefined ? aj.label : undefined
|
||||
}
|
||||
})
|
||||
rollData.show.title = rollTitle
|
||||
}
|
||||
|
||||
}
|
439
module/roll/roll-dialog.mjs
Normal file
@@ -0,0 +1,439 @@
|
||||
import { Misc } from "../misc.js";
|
||||
import { RollModeComp } from "./roll-mode-comp.mjs";
|
||||
import { RollModeTache } from "./roll-mode-tache.mjs";
|
||||
import { RollModeAttaque } from "./roll-mode-attaque.mjs";
|
||||
import { RollModeDefense } from "./roll-mode-defense.mjs";
|
||||
import { RollModeMeditation } from "./roll-mode-meditation.mjs";
|
||||
import { RollModeSort } from "./roll-mode-sort.mjs";
|
||||
import { RollModeOeuvre } from "./roll-mode-oeuvre.mjs";
|
||||
import { RollModeJeu } from "./roll-mode-jeu.mjs";
|
||||
|
||||
import { RollPartAction } from "./roll-part-action.mjs";
|
||||
import { RollPartActor } from "./roll-part-actor.mjs";
|
||||
import { RollPartAppelMoral } from "./roll-part-appelmoral.mjs";
|
||||
import { RollPartAstrologique } from "./roll-part-astrologique.mjs";
|
||||
import { RollPartCarac } from "./roll-part-carac.mjs";
|
||||
import { RollPartCoeur } from "./roll-part-coeur.mjs";
|
||||
import { PART_COMP, RollPartComp } from "./roll-part-comp.mjs";
|
||||
import { RollPartConditions } from "./roll-part-conditions.mjs";
|
||||
import { RollPartDiff } from "./roll-part-diff.mjs";
|
||||
import { RollPartEncTotal } from "./roll-part-enctotal.mjs";
|
||||
import { RollPartEtat } from "./roll-part-etat.mjs";
|
||||
import { RollPartEthylisme } from "./roll-part-ethylisme.mjs";
|
||||
import { RollPartMalusArmure } from "./roll-part-malusarmure.mjs";
|
||||
import { RollPartMeditation } from "./roll-part-meditation.mjs";
|
||||
import { RollPartMoral } from "./roll-part-moral.mjs";
|
||||
import { RollPartOpponent } from "./roll-part-opponent.mjs";
|
||||
import { RollPartSurEnc } from "./roll-part-surenc.mjs";
|
||||
import { RollPartTricher } from "./roll-part-tricher.mjs";
|
||||
import { RollPartTache } from "./roll-part-tache.mjs";
|
||||
import { RollPartOeuvre } from "./roll-part-oeuvre.mjs";
|
||||
import { RollPartSort } from "./roll-part-sort.mjs";
|
||||
import { RollBasicParts } from "./roll-basic-parts.mjs";
|
||||
import { RollPartRollMode } from "./roll-part-rollmode.mjs";
|
||||
import { RollPartJeu } from "./roll-part-jeu.mjs";
|
||||
import { RollPartSign } from "./roll-part-sign.mjs";
|
||||
import { RollPartAttaque } from "./roll-part-attaque.mjs";
|
||||
import { RollPartDefense } from "./roll-part-defense.mjs";
|
||||
import { RollDialogAdapter } from "./roll-dialog-adapter.mjs";
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs";
|
||||
import { ROLL_MODE_COMP } from "./roll-constants.mjs";
|
||||
|
||||
const { HandlebarsApplicationMixin, ApplicationV2 } = foundry.applications.api
|
||||
const doNothing = (dialog) => { }
|
||||
|
||||
const ROLL_MODE_TABS = [
|
||||
new RollModeComp(),
|
||||
new RollModeTache(),
|
||||
new RollModeAttaque(),
|
||||
new RollModeDefense(),
|
||||
// new RollModeParade??
|
||||
// new RollModeEsquive??
|
||||
// new RollModeResistance ??
|
||||
new RollModeSort(),
|
||||
new RollModeMeditation(),
|
||||
new RollModeOeuvre(),
|
||||
new RollModeJeu(),
|
||||
]
|
||||
|
||||
const BASIC_PARTS = new RollBasicParts()
|
||||
|
||||
const ROLL_PARTS = [
|
||||
new RollPartActor(),
|
||||
new RollPartAction(),
|
||||
new RollPartOpponent(),
|
||||
new RollPartCarac(),
|
||||
new RollPartComp(),
|
||||
|
||||
new RollPartDiff(),
|
||||
new RollPartAttaque(),
|
||||
new RollPartDefense(),
|
||||
new RollPartMeditation(),
|
||||
new RollPartSort(),
|
||||
new RollPartTache(),
|
||||
new RollPartOeuvre(),
|
||||
new RollPartJeu(),
|
||||
|
||||
new RollPartSign(),
|
||||
|
||||
new RollPartEtat(),
|
||||
new RollPartConditions(),
|
||||
new RollPartEthylisme(),
|
||||
new RollPartMalusArmure(),
|
||||
new RollPartEncTotal(),
|
||||
new RollPartSurEnc(),
|
||||
new RollPartAppelMoral(),
|
||||
new RollPartMoral(),
|
||||
new RollPartCoeur(),
|
||||
new RollPartAstrologique(),
|
||||
new RollPartTricher(),
|
||||
new RollPartRollMode(),
|
||||
]
|
||||
|
||||
/**
|
||||
* Extend the base Dialog entity to select roll parameters
|
||||
* @extends {Dialog}
|
||||
* # Principes
|
||||
* - une seule fenêtre de dialogue (classe RollDialog)
|
||||
* - plusieurs modes de fonctionnement (classe RollMode)
|
||||
* - gestion uniforme des modificateurs (classe RollPart)
|
||||
* - un objet rollData contient les informations liées à un jet de dés
|
||||
* - un rollData doit pouvoir être "réduit" pour fournir les informations significatives
|
||||
* d'un jet de dés
|
||||
* - un rollData réduit doit pouvoir être complété pour afficher la même fenêtre
|
||||
* - un rollData réduit sera utilisé pour piloter l'ouverture de la fenêtre
|
||||
*
|
||||
* - TODO: une classe de base RollChatMessage gerera les messages correspondant aux résultats du dés
|
||||
* - TODO: réfléchir aux messages supplémentaires gérés par RdDCombat ?
|
||||
*
|
||||
* ## Modes de fonctionnement - RollMode
|
||||
*
|
||||
* Un mode de fonctionnement (RollMode) détermine quelles parties (RollPart) de la
|
||||
* fenêtre RollDialog sont actives, mais aussi quels sont les effets du jet.
|
||||
*
|
||||
* - chaque mode de fonctionnement peut impacter les RollPart utilisés, les données
|
||||
* attendues et ajoutées au rollData.
|
||||
* - chaque mode de fonctionnement peut définir le template de ChatMessage correspondant
|
||||
* - Le mode de fonctionnement détermine aussi quelles sont les effets du jet:
|
||||
* - quelle ChatMessage afficher dans le tchat?
|
||||
* - en cas d'attaque/de défense, quelles sont les suites à donner?
|
||||
* - en cas de lancement de sort, réduire les points de rêve
|
||||
* - en cas de méditation, créer le signe draconique
|
||||
* - en cas de tâche, ajuster les points de tâche
|
||||
*
|
||||
*
|
||||
* ## Modificateurs - RollPart
|
||||
* - Chaque modificateur a:
|
||||
* - un code (comp, carac, diff, ...)
|
||||
* - une partie dédiée pour sauvegarder son contexte
|
||||
* - le contexte d'un RollPart est stocké dans le rollData de la fenêtre RollDialog,
|
||||
* dans des parties dédiés:
|
||||
* - `rollData.refs[code]` pour les données de référentiel (liste de compétences, ...)
|
||||
* - `rollData.current[code]` pour les informations d'état courante (la compétence sélectionnée, ...)
|
||||
* - `rollData.selected[code]` pour les informations à sauvegarder, et utilisées pour paramétrer l'ouverture
|
||||
* - Chaque RollPart gère ses données dans cet espace dédié.
|
||||
* - Chaque RollPart a un sous-template dédié, et indique où il doit s'afficher dans le RollDialog
|
||||
* - Chaque RollPart peut enregistrer ses propres events handlers pour mettre à jour son contexte (et généralement réafficher le RollDialo)
|
||||
* - Chaque RollPart fournit les informations contextuelles associées au jet
|
||||
* - TODO: chaque RollPart peut fournir un sous-template pour le ChatMessage correspondant au résultat du dé.
|
||||
*
|
||||
* ## boucle de rétroaction
|
||||
* Lors de l'affichage, chaque RollPart peut fournir un filtre pour les autres RollParts.
|
||||
* Ce filtre sert principalement à filtrer les caractéristiques/compétense.
|
||||
*
|
||||
* Une fois ce filtrage effectué, chaque RollPart va pouvoir modifier sa partie du contexte
|
||||
* de la fenêtre, permettant à son template hbs d'avoir les donnéers à afficher.
|
||||
*
|
||||
* Enfin, lors de l'affichage (vu que les contrêles sont réaffichés), il peut
|
||||
* enregistrer les listeners appropriés.
|
||||
*
|
||||
* ## Utilisation des informations sélectionnées
|
||||
*
|
||||
* Le rollData est la structure de stockage, et sert à préparer le jet de dé.
|
||||
* Le résultat du jet est stocké dans le noeud `rollData.rolled` (comme pour
|
||||
* la première version de jets de dés)
|
||||
*
|
||||
*
|
||||
* # TODO
|
||||
* - intégration pour un jet (oeuvres / tâches / méditation / compétence)
|
||||
* - RdDRollResult V2 (affichage avec templates basés sur roll-dialog)
|
||||
* - Extraction de jet résumé (pour appel chance)
|
||||
* - gestion significative
|
||||
* - Attaque
|
||||
* - Défense
|
||||
* - intégration rdd-combat
|
||||
* - combat rencontres
|
||||
*
|
||||
*/
|
||||
/* -------------------------------------------- */
|
||||
export default class RollDialog extends HandlebarsApplicationMixin(ApplicationV2)
|
||||
{
|
||||
|
||||
static init() {
|
||||
}
|
||||
|
||||
static onReady() {
|
||||
|
||||
foundry.applications.handlebars.loadTemplates({
|
||||
'roll-section': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-section.hbs',
|
||||
'roll-mode': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-mode.hbs',
|
||||
'roll-table': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-table.hbs',
|
||||
'roll-ajustements': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-ajustements.hbs',
|
||||
'roll-chances': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-chances.hbs',
|
||||
'roll-button': 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-button.hbs',
|
||||
})
|
||||
|
||||
foundry.applications.handlebars.loadTemplates(ROLL_MODE_TABS.map(m => m.template))
|
||||
foundry.applications.handlebars.loadTemplates(ROLL_PARTS.map(p => p.template))
|
||||
ROLL_PARTS.forEach(p => p.onReady())
|
||||
|
||||
Handlebars.registerHelper('roll-centered-array', (base, show) => RollDialog.centeredArray(base, show))
|
||||
Handlebars.registerHelper('roll-list-item-value', (list, key, path = undefined) => {
|
||||
const selected = list.find(p => p.key == key)
|
||||
if (selected && path && path != '') {
|
||||
return foundry.utils.getProperty(selected, path)
|
||||
}
|
||||
return selected
|
||||
})
|
||||
Handlebars.registerHelper('roll-part-context', (rollData, code) => {
|
||||
const rollPart = ROLL_PARTS.find(it => it.code == code)
|
||||
if (rollPart == undefined) {
|
||||
return {}
|
||||
}
|
||||
return {
|
||||
code: code,
|
||||
name: rollPart.name,
|
||||
template: rollPart.template,
|
||||
rollData: rollData,
|
||||
refs: rollPart.getRefs(rollData),
|
||||
current: rollPart.getCurrent(rollData)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
static centeredArray(base, show) {
|
||||
show = Math.abs(show)
|
||||
const start = base - show
|
||||
return [...Array(2 * show + 1).keys()].map(it => start + it)
|
||||
}
|
||||
|
||||
static async create(rollData, rollOptions = {}) {
|
||||
const rollDialog = new RollDialog(rollData, rollOptions)
|
||||
rollDialog.render(true)
|
||||
}
|
||||
|
||||
static get PARTS() {
|
||||
return { form: { template: 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-dialog.hbs', } }
|
||||
}
|
||||
|
||||
static get DEFAULT_OPTIONS() {
|
||||
const default_options = {
|
||||
tag: "form",
|
||||
form: {
|
||||
handler: RollDialog.handler,
|
||||
submitOnChange: false,
|
||||
closeOnSubmit: false
|
||||
},
|
||||
position: {
|
||||
width: 600,
|
||||
height: "auto",
|
||||
},
|
||||
}
|
||||
return default_options
|
||||
}
|
||||
|
||||
static async handler(event, form, formData) {
|
||||
// rien pour l'instant
|
||||
}
|
||||
|
||||
constructor(rollData, rollOptions) {
|
||||
super()
|
||||
this.rollData = rollData
|
||||
// const callbacks = this.rollOptions.callbacks.map(c =>
|
||||
// r => r.activve.actor Promise.all(this.rollOptions.callbacks.map(async callback => await callback(rollData.active.actor, rollData)))
|
||||
// )
|
||||
this.rollOptions = {
|
||||
callbacks: [
|
||||
async (actor, r) => await actor.appliquerAjoutExperience(r),
|
||||
async (actor, r) => await actor.appliquerAppelMoral(r),
|
||||
...(rollOptions.callbacks ?? [])
|
||||
],
|
||||
customChatMessage: rollOptions.customChatMessage,
|
||||
onRoll: rollOptions.onRoll ?? doNothing
|
||||
}
|
||||
this.$loadParts()
|
||||
}
|
||||
|
||||
/** pre-configure les paramètres des différentes parties de la fenêtre (par exemple, prépare les listes de caractéristiques/compétences */
|
||||
$loadParts() {
|
||||
const rollData = this.rollData;
|
||||
const loadedMode = rollData.mode?.current
|
||||
rollData.current = rollData.current ?? {}
|
||||
rollData.selected = rollData.selected ?? {}
|
||||
rollData.mode = rollData.mode ?? {}
|
||||
rollData.mode.retry = rollData.mode.retry ?? false
|
||||
BASIC_PARTS.restore(rollData)
|
||||
|
||||
rollData.mode.allowed = rollData.mode.retry ? [loadedMode] : rollData.mode.allowed ?? ROLL_MODE_TABS.map(m => m.code)
|
||||
rollData.mode.current = loadedMode ?? ROLL_MODE_TABS.find(m => m.isAllowed(rollData) && m.visible(rollData))?.code ?? ROLL_MODE_COMP
|
||||
this.getSelectedMode().setRollDataMode(rollData)
|
||||
|
||||
rollData.refs = this.$prepareRefs(rollData)
|
||||
rollData.options = rollData.options ?? { showDice: true, rollMode: game.settings.get("core", "rollMode") }
|
||||
|
||||
ROLL_PARTS.forEach(p => p.initialize(rollData))
|
||||
ROLL_PARTS.forEach(p => p.restore(rollData))
|
||||
ROLL_PARTS.filter(p => p.isValid(rollData))
|
||||
.forEach(p => {
|
||||
p.loadRefs(rollData)
|
||||
p.prepareContext(rollData)
|
||||
})
|
||||
this.selectMode();
|
||||
}
|
||||
|
||||
selectMode() {
|
||||
this.rollData.mode.label = this.getSelectedMode().title(this.rollData)
|
||||
this.getSelectedMode().setRollDataMode(this.rollData)
|
||||
this.getSelectedMode().onSelect(this.rollData);
|
||||
}
|
||||
|
||||
$prepareRefs(rollData) {
|
||||
return foundry.utils.mergeObject(rollData.refs ?? {}, Object.fromEntries(ROLL_PARTS.map(p => [p.code, {}])));
|
||||
}
|
||||
|
||||
$saveParts() {
|
||||
const target = BASIC_PARTS.initFrom(this.rollData)
|
||||
ROLL_PARTS.filter(p => p.isActive(this.rollData))
|
||||
.forEach(p => p.store(this.rollData, target))
|
||||
return target
|
||||
}
|
||||
|
||||
getActiveParts() {
|
||||
return ROLL_PARTS.filter(p => p.isActive(this.rollData))
|
||||
}
|
||||
|
||||
get title() {
|
||||
return this.rollData.title ?? `Jet de dés de ${this.rollData.active.actor.name}`
|
||||
}
|
||||
|
||||
async _onRender(context, options) {
|
||||
this.window.title.innerText = this.rollTitle(this.rollData)
|
||||
const buttonRoll = this.element.querySelector(`button[name="roll-dialog-button"]`)
|
||||
buttonRoll?.addEventListener(
|
||||
"click", e => {
|
||||
e.preventDefault()
|
||||
this.roll()
|
||||
}
|
||||
)
|
||||
const buttonsMode = this.element.querySelectorAll(`button[name="roll-mode"]`)
|
||||
buttonsMode?.forEach(it => it.addEventListener(
|
||||
"click", e => {
|
||||
e.preventDefault()
|
||||
this.rollData.mode.current = e.currentTarget.dataset.mode
|
||||
this.selectMode()
|
||||
this.render()
|
||||
}
|
||||
))
|
||||
|
||||
Promise.all(
|
||||
this.getActiveParts().map(async p => await p._onRender(this, context, options))
|
||||
)
|
||||
}
|
||||
|
||||
getAjustements() {
|
||||
return this.getActiveParts()
|
||||
.map(p => p.getAjustements(this.rollData))
|
||||
.reduce((a, b) => a.concat(b))
|
||||
.sort((a, b) => a.diff == undefined ? 1 : b.diff == undefined ? -1 : 0)
|
||||
}
|
||||
|
||||
async buildHTMLTable(carac, diff) {
|
||||
return await foundry.applications.handlebars.renderTemplate('roll-table', { carac, diff })
|
||||
}
|
||||
|
||||
|
||||
async _prepareContext() {
|
||||
const rollData = this.rollData
|
||||
|
||||
const modes = ROLL_MODE_TABS.filter(m => m.isAllowed(rollData) && m.visible(rollData))
|
||||
.map(m => m.toModeData(rollData))
|
||||
this.setModeTitle()
|
||||
|
||||
const visibleRollParts = this.getActiveParts()
|
||||
visibleRollParts.forEach(p => p.setExternalFilter(visibleRollParts, rollData))
|
||||
|
||||
this.setSpecialComp(visibleRollParts);
|
||||
|
||||
visibleRollParts.forEach(p => p.prepareContext(rollData))
|
||||
|
||||
this.calculAjustements()
|
||||
|
||||
const templates = this.getActiveParts().map(p => p.toTemplateData())
|
||||
const context = await super._prepareContext()
|
||||
return foundry.utils.mergeObject(
|
||||
{
|
||||
modes: modes,
|
||||
templates: templates,
|
||||
rollData: rollData,
|
||||
}, context)
|
||||
}
|
||||
|
||||
setSpecialComp(visibleRollParts) {
|
||||
const specialComp = visibleRollParts.map(p => p.getSpecialComp(this.rollData))
|
||||
.reduce((a, b) => a.concat(b))
|
||||
if (specialComp.length > 0) {
|
||||
const rollPartComp = this.getActiveParts()
|
||||
.find(it => it.code == PART_COMP);
|
||||
rollPartComp?.setSpecialComp(this.rollData, specialComp)
|
||||
}
|
||||
}
|
||||
|
||||
calculAjustements() {
|
||||
this.rollData.ajustements = this.getAjustements()
|
||||
this.rollData.ajustements.forEach(it => it.isDiff = it.diff != undefined)
|
||||
this.rollData.current.totaldiff = this.rollData.ajustements
|
||||
.map(adj => adj.diff)
|
||||
.filter(d => d != undefined)
|
||||
.reduce(Misc.sum(), 0)
|
||||
}
|
||||
|
||||
setModeTitle() {
|
||||
this.rollData.mode.label = this.getSelectedMode()?.title(this.rollData)
|
||||
}
|
||||
|
||||
getSelectedMode() {
|
||||
return ROLL_MODE_TABS.find(m => m.code == this.rollData.mode.current)
|
||||
}
|
||||
|
||||
async roll() {
|
||||
this.calculAjustements()
|
||||
const rollData = this.rollData
|
||||
console.info('Roll parts:', this.$saveParts())
|
||||
const rolled = await this.$rollDice(rollData)
|
||||
rollData.rolled = rolled
|
||||
Promise.all(this.rollOptions.callbacks.map(async callback => await callback(rollData.active.actor, rollData)))
|
||||
if (!this.rollOptions.customChatMessage) {
|
||||
rollData.active.actor.$onRollCompetence(this.rollData)
|
||||
}
|
||||
this.rollOptions.onRoll(this)
|
||||
}
|
||||
|
||||
|
||||
async defaultCallback(rollData, rolled) {
|
||||
await rollData.active.actor.appliquerAjoutExperience(rollData)
|
||||
await rollData.active.actor.appliquerAppelMoral(rollData)
|
||||
}
|
||||
|
||||
async $rollDice(rollData) {
|
||||
const adapter = new RollDialogAdapter(ROLL_PARTS);
|
||||
return await adapter.rollDice(rollData, this.rollTitle(rollData));
|
||||
}
|
||||
|
||||
rollTitle(rollData) {
|
||||
return ROLL_PARTS
|
||||
.filter(it => it.section == ROLLDIALOG_SECTION.ACTION)
|
||||
.filter(it => it.isActive(rollData))
|
||||
.map(it => it.title(rollData))
|
||||
.reduce(Misc.joining(' '))
|
||||
}
|
||||
}
|
13
module/roll/roll-mode-attaque.mjs
Normal file
@@ -0,0 +1,13 @@
|
||||
import { DIFF_MODE, ROLL_MODE_ATTAQUE } from "./roll-constants.mjs"
|
||||
import { RollMode } from "./roll-mode.mjs"
|
||||
|
||||
export class RollModeAttaque extends RollMode {
|
||||
get code() { return ROLL_MODE_ATTAQUE }
|
||||
get name() { return `Attaquer` }
|
||||
|
||||
title(rollData) { return `attaque` }
|
||||
|
||||
onSelect(rollData) {
|
||||
this.setDiffMode(rollData, DIFF_MODE.ATTAQUE)
|
||||
}
|
||||
}
|
9
module/roll/roll-mode-comp.mjs
Normal file
@@ -0,0 +1,9 @@
|
||||
import { ROLL_MODE_COMP } from "./roll-constants.mjs"
|
||||
import { RollMode } from "./roll-mode.mjs"
|
||||
|
||||
export class RollModeComp extends RollMode {
|
||||
get code() { return ROLL_MODE_COMP }
|
||||
get name() { return `Jet de caractéristique / compétence` }
|
||||
|
||||
title(rollData) { return `fait un jet ${rollData.mode.opposed ? ' contre ' : ''}` }
|
||||
}
|
17
module/roll/roll-mode-defense.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
import { DIFF_MODE, ROLL_MODE_DEFENSE } from "./roll-constants.mjs"
|
||||
import { RollMode } from "./roll-mode.mjs"
|
||||
|
||||
export class RollModeDefense extends RollMode {
|
||||
get code() { return ROLL_MODE_DEFENSE }
|
||||
get name() { return `Se défendre` }
|
||||
|
||||
title(rollData) { return `se défend${rollData.attacker ? ' de' : ''}` }
|
||||
|
||||
getOpponent(rollData) {
|
||||
return rollData.attacker
|
||||
}
|
||||
|
||||
onSelect(rollData) {
|
||||
this.setDiffMode(rollData, DIFF_MODE.DEFENSE)
|
||||
}
|
||||
}
|
17
module/roll/roll-mode-jeu.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
import { PART_JEU } from "./roll-part-jeu.mjs"
|
||||
import { RollMode } from "./roll-mode.mjs"
|
||||
import { ROLL_MODE_JEU } from "./roll-constants.mjs"
|
||||
|
||||
export class RollModeJeu extends RollMode {
|
||||
get code() { return ROLL_MODE_JEU }
|
||||
get name() { return `Jouer` }
|
||||
|
||||
visible(rollData) { return rollData.active.actor.isPersonnage() }
|
||||
title(rollData) {
|
||||
if (rollData.opponent) {
|
||||
return `joue contre`
|
||||
}
|
||||
return `joue: ${rollData.current[PART_JEU].label}`
|
||||
}
|
||||
|
||||
}
|
19
module/roll/roll-mode-meditation.mjs
Normal file
@@ -0,0 +1,19 @@
|
||||
import { DIFF_MODE, ROLL_MODE_MEDITATION } from "./roll-constants.mjs"
|
||||
import { PART_MEDITATION } from "./roll-part-meditation.mjs"
|
||||
import { RollMode } from "./roll-mode.mjs"
|
||||
|
||||
export class RollModeMeditation extends RollMode {
|
||||
get code() { return ROLL_MODE_MEDITATION }
|
||||
get name() { return `Méditation draconique` }
|
||||
|
||||
visible(rollData) { return rollData.active.actor.isHautRevant() }
|
||||
title(rollData) {
|
||||
const current = rollData.current[PART_MEDITATION]
|
||||
const theme = current?.meditation.system.theme
|
||||
return theme ? 'médite sur ' + theme : 'médite'
|
||||
}
|
||||
|
||||
onSelect(rollData) {
|
||||
this.setDiffMode(rollData, DIFF_MODE.AUCUN)
|
||||
}
|
||||
}
|
19
module/roll/roll-mode-oeuvre.mjs
Normal file
@@ -0,0 +1,19 @@
|
||||
import { DIFF_MODE, ROLL_MODE_OEUVRE } from "./roll-constants.mjs"
|
||||
import { PART_OEUVRE } from "./roll-part-oeuvre.mjs"
|
||||
import { RollMode } from "./roll-mode.mjs"
|
||||
|
||||
export class RollModeOeuvre extends RollMode {
|
||||
get code() { return ROLL_MODE_OEUVRE }
|
||||
get name() { return `Interpréter une oeuvre` }
|
||||
|
||||
visible(rollData) { return rollData.active.actor.isPersonnage() }
|
||||
title(rollData) {
|
||||
const current = rollData.current[PART_OEUVRE]
|
||||
return `${current.art.action} ${current.label}`
|
||||
}
|
||||
|
||||
onSelect(rollData) {
|
||||
this.setDiffMode(rollData, DIFF_MODE.AUCUN)
|
||||
}
|
||||
}
|
||||
|
15
module/roll/roll-mode-sort.mjs
Normal file
@@ -0,0 +1,15 @@
|
||||
import { DIFF_MODE, ROLL_MODE_SORT } from "./roll-constants.mjs"
|
||||
import { RollMode } from "./roll-mode.mjs"
|
||||
import { PART_SORT } from "./roll-part-sort.mjs"
|
||||
|
||||
export class RollModeSort extends RollMode {
|
||||
get code() { return ROLL_MODE_SORT }
|
||||
get name() { return `lancer un sort` }
|
||||
|
||||
visible(rollData) { return rollData.active.actor.isHautRevant() }
|
||||
title(rollData) { return `lance le sort:` }
|
||||
|
||||
onSelect(rollData) {
|
||||
this.setDiffMode(rollData, DIFF_MODE.AUCUN)
|
||||
}
|
||||
}
|
19
module/roll/roll-mode-tache.mjs
Normal file
@@ -0,0 +1,19 @@
|
||||
import { DIFF_MODE, ROLL_MODE_TACHE } from "./roll-constants.mjs"
|
||||
import { PART_TACHE } from "./roll-part-tache.mjs"
|
||||
import { RollMode } from "./roll-mode.mjs"
|
||||
|
||||
export class RollModeTache extends RollMode {
|
||||
get code() { return ROLL_MODE_TACHE }
|
||||
get name() { return `Travailler à une tâche` }
|
||||
|
||||
visible(rollData) { return rollData.active.actor.isPersonnage() }
|
||||
title(rollData) {
|
||||
const current = rollData.current[PART_TACHE]
|
||||
const tache = current?.tache
|
||||
return `travaille à sa tâche: ${tache.name ?? ''}`
|
||||
}
|
||||
|
||||
onSelect(rollData) {
|
||||
this.setDiffMode(rollData, DIFF_MODE.AUCUN)
|
||||
}
|
||||
}
|
54
module/roll/roll-mode.mjs
Normal file
@@ -0,0 +1,54 @@
|
||||
import { DIFF_MODE } from "./roll-constants.mjs"
|
||||
import { PART_DIFF } from "./roll-part-diff.mjs"
|
||||
|
||||
const DEFAULT_DIFF_MODES = [DIFF_MODE.LIBRE, DIFF_MODE.IMPOSEE, DIFF_MODE.DEFAUT]
|
||||
|
||||
export class RollMode {
|
||||
|
||||
onReady() { }
|
||||
|
||||
get code() { throw new Error(`Pas de code défini pour ${this}`) }
|
||||
get name() { return this.code }
|
||||
get icon() { return `systems/foundryvtt-reve-de-dragon/assets/actions/${this.code}.svg` }
|
||||
|
||||
toModeData(rollData) {
|
||||
return { code: this.code, name: this.name, icon: this.icon, section: 'mode', template: this.template, selected: this.isSelected(rollData) }
|
||||
}
|
||||
|
||||
isAllowed(rollData) { return rollData.mode.allowed == undefined || rollData.mode.allowed.includes(this.code) }
|
||||
visible(rollData) { return true }
|
||||
|
||||
title(rollData) { return this.code }
|
||||
isSelected(rollData) { return rollData.mode.current == this.code }
|
||||
|
||||
setRollDataMode(rollData) {
|
||||
rollData.mode.opposed = rollData.opponent != undefined
|
||||
rollData.mode.resistance = false /** TODO */
|
||||
}
|
||||
|
||||
onSelect(rollData) {
|
||||
const mode = [
|
||||
rollData.current[PART_DIFF].mode,
|
||||
this.modeFromOpponents(rollData),
|
||||
rollData.selected[PART_DIFF].mode].find(m => DEFAULT_DIFF_MODES.includes(m))
|
||||
|
||||
this.setDiffMode(rollData, mode ??
|
||||
DIFF_MODE.DEFAUT)
|
||||
}
|
||||
|
||||
|
||||
modeFromOpponents(rollData) {
|
||||
if (rollData.mode.opposed) {
|
||||
if (rollData.mode.resistance) {
|
||||
return DIFF_MODE.IMPOSEE
|
||||
}
|
||||
return DIFF_MODE.LIBRE
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
setDiffMode(rollData, mode) {
|
||||
rollData.current[PART_DIFF].mode = mode
|
||||
this.setRollDataMode(rollData)
|
||||
}
|
||||
}
|
19
module/roll/roll-part-action.mjs
Normal file
@@ -0,0 +1,19 @@
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
export const PART_ACTION = "action"
|
||||
|
||||
export class RollPartAction extends RollPart {
|
||||
|
||||
get code() { return PART_ACTION }
|
||||
get section() { return ROLLDIALOG_SECTION.ACTION }
|
||||
|
||||
title(rollData) {
|
||||
return rollData.mode.label
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
current.verb = rollData.mode.label
|
||||
}
|
||||
|
||||
}
|
11
module/roll/roll-part-actor.mjs
Normal file
@@ -0,0 +1,11 @@
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
export const PART_ACTOR = "actor"
|
||||
|
||||
export class RollPartActor extends RollPart {
|
||||
|
||||
get code() { return PART_ACTOR }
|
||||
get section() { return ROLLDIALOG_SECTION.ACTION }
|
||||
|
||||
title(rollData) { return rollData.active.name }
|
||||
}
|
42
module/roll/roll-part-appelmoral.mjs
Normal file
@@ -0,0 +1,42 @@
|
||||
import { RdDCarac } from "../rdd-carac.js"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
|
||||
export const PART_APPELMORAL = "appelmoral"
|
||||
|
||||
export class RollPartAppelMoral extends RollPartCheckbox {
|
||||
|
||||
get code() { return PART_APPELMORAL }
|
||||
get useCheckboxTemplate() { return false }
|
||||
get isDefaultChecked() { return false }
|
||||
|
||||
visible(rollData) {
|
||||
return rollData.active.actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.current.carac.key)
|
||||
}
|
||||
|
||||
restore(rollData) {
|
||||
this.getCurrent(rollData).checked = this.getSaved(rollData).checked ?? false
|
||||
}
|
||||
|
||||
store(rollData, targetData) {
|
||||
this.setSaved(targetData, { checked: this.getCurrent(rollData).checked })
|
||||
}
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.moral = rollData.active.actor.getMoralTotal()
|
||||
refs.label = refs.moral > 0 ? "Appel au moral" : "Énergie du désespoir"
|
||||
}
|
||||
|
||||
getCheckboxIcon(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
if (refs.moral > 0) {
|
||||
return '<i class="fa-regular fa-face-smile-beam"></i>'
|
||||
}
|
||||
if (refs.moral < 0) {
|
||||
return '<i class="fa-regular fa-face-sad-tear"></i>'
|
||||
}
|
||||
return '<i class="fa-regular fa-face-meh"></i>'
|
||||
}
|
||||
getCheckboxLabel(rollData) { return "Appel au moral" }
|
||||
getCheckboxValue(rollData) { return 1 }
|
||||
}
|
33
module/roll/roll-part-astrologique.mjs
Normal file
@@ -0,0 +1,33 @@
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { ReglesOptionnelles } from "../settings/regles-optionnelles.js"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
|
||||
export const PART_ASTROLOGIQUE = "astrologique"
|
||||
|
||||
export class RollPartAstrologique extends RollPartCheckbox {
|
||||
|
||||
get code() { return PART_ASTROLOGIQUE }
|
||||
get useCheckboxTemplate() { return false }
|
||||
|
||||
visible(rollData) {
|
||||
return this.$isUsingAstrologie() && (
|
||||
this.isJetChance(rollData)
|
||||
|| this.isLancementRituel(rollData)
|
||||
)
|
||||
}
|
||||
|
||||
isLancementRituel(rollData) {
|
||||
return false
|
||||
}
|
||||
|
||||
isJetChance(rollData) {
|
||||
return Grammar.includesLowerCaseNoAccent(rollData.current.carac.key, 'chance')
|
||||
}
|
||||
|
||||
$isUsingAstrologie() {
|
||||
return ReglesOptionnelles.isUsing("astrologie")
|
||||
}
|
||||
|
||||
getCheckboxLabel(rollData) { return "Astrologique" }
|
||||
getCheckboxValue(rollData) { return rollData.active.actor.ajustementAstrologique() }
|
||||
}
|
66
module/roll/roll-part-attaque.mjs
Normal file
@@ -0,0 +1,66 @@
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { ROLL_MODE_ATTAQUE } from "./roll-constants.mjs"
|
||||
import { PART_CARAC } from "./roll-part-carac.mjs"
|
||||
import { PART_COMP } from "./roll-part-comp.mjs"
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
export const PART_ATTAQUE = 'attaque'
|
||||
|
||||
export class RollPartAttaque extends RollPartSelect {
|
||||
|
||||
get code() { return PART_ATTAQUE }
|
||||
get section() { return ROLLDIALOG_SECTION.CHOIX }
|
||||
|
||||
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_ATTAQUE) }
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
const attaques = rollData.active.actor.listAttaques()
|
||||
refs.attaques = attaques.map(it => RollPartAttaque.$extractAttaque(it, rollData.active.actor))
|
||||
if (refs.attaques.length>0){
|
||||
this.$selectAttaque(rollData)
|
||||
}
|
||||
}
|
||||
|
||||
choices(refs) { return refs.attaques }
|
||||
|
||||
static $extractAttaque(action, actor) {
|
||||
return {
|
||||
key: `${action.action}::${action.arme.id}::${action.comp.id}`,
|
||||
label: action.name,
|
||||
action: action,
|
||||
arme: action.arme,
|
||||
comp: action.comp,
|
||||
}
|
||||
}
|
||||
|
||||
$selectAttaque(rollData, key) {
|
||||
this.selectByKey(rollData, key, 0)
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const selectAttaque = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-attaque"]`)
|
||||
|
||||
selectAttaque.addEventListener("change", e => {
|
||||
const selectOptions = e.currentTarget.options
|
||||
const index = selectOptions.selectedIndex
|
||||
this.$selectAttaque(rollDialog.rollData, selectOptions[index]?.value)
|
||||
rollDialog.setModeTitle()
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
getExternalPartsFilter(partCode, rollData) {
|
||||
if (this.visible(rollData)) {
|
||||
const current = this.getCurrent(rollData)
|
||||
switch (partCode) {
|
||||
case PART_CARAC: return p => Grammar.equalsInsensitive(current.action.carac.key, p.key)
|
||||
case PART_COMP: return p => p.label == current.comp?.name
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
|
||||
}
|
66
module/roll/roll-part-carac.mjs
Normal file
@@ -0,0 +1,66 @@
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
|
||||
|
||||
export const PART_CARAC = "carac"
|
||||
|
||||
export class RollPartCarac extends RollPartSelect {
|
||||
/** TODO: remplacer selectOption par une sorte de sélecteur plus sympa? */
|
||||
|
||||
get code() { return PART_CARAC }
|
||||
get name() { return 'Caractéristiques' }
|
||||
get section() { return ROLLDIALOG_SECTION.CARAC }
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.all = this.$getActorCaracs(rollData)
|
||||
refs.caracs = refs.all
|
||||
this.$selectCarac(rollData)
|
||||
}
|
||||
|
||||
choices(refs) { return refs.caracs }
|
||||
|
||||
$getActorCaracs(rollData) {
|
||||
return Object.entries(rollData.active.actor.getCarac())
|
||||
.filter(([key, c]) => key != 'taille')
|
||||
/* TODO: filter by context */
|
||||
.map(([key, carac]) => {
|
||||
return RollPartCarac.$extractCarac(key, carac)
|
||||
})
|
||||
}
|
||||
|
||||
static $extractCarac(key, carac) {
|
||||
return {
|
||||
key: key,
|
||||
label: carac.label,
|
||||
value: parseInt(carac.value)
|
||||
}
|
||||
}
|
||||
|
||||
setFilter(rollData, filter) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.caracs = refs.all.filter(filter)
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
this.$selectCarac(rollData)
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
return []
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const select = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select`)
|
||||
|
||||
select?.addEventListener("change", async e => {
|
||||
const selectOptions = e.currentTarget.options
|
||||
const index = selectOptions.selectedIndex
|
||||
this.$selectCarac(rollDialog.rollData, selectOptions[index]?.value)
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
$selectCarac(rollData, key) {
|
||||
this.selectByKey(rollData, key, 10)
|
||||
}
|
||||
}
|
61
module/roll/roll-part-checkbox.mjs
Normal file
@@ -0,0 +1,61 @@
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
export class RollPartCheckbox extends RollPart {
|
||||
|
||||
get section() { return ROLLDIALOG_SECTION.CONDITIONS }
|
||||
|
||||
get useCheckboxTemplate() { return true }
|
||||
get template() { return this.useCheckboxTemplate ? 'systems/foundryvtt-reve-de-dragon/templates/roll/roll-part-checkbox.hbs' : super.template }
|
||||
get isDefaultChecked() { return true }
|
||||
|
||||
restore(rollData) {
|
||||
const checked = this.getSaved(rollData).checked
|
||||
this.getCurrent(rollData).checked = checked == undefined? this.isDefaultChecked : checked
|
||||
}
|
||||
|
||||
store(rollData, targetData) {
|
||||
this.setSaved(targetData, { checked: this.getCurrent(rollData).checked })
|
||||
}
|
||||
|
||||
loadRefs(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
current.label = this.getCheckboxLabel(rollData)
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (current.checked == undefined) {
|
||||
/* TODO: user setting? */
|
||||
current.checked = true
|
||||
}
|
||||
if (current.value == undefined) {
|
||||
current.value = this.getCheckboxValue(rollData)
|
||||
}
|
||||
current.icon = this.getCheckboxIcon(rollData)
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (current.checked) {
|
||||
return [{ label: this.getCheckboxLabelAjustement(rollData), diff: current.value }]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
getCheckboxLabelAjustement(rollData) {
|
||||
return `${this.getCheckboxIcon(rollData)} ${this.getCurrent(rollData).label}`
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const checkbox = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`)
|
||||
|
||||
checkbox?.addEventListener("change", e => {
|
||||
this.getCurrent(rollDialog.rollData).checked = e.currentTarget.checked
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
getCheckboxIcon(rollData) { return '' }
|
||||
getCheckboxLabel(rollData) { return "LABEL" }
|
||||
getCheckboxValue(rollData) { return 0 }
|
||||
}
|
66
module/roll/roll-part-coeur.mjs
Normal file
@@ -0,0 +1,66 @@
|
||||
import { RdDCarac } from "../rdd-carac.js"
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
const COEUR = "coeur"
|
||||
|
||||
const SANS_AMOUR = { key: '', label: "", value: 0 }
|
||||
|
||||
export class RollPartCoeur extends RollPartSelect {
|
||||
|
||||
get code() { return COEUR }
|
||||
get section() { return ROLLDIALOG_SECTION.CONDITIONS }
|
||||
|
||||
get useCheckboxTemplate() { return false }
|
||||
|
||||
isValid(rollData) { return rollData.active.actor.isPersonnage() }
|
||||
visible(rollData) {
|
||||
return this.getRefs(rollData).amoureux.length > 1 && RdDCarac.isVolonte(rollData.current.carac.key)
|
||||
}
|
||||
|
||||
loadRefs(rollData) {
|
||||
const liste = rollData.active.actor.listeAmoureux()
|
||||
.filter(amour => amour.coeur > 0)
|
||||
.map(RollPartCoeur.$extractAmoureux)
|
||||
|
||||
this.getRefs(rollData).amoureux = [SANS_AMOUR, ...liste]
|
||||
this.$selectAmoureux(rollData)
|
||||
}
|
||||
|
||||
choices(refs) { return refs.amoureux }
|
||||
|
||||
static $extractAmoureux(amour) {
|
||||
return {
|
||||
key: amour.id,
|
||||
label: amour.name,
|
||||
value: -2 * (amour?.coeur ?? 0),
|
||||
amour: amour
|
||||
}
|
||||
}
|
||||
|
||||
$selectAmoureux(rollData, key) {
|
||||
this.selectByKey(rollData, key, 0)
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (current.key != '') {
|
||||
return [{
|
||||
label: "Coeur pour " + current.label,
|
||||
diff: current.value
|
||||
}]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const selectAmour = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="${this.code}"]`)
|
||||
|
||||
selectAmour?.addEventListener("change", e => {
|
||||
const selectOptions = e.currentTarget.options
|
||||
const index = selectOptions.selectedIndex
|
||||
this.$selectAmoureux(rollDialog.rollData, selectOptions[index]?.value)
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
}
|
77
module/roll/roll-part-comp.mjs
Normal file
@@ -0,0 +1,77 @@
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { Misc } from "../misc.js"
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
|
||||
|
||||
export const PART_COMP = "comp"
|
||||
|
||||
const SANS_COMPETENCE = { key: '', label: "Sans compétence", value: 0 }
|
||||
|
||||
export class RollPartComp extends RollPartSelect {
|
||||
|
||||
/** TODO: remplacer selectOption par un sélecteur plus sympa (avec image de compétence, par exemple? */
|
||||
|
||||
get code() { return PART_COMP }
|
||||
get name() { return 'Compétences' }
|
||||
get section() { return ROLLDIALOG_SECTION.COMP }
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.all = this.$getActorComps(rollData)
|
||||
refs.comps = refs.all
|
||||
this.$selectComp(rollData)
|
||||
}
|
||||
|
||||
choices(refs) { return refs.comps }
|
||||
|
||||
$getActorComps(rollData) {
|
||||
const competences = (rollData.active.actor?.getCompetences() ?? [])
|
||||
.map(RollPartComp.$extractComp)
|
||||
.sort(Misc.ascending(it => Grammar.toLowerCaseNoAccentNoSpace(it.label)))
|
||||
/* TODO: filter competences */
|
||||
const listCompetences = [
|
||||
SANS_COMPETENCE,
|
||||
...competences
|
||||
]
|
||||
return listCompetences
|
||||
}
|
||||
|
||||
static $extractComp(comp) {
|
||||
return {
|
||||
key: comp.name,
|
||||
label: comp.name,
|
||||
value: comp.system.niveau,
|
||||
comp: comp
|
||||
}
|
||||
}
|
||||
|
||||
setFilter(rollData, filter) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.comps = refs.all.filter(filter)
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
this.$selectComp(rollData)
|
||||
}
|
||||
|
||||
setSpecialComp(rollData, comps) {
|
||||
this.getRefs(rollData).comps = comps.map(RollPartComp.$extractComp)
|
||||
.sort(Misc.ascending(it => Grammar.toLowerCaseNoAccentNoSpace(it.label)))
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const select = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select`)
|
||||
|
||||
select?.addEventListener("change", e => {
|
||||
const selectOptions = e.currentTarget.options
|
||||
const index = selectOptions.selectedIndex
|
||||
this.$selectComp(rollDialog.rollData, selectOptions[index]?.value)
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
$selectComp(rollData, key) {
|
||||
this.selectByKey(rollData, key, 0)
|
||||
}
|
||||
|
||||
}
|
74
module/roll/roll-part-conditions.mjs
Normal file
@@ -0,0 +1,74 @@
|
||||
import { SYSTEM_RDD } from "../constants.js";
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs";
|
||||
|
||||
const CONDITIONS = "conditions"
|
||||
const DESCR_CONDITIONS = "Conditions"
|
||||
|
||||
export class RollPartConditions extends RollPart {
|
||||
/** TODO: use alternate to numberInput that supports displaying '+' sign */
|
||||
settingMin() { return RollPart.settingKey(this, 'min') }
|
||||
settingMax() { return RollPart.settingKey(this, 'max') }
|
||||
|
||||
onReady() {
|
||||
game.settings.register(SYSTEM_RDD, this.settingMin(),
|
||||
{
|
||||
name: "Malus maximal de conditions",
|
||||
type: Number,
|
||||
config: true,
|
||||
scope: "world",
|
||||
range: { min: -20, max: -10, step: 1 },
|
||||
default: -16
|
||||
}
|
||||
)
|
||||
game.settings.register(SYSTEM_RDD, this.settingMax(),
|
||||
{
|
||||
name: "Bonus maximal de conditions",
|
||||
type: Number,
|
||||
config: true,
|
||||
scope: "world",
|
||||
range: { min: 5, max: 15, step: 1 },
|
||||
default: 10
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
restore(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
current.value = this.getSaved(rollData)?.value ?? current.value ?? 0
|
||||
}
|
||||
|
||||
|
||||
store(rollData, targetData) {
|
||||
this.setSaved(targetData, { value: this.getCurrent(rollData).value })
|
||||
}
|
||||
|
||||
/** @override */
|
||||
get code() { return CONDITIONS }
|
||||
get section() { return ROLLDIALOG_SECTION.CONDITIONS }
|
||||
|
||||
prepareContext(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
current.min = game.settings.get(SYSTEM_RDD, this.settingMin())
|
||||
current.max = game.settings.get(SYSTEM_RDD, this.settingMax())
|
||||
current.value = current.value ?? 0
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (current.value != 0) {
|
||||
return [{ label: DESCR_CONDITIONS, diff: current.value }]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const input = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`)
|
||||
|
||||
input?.addEventListener("change", e => {
|
||||
const current = this.getCurrent(rollDialog.rollData)
|
||||
current.value = parseInt(e.currentTarget.value)
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
17
module/roll/roll-part-defense.mjs
Normal file
@@ -0,0 +1,17 @@
|
||||
import { ROLL_MODE_DEFENSE } from "./roll-constants.mjs"
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
export const PART_DEFENSE = 'defense'
|
||||
|
||||
export class RollPartDefense extends RollPart {
|
||||
|
||||
get code() { return PART_DEFENSE }
|
||||
get section() { return ROLLDIALOG_SECTION.CHOIX }
|
||||
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_DEFENSE) }
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.defenses =[]
|
||||
}
|
||||
|
||||
}
|
70
module/roll/roll-part-diff.mjs
Normal file
@@ -0,0 +1,70 @@
|
||||
import { DIFF_MODE, DIFF_MODES, ROLL_MODE_MEDITATION, ROLL_MODE_OEUVRE, ROLL_MODE_SORT, ROLL_MODE_TACHE } from "./roll-constants.mjs";
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs";
|
||||
|
||||
export const PART_DIFF = "diff"
|
||||
|
||||
const EXCLUDED_ROLL_MODES = [ROLL_MODE_TACHE, ROLL_MODE_MEDITATION, ROLL_MODE_SORT, ROLL_MODE_OEUVRE]
|
||||
|
||||
export class RollPartDiff extends RollPart {
|
||||
|
||||
get code() { return PART_DIFF }
|
||||
get section() { return ROLLDIALOG_SECTION.CHOIX }
|
||||
|
||||
restore(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
const saved = this.getSaved(rollData)
|
||||
current.value = saved?.value ?? current.value ?? 0
|
||||
current.mode = saved?.mode ?? current.mode
|
||||
}
|
||||
|
||||
store(rollData, targetData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
this.setSaved(targetData, {
|
||||
value: current.value,
|
||||
mode: current.mode
|
||||
})
|
||||
}
|
||||
|
||||
visible(rollData) {
|
||||
if (EXCLUDED_ROLL_MODES.includes(rollData.mode.current)) {
|
||||
return false
|
||||
}
|
||||
const current = this.getCurrent(rollData)
|
||||
/* TODO: affiner les cas où afficher ou non. devrait s'afficher pour les jets basiques (même si pas d'opposant sélectionné)*/
|
||||
return Object.values(DIFF_MODE).includes(current.mode)
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
const diffMode = DIFF_MODES[current.mode] ?? DIFF_MODES[DIFF_MODE.AUCUN]
|
||||
foundry.utils.mergeObject(current,
|
||||
{
|
||||
mode: diffMode.key,
|
||||
label: diffMode?.label ?? '',
|
||||
value: current.value ?? 0,
|
||||
disabled: !diffMode.libre,
|
||||
min: -10,
|
||||
max: diffMode.max
|
||||
},
|
||||
{ inplace: true }
|
||||
)
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
return [{
|
||||
label: current.label,
|
||||
diff: current.value
|
||||
}]
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const input = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`)
|
||||
|
||||
input?.addEventListener("change", e => {
|
||||
this.getCurrent(rollDialog.rollData).value = parseInt(e.currentTarget.value)
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
31
module/roll/roll-part-enctotal.mjs
Normal file
@@ -0,0 +1,31 @@
|
||||
import { RdDItemCompetence } from "../item-competence.js"
|
||||
import { RdDCarac } from "../rdd-carac.js"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
|
||||
const ENCTOTAL = "enctotal"
|
||||
|
||||
export class RollPartEncTotal extends RollPartCheckbox {
|
||||
|
||||
get code() { return ENCTOTAL }
|
||||
get useCheckboxTemplate() { return false }
|
||||
|
||||
visible(rollData) {
|
||||
return RdDCarac.isAgiliteOuDerobee(rollData.current.carac.key)
|
||||
&& RdDItemCompetence.isMalusEncombrementTotal(rollData.current.comp?.key)
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
super._onRender(rollDialog, context, options)
|
||||
|
||||
const inputMalusEnc = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="malusenc"]`)
|
||||
|
||||
inputMalusEnc?.addEventListener("change", e => {
|
||||
this.getCurrent(rollDialog.rollData).value = parseInt(e.currentTarget.value)
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
getCheckboxIcon(rollData) { return '<i class="fa-solid fa-weight-hanging"></i>' }
|
||||
getCheckboxLabel(rollData) { return "Enc. total" }
|
||||
getCheckboxValue(rollData) { return - rollData.active.actor.getEncTotal() }
|
||||
}
|
30
module/roll/roll-part-etat.mjs
Normal file
@@ -0,0 +1,30 @@
|
||||
import { RdDCarac } from "../rdd-carac.js"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
|
||||
const ETAT = "etat"
|
||||
|
||||
export class RollPartEtat extends RollPartCheckbox {
|
||||
|
||||
get code() { return ETAT }
|
||||
|
||||
visible(rollData) {
|
||||
const selectedCarac = rollData.current.carac?.key ?? ''
|
||||
if (selectedCarac == '') {
|
||||
return false
|
||||
}
|
||||
if (RdDCarac.isChance(selectedCarac)) {
|
||||
return false
|
||||
}
|
||||
if (RdDCarac.isReve(selectedCarac)) {
|
||||
if ((rollData.current.comp?.key ?? '') == '') {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return this.getCheckboxValue(rollData) != 0
|
||||
}
|
||||
|
||||
getCheckboxLabel(rollData) { return "État général" }
|
||||
getCheckboxValue(rollData) {
|
||||
return rollData.active.actor.getEtatGeneral({ ethylisme: true })
|
||||
}
|
||||
}
|
28
module/roll/roll-part-ethylisme.mjs
Normal file
@@ -0,0 +1,28 @@
|
||||
import { RdDCarac } from "../rdd-carac.js"
|
||||
import { RdDUtility } from "../rdd-utility.js"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
|
||||
const ETHYLISME = "ethylisme"
|
||||
|
||||
export class RollPartEthylisme extends RollPartCheckbox {
|
||||
|
||||
get code() { return ETHYLISME }
|
||||
|
||||
isValid(rollData) { return rollData.active.actor.isPersonnage()}
|
||||
|
||||
visible(rollData) {
|
||||
return rollData.active.actor.isAlcoolise() && !RdDCarac.isChance(rollData.current.carac.key)
|
||||
}
|
||||
|
||||
getCheckboxIcon(rollData) {
|
||||
return '<i class="fa-solid fa-champagne-glasses"></i>'
|
||||
}
|
||||
|
||||
getCheckboxLabel(rollData) {
|
||||
return `${RdDUtility.getNomEthylisme(rollData.active.actor.ethylisme())}`
|
||||
}
|
||||
|
||||
getCheckboxValue(rollData) {
|
||||
return rollData.active.actor.malusEthylisme()
|
||||
}
|
||||
}
|
110
module/roll/roll-part-jeu.mjs
Normal file
@@ -0,0 +1,110 @@
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { ITEM_TYPES } from "../constants.js"
|
||||
import { CARACS } from "../rdd-carac.js"
|
||||
import { ROLL_MODE_JEU } from "./roll-constants.mjs"
|
||||
import { PART_CARAC } from "./roll-part-carac.mjs"
|
||||
import { PART_COMP } from "./roll-part-comp.mjs"
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
|
||||
|
||||
export const PART_JEU = "jeu"
|
||||
|
||||
const COMPETENCE_JEU = 'Jeu'
|
||||
|
||||
export class RollPartJeu extends RollPartSelect {
|
||||
|
||||
get code() { return PART_JEU }
|
||||
get section() { return ROLLDIALOG_SECTION.CHOIX }
|
||||
|
||||
isValid(rollData) { return rollData.active.actor.isPersonnage() }
|
||||
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_JEU) }
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.jeux = rollData.active.actor.itemTypes[ITEM_TYPES.jeu]
|
||||
.map(it => RollPartJeu.$extractJeu(it, rollData.active.actor))
|
||||
if (refs.jeux.length > 0) {
|
||||
this.$selectJeu(rollData)
|
||||
}
|
||||
}
|
||||
|
||||
choices(refs) { return refs.jeux }
|
||||
|
||||
static $extractJeu(jeu, actor) {
|
||||
const comp = actor.getCompetence(COMPETENCE_JEU)
|
||||
const caracs = jeu.system.caraccomp.toLowerCase().split(/[.,:\/-]/).map(it => it.trim())
|
||||
const base = RollPartJeu.$getJeuBase(jeu, comp, caracs)
|
||||
return {
|
||||
key: jeu.id,
|
||||
label: jeu.name,
|
||||
caracs: caracs,
|
||||
jeu: jeu,
|
||||
value: (base ?? comp).system.niveau,
|
||||
base: base,
|
||||
comp: comp
|
||||
}
|
||||
}
|
||||
|
||||
static $getJeuBase(jeu, comp, caracs) {
|
||||
if (jeu.system.base < comp.system.niveau) {
|
||||
return undefined
|
||||
}
|
||||
return {
|
||||
id: comp.id,
|
||||
name: `Jeu ${jeu.name}`,
|
||||
type: comp.type,
|
||||
img: comp.img,
|
||||
system: foundry.utils.mergeObject(
|
||||
{
|
||||
niveau: jeu.system.base,
|
||||
base: jeu.system.base,
|
||||
default_carac: caracs.length > 0 ? caracs[0] : CARACS.CHANCE
|
||||
},
|
||||
comp.system,
|
||||
{ inplace: true, overwrite: false }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (rollData.mode.current == ROLL_MODE_JEU && current) {
|
||||
rollData.mode.opposed = true
|
||||
}
|
||||
}
|
||||
|
||||
getAjustements(rollData) { return [] }
|
||||
|
||||
$selectJeu(rollData, key) {
|
||||
this.selectByKey(rollData, key, 0)
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const selectjeu = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-jeu"]`)
|
||||
|
||||
selectjeu.addEventListener("change", e => {
|
||||
const selectOptions = e.currentTarget.options
|
||||
const index = selectOptions.selectedIndex
|
||||
this.$selectJeu(rollDialog.rollData, selectOptions[index]?.value)
|
||||
rollDialog.setModeTitle()
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
getExternalPartsFilter(partCode, rollData) {
|
||||
if (this.visible(rollData)) {
|
||||
const current = this.getCurrent(rollData)
|
||||
switch (partCode) {
|
||||
case PART_CARAC: return p => current.caracs?.includes(Grammar.toLowerCaseNoAccent(p.key))
|
||||
case PART_COMP: return p => p.label == current.comp?.name
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
getSpecialComp(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
return current.base ? [current.base] : []
|
||||
}
|
||||
|
||||
}
|
16
module/roll/roll-part-malusarmure.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import { RdDCarac } from "../rdd-carac.js"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
|
||||
const MALUSARMURE = "malusarmure"
|
||||
|
||||
export class RollPartMalusArmure extends RollPartCheckbox {
|
||||
|
||||
get code() { return MALUSARMURE }
|
||||
|
||||
visible(rollData) {
|
||||
return RdDCarac.isAgiliteOuDerobee(rollData.current.carac.key) && this.getCheckboxValue(rollData) != 0
|
||||
}
|
||||
|
||||
getCheckboxLabel(rollData) { return "Malus armure" }
|
||||
getCheckboxValue(rollData) { return rollData.active.actor.getMalusArmure() }
|
||||
}
|
117
module/roll/roll-part-meditation.mjs
Normal file
@@ -0,0 +1,117 @@
|
||||
import { ITEM_TYPES } from "../constants.js"
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { RdDCarac } from "../rdd-carac.js"
|
||||
import { RdDTimestamp } from "../time/rdd-timestamp.js"
|
||||
import { TMRUtility } from "../tmr-utility.js"
|
||||
import { ROLL_MODE_MEDITATION } from "./roll-constants.mjs"
|
||||
import { PART_CARAC } from "./roll-part-carac.mjs"
|
||||
import { PART_COMP } from "./roll-part-comp.mjs"
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
|
||||
|
||||
export const PART_MEDITATION = "meditation"
|
||||
|
||||
export class RollPartMeditation extends RollPartSelect {
|
||||
|
||||
get code() { return PART_MEDITATION }
|
||||
get section() { return ROLLDIALOG_SECTION.CHOIX }
|
||||
|
||||
isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() }
|
||||
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_MEDITATION) }
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
foundry.utils.mergeObject(refs,
|
||||
{
|
||||
meditations: rollData.active.actor.itemTypes[ITEM_TYPES.meditation]
|
||||
.map(it => RollPartMeditation.$extractMeditation(it, rollData.active.actor))
|
||||
}
|
||||
)
|
||||
if (refs.meditations.length > 0) {
|
||||
this.$selectMeditation(rollData)
|
||||
}
|
||||
}
|
||||
choices(refs) { return refs.meditations }
|
||||
|
||||
static $extractMeditation(meditation, actor) {
|
||||
return {
|
||||
key: meditation.id,
|
||||
label: meditation.name,
|
||||
meditation: meditation,
|
||||
comp: actor.getCompetence(meditation.system.competence)
|
||||
}
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
this.getCurrent(rollData).value = this.getMalusConditions(rollData)
|
||||
}
|
||||
|
||||
getMalusConditions(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
const conditionsManquantes = [
|
||||
current.isComportement,
|
||||
current.isHeure,
|
||||
current.isPurification,
|
||||
current.isVeture
|
||||
].filter(it => !it).length
|
||||
return -2 * conditionsManquantes
|
||||
}
|
||||
|
||||
getMalusEchecs(rollData) {
|
||||
return this.getCurrent(rollData).meditation.system.malus
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
const malusEchecs = { label: "Méditation", diff: this.getMalusEchecs(rollData) }
|
||||
const malusConditions = { label: "Conditions", diff: this.getMalusConditions(rollData) }
|
||||
return [malusConditions, ...(malusEchecs.diff == 0 ? [] : [malusEchecs])]
|
||||
}
|
||||
|
||||
$selectMeditation(rollData, key) {
|
||||
const previous = this.getCurrent(rollData)
|
||||
const current = this.selectByKey(rollData, key, 0)
|
||||
if (current.key != previous.key) {
|
||||
const heureMonde = RdDTimestamp.getWorldTime().heure
|
||||
const heureMeditation = RdDTimestamp.findHeure(current.meditation.system.heure)?.heure
|
||||
current.isHeure = heureMeditation == heureMonde
|
||||
current.isTMR = Grammar.equalsInsensitive(current.meditation.system.tmr, TMRUtility.getTMRType(rollData.active.actor.system.reve.tmrpos.coord))
|
||||
}
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
|
||||
const selectMeditation = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-meditation"]`)
|
||||
selectMeditation.addEventListener("change", e => {
|
||||
const selectOptions = e.currentTarget.options
|
||||
const index = selectOptions.selectedIndex
|
||||
this.$selectMeditation(rollDialog.rollData, selectOptions[index]?.value)
|
||||
rollDialog.render()
|
||||
rollDialog.setModeTitle()
|
||||
})
|
||||
|
||||
this.setupListenerCondition(rollDialog, 'isComportement')
|
||||
this.setupListenerCondition(rollDialog, 'isHeure')
|
||||
this.setupListenerCondition(rollDialog, 'isPurification')
|
||||
this.setupListenerCondition(rollDialog, 'isVeture')
|
||||
}
|
||||
|
||||
setupListenerCondition(rollDialog, inputName) {
|
||||
const checkbox = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${inputName}"]`)
|
||||
checkbox.addEventListener("change", e => {
|
||||
const current = this.getCurrent(rollDialog.rollData)
|
||||
current[inputName] = e.currentTarget.checked
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
getExternalPartsFilter(partCode, rollData) {
|
||||
if (this.visible(rollData)) {
|
||||
const current = this.getCurrent(rollData)
|
||||
switch (partCode) {
|
||||
case PART_CARAC: return p => RdDCarac.isIntellect(p.key)
|
||||
case PART_COMP: return p => p.label == current.comp?.name
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
}
|
16
module/roll/roll-part-moral.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import { RdDCarac } from "../rdd-carac.js"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
|
||||
const MORAL = "moral"
|
||||
|
||||
export class RollPartMoral extends RollPartCheckbox {
|
||||
|
||||
get code() { return MORAL }
|
||||
|
||||
visible(rollData) {
|
||||
return RdDCarac.isVolonte(rollData.current.carac.key) && this.getCheckboxValue(rollData) != 0
|
||||
}
|
||||
|
||||
getCheckboxLabel(rollData) { return "Moral" }
|
||||
getCheckboxValue(rollData) { return rollData.active.actor.getMoralTotal() }
|
||||
}
|
99
module/roll/roll-part-oeuvre.mjs
Normal file
@@ -0,0 +1,99 @@
|
||||
import { ITEM_TYPES } from "../constants.js"
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { Misc } from "../misc.js"
|
||||
import { CARACS } from "../rdd-carac.js"
|
||||
import { ROLL_MODE_OEUVRE } from "./roll-constants.mjs"
|
||||
import { PART_CARAC } from "./roll-part-carac.mjs"
|
||||
import { PART_COMP } from "./roll-part-comp.mjs"
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
|
||||
|
||||
export const PART_OEUVRE = "oeuvre"
|
||||
|
||||
const ARTS = [
|
||||
{ type: ITEM_TYPES.oeuvre, action: "interpréte l'oeuvre", competence: it => it.system.competence, caracs: it => [it.system.default_carac] },
|
||||
{ type: ITEM_TYPES.chant, action: "chante", competence: it => 'Chant', caracs: it => [CARACS.OUIE] },
|
||||
{
|
||||
type: ITEM_TYPES.danse, action: "danse:", competence: it => 'Danse', caracs: it => {
|
||||
const caracs = []
|
||||
if (it.system.agilite) { caracs.push(CARACS.AGILITE) }
|
||||
if (it.system.apparence) { caracs.push(CARACS.APPARENCE) }
|
||||
return caracs
|
||||
}
|
||||
},
|
||||
{ type: ITEM_TYPES.musique, action: "joue le morceau:", competence: it => 'Musique', caracs: it => [CARACS.OUIE] },
|
||||
{ type: ITEM_TYPES.recettecuisine, action: "cuisine le plat:", competence: it => 'Cuisine', caracs: it => [CARACS.ODORATGOUT] },
|
||||
]
|
||||
|
||||
export class RollPartOeuvre extends RollPartSelect {
|
||||
onReady() {
|
||||
ARTS.forEach(art => art.label = Misc.typeName('Item', art.type))
|
||||
ARTS.map(it => `roll-oeuvre-${it.type}`)
|
||||
.forEach(art =>
|
||||
foundry.applications.handlebars.loadTemplates({ [art]: `systems/foundryvtt-reve-de-dragon/templates/roll/${art}.hbs` })
|
||||
)
|
||||
}
|
||||
|
||||
get code() { return PART_OEUVRE }
|
||||
get section() { return ROLLDIALOG_SECTION.CHOIX }
|
||||
|
||||
isValid(rollData) { return rollData.active.actor.isPersonnage() }
|
||||
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_OEUVRE) }
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.oeuvres = rollData.active.actor.items
|
||||
.filter(it => it.isOeuvre() && RollPartOeuvre.getArt(it))
|
||||
.map(it => RollPartOeuvre.$extractOeuvre(it, rollData.active.actor))
|
||||
if (refs.oeuvres.length > 0) {
|
||||
this.$selectOeuvre(rollData)
|
||||
}
|
||||
}
|
||||
|
||||
choices(refs) { return refs.oeuvres }
|
||||
|
||||
static $extractOeuvre(oeuvre, actor) {
|
||||
const art = RollPartOeuvre.getArt(oeuvre)
|
||||
return {
|
||||
key: oeuvre.id,
|
||||
label: oeuvre.name,
|
||||
art: art,
|
||||
caracs: art.caracs(oeuvre),
|
||||
value: -oeuvre.system.niveau,
|
||||
oeuvre: oeuvre,
|
||||
comp: actor.getCompetence(art.competence(oeuvre))
|
||||
}
|
||||
}
|
||||
|
||||
static getArt(oeuvre) {
|
||||
return ARTS.find(it => it.type == oeuvre.type)
|
||||
}
|
||||
|
||||
$selectOeuvre(rollData, key) {
|
||||
this.selectByKey(rollData, key, 0)
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const selectOeuvre = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-oeuvre"]`)
|
||||
|
||||
selectOeuvre.addEventListener("change", e => {
|
||||
const selectOptions = e.currentTarget.options
|
||||
const index = selectOptions.selectedIndex
|
||||
this.$selectOeuvre(rollDialog.rollData, selectOptions[index]?.value)
|
||||
rollDialog.setModeTitle()
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
getExternalPartsFilter(partCode, rollData) {
|
||||
if (this.visible(rollData)) {
|
||||
const current = this.getCurrent(rollData)
|
||||
switch (partCode) {
|
||||
case PART_CARAC: return p => current.caracs?.includes(Grammar.toLowerCaseNoAccent(p.key))
|
||||
case PART_COMP: return p => p.label == current.comp?.name
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
}
|
12
module/roll/roll-part-opponent.mjs
Normal file
@@ -0,0 +1,12 @@
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
const OPPONENT = "opponent"
|
||||
|
||||
export class RollPartOpponent extends RollPart {
|
||||
|
||||
get code() { return OPPONENT }
|
||||
get section() { return ROLLDIALOG_SECTION.ACTION }
|
||||
|
||||
visible(rollData) { return rollData.mode.opposed }
|
||||
title(rollData) { return rollData.opponent?.name ?? '' }
|
||||
}
|
32
module/roll/roll-part-rollmode.mjs
Normal file
@@ -0,0 +1,32 @@
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
const ROLLMODE = "rollmode"
|
||||
|
||||
export class RollPartRollMode extends RollPart {
|
||||
|
||||
get code() { return ROLLMODE }
|
||||
get section() { return ROLLDIALOG_SECTION.CONDITIONS }
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.rollmodes = Object.entries(CONFIG.Dice.rollModes).map(([k, v]) => { return { key: k, label: v.label, icon: v.icon } })
|
||||
}
|
||||
|
||||
restore(rollData) {
|
||||
this.setCurrent(rollData, { key: this.getSaved(rollData)?.key ?? game.settings.get("core", "rollMode") })
|
||||
}
|
||||
|
||||
store(rollData, targetData) {
|
||||
this.setSaved(targetData, { key: this.getCurrent(rollData).key })
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const rollvisibilityButtons = rollDialog.element.querySelectorAll(`button[name="roll-rollmode"]`)
|
||||
rollvisibilityButtons?.forEach(it => it.addEventListener(
|
||||
"click", e => {
|
||||
e.preventDefault()
|
||||
this.getCurrent(rollDialog.rollData).key = e.currentTarget.dataset.key
|
||||
rollDialog.render()
|
||||
}))
|
||||
}
|
||||
}
|
50
module/roll/roll-part-select.mjs
Normal file
@@ -0,0 +1,50 @@
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { RollPart } from "./roll-part.mjs"
|
||||
|
||||
export class RollPartSelect extends RollPart {
|
||||
|
||||
restore(rollData) {
|
||||
this.setCurrent(rollData, { key: this.getSaved(rollData)?.key })
|
||||
}
|
||||
|
||||
store(rollData, targetData) {
|
||||
this.setSaved(targetData, { key: this.getCurrent(rollData).key })
|
||||
}
|
||||
|
||||
choices(refs) { return [] }
|
||||
|
||||
getAjustements(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (current) {
|
||||
return [{ label: current.label, diff: current.value }]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
selectByKey(rollData, key = undefined, defValue = undefined) {
|
||||
const refs = this.getRefs(rollData)
|
||||
const choices = this.choices(refs) ??[]
|
||||
const current = this.getCurrent(rollData)
|
||||
const newChoice = (choices.length == 0)
|
||||
? { key: '', value: defValue }
|
||||
: this.$getSelectedChoice(choices, key ?? current?.key ?? refs.key ?? '')
|
||||
this.setCurrent(rollData, newChoice)
|
||||
return newChoice
|
||||
}
|
||||
|
||||
$getSelectedChoice(choices, key) {
|
||||
const potential = choices.filter(it => Grammar.includesLowerCaseNoAccent(it.key, key))
|
||||
switch (potential.length) {
|
||||
case 0:
|
||||
// ui.notifications.warn(`Aucun choix de ${this.name} pour ${key}`)
|
||||
return choices[0]
|
||||
case 1:
|
||||
return potential[0]
|
||||
default:
|
||||
const selected = potential.find(it => Grammar.equalsInsensitive(it.key, key))
|
||||
// ui.notifications.info(`Plusieurs choix de ${this.name} pour ${key}, le premier est utilisé`)
|
||||
return selected ?? potential[0]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
93
module/roll/roll-part-sign.mjs
Normal file
@@ -0,0 +1,93 @@
|
||||
import { Misc } from "../misc.js"
|
||||
import { StatusEffects } from "../settings/status-effects.js"
|
||||
import { ROLL_MODE_ATTAQUE, ROLL_MODE_DEFENSE } from "./roll-constants.mjs"
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
export const PART_SIGN = "sign"
|
||||
|
||||
export class RollPartSign extends RollPart {
|
||||
|
||||
get code() { return PART_SIGN }
|
||||
get section() { return ROLLDIALOG_SECTION.AJUSTEMENTS }
|
||||
|
||||
loadRefs(rollData) {
|
||||
this.setFromState(rollData)
|
||||
}
|
||||
|
||||
restore(rollData) {
|
||||
this.setCurrent(rollData, this.getSaved(rollData))
|
||||
}
|
||||
|
||||
store(rollData, targetData) {
|
||||
this.setSaved(targetData, this.getCurrent(rollData))
|
||||
}
|
||||
|
||||
// visible(rollData) {
|
||||
// const current = this.getCurrent(rollData)
|
||||
// return current.surprise != ''
|
||||
// }
|
||||
|
||||
isCombat(rollData) {
|
||||
return [ROLL_MODE_ATTAQUE, ROLL_MODE_DEFENSE].includes(rollData.mode.current) || rollData.mode.isCombat
|
||||
}
|
||||
|
||||
prepareContext(rollData) {
|
||||
this.setFromState(rollData)
|
||||
}
|
||||
|
||||
setFromState(rollData) {
|
||||
if (rollData.mode.retry) {
|
||||
return
|
||||
}
|
||||
const actor = rollData.active.actor;
|
||||
const isCombat = this.isCombat(rollData)
|
||||
const current = this.getCurrent(rollData)
|
||||
current.surprise = actor.getSurprise(isCombat)
|
||||
current.reasons = actor.getEffects(it => StatusEffects.niveauSurprise(it) > 0).map(it => it.name)
|
||||
current.diviseur = 1
|
||||
if (isCombat && actor.isDemiReve()) {
|
||||
current.reasons.push('Demi-rêve en combat')
|
||||
}
|
||||
if (current.surprise == 'demi') {
|
||||
current.diviseur *= 2
|
||||
}
|
||||
|
||||
if (this.isAttaqueFinesse(rollData)) {
|
||||
current.diviseur *= 2
|
||||
current.reasons.push('Attaque en finesse')
|
||||
}
|
||||
if (this.isForceInsuffisante(rollData)) {
|
||||
current.diviseur *= 2
|
||||
current.reasons.push('Force insuffisante')
|
||||
}
|
||||
current.reason = current.reasons.join(', ')
|
||||
}
|
||||
|
||||
isForceInsuffisante(rollData) {
|
||||
//this.isCombat(rollData) && ... arme avec force min
|
||||
return this.isCombat(rollData) && true
|
||||
}
|
||||
|
||||
isAttaqueFinesse(rollData) {
|
||||
// this.rollData.selected[PART_DEFENSE] && attaquant avec particulière en finesse
|
||||
return ROLL_MODE_DEFENSE == rollData.mode.current && true
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (current.surprise == 'demi') {
|
||||
return [{ label: 'Significative requise ' + Misc.getFractionOneN(current.diviseur), diff: undefined }]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const input = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`)
|
||||
|
||||
input?.addEventListener("change", e => {
|
||||
this.getCurrent(rollDialog.rollData).value = parseInt(e.currentTarget.value)
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
}
|
129
module/roll/roll-part-sort.mjs
Normal file
@@ -0,0 +1,129 @@
|
||||
import { ITEM_TYPES } from "../constants.js"
|
||||
import { ROLL_MODE_SORT } from "./roll-constants.mjs"
|
||||
import { PART_CARAC } from "./roll-part-carac.mjs"
|
||||
import { PART_COMP } from "./roll-part-comp.mjs"
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
|
||||
import { TMRUtility } from "../tmr-utility.js"
|
||||
import { RdDItemSort } from "../item-sort.js"
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
|
||||
export const PART_SORT = "sort"
|
||||
|
||||
export class RollPartSort extends RollPartSelect {
|
||||
onReady() {
|
||||
// TODO: utiliser un hook pour écouter les déplacements dans les TMRs?
|
||||
}
|
||||
get code() { return PART_SORT }
|
||||
get section() { return ROLLDIALOG_SECTION.CHOIX }
|
||||
|
||||
isValid(rollData) { return rollData.active.actor.isPersonnage() && rollData.active.actor.isHautRevant() }
|
||||
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_SORT) }
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
const coord = rollData.active.actor.system.reve.tmrpos.coord
|
||||
const draconics = rollData.active.actor.getDraconicList()
|
||||
const sorts = rollData.active.actor.itemTypes[ITEM_TYPES.sort]
|
||||
.map(s => RollPartSort.$extractSort(s, coord, draconics))
|
||||
|
||||
foundry.utils.mergeObject(refs,
|
||||
{
|
||||
coord: coord,
|
||||
tmr: TMRUtility.getTMR(coord),
|
||||
reve: rollData.active.actor.system.reve.reve.value,
|
||||
draconics: draconics,
|
||||
all: sorts,
|
||||
sorts: sorts.filter(it => RdDItemSort.isSortOnCoord(it.sort, coord))
|
||||
},
|
||||
{ inplace: true }
|
||||
)
|
||||
if (refs.sorts.length > 0) {
|
||||
this.$selectSort(rollData)
|
||||
}
|
||||
}
|
||||
|
||||
choices(refs) { return refs.sorts }
|
||||
|
||||
static $extractSort(sort, coord, draconics) {
|
||||
const isDiffVariable = RdDItemSort.isDifficulteVariable(sort)
|
||||
const isReveVariable = RdDItemSort.isCoutVariable(sort)
|
||||
return {
|
||||
key: sort.id,
|
||||
label: sort.name,
|
||||
value: isDiffVariable ? -7 : parseInt(sort.system.difficulte),
|
||||
ptreve: isReveVariable ? 1 : sort.system.ptreve,
|
||||
caseTMR: RdDItemSort.getCaseTMR(sort),
|
||||
isDiffVariable: isDiffVariable,
|
||||
isReveVariable: isReveVariable,
|
||||
isReserve: false,
|
||||
sort: sort,
|
||||
draconics: RdDItemSort.getDraconicsSort(draconics, sort).map(it => it.name)
|
||||
}
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (current) {
|
||||
const reserve = current.isReserve ?
|
||||
[{ label: `Mise en réserve en ${current.coord}` }] : []
|
||||
const bonusCase = current.bonusCase ?
|
||||
[{ label: `Bonus case +${current.bonusCase}%` }] : []
|
||||
return [
|
||||
{ label: current.label, diff: current.value },
|
||||
{ label: `r${current.ptreve}` },
|
||||
...bonusCase,
|
||||
...reserve
|
||||
]
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
$selectSort(rollData, key) {
|
||||
const previous = this.getCurrent(rollData)
|
||||
const current = this.selectByKey(rollData, key, -7)
|
||||
if (current.key != previous.key) { }
|
||||
current.bonusCase = RdDItemSort.getCaseBonus(current.sort,
|
||||
rollData.active.actor.system.reve.tmrpos.coord)
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const current = this.getCurrent(rollDialog.rollData)
|
||||
const selectSort = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-sort"]`)
|
||||
const inputDiff = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="diff-var"]`)
|
||||
const inputPtReve = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="ptreve-var"]`)
|
||||
const checkboxReserve = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="reserve"]`)
|
||||
|
||||
selectSort.addEventListener("change", e => {
|
||||
const selectOptions = e.currentTarget.options
|
||||
const index = selectOptions.selectedIndex
|
||||
this.$selectSort(rollDialog.rollData, selectOptions[index]?.value)
|
||||
rollDialog.setModeTitle()
|
||||
rollDialog.render()
|
||||
})
|
||||
|
||||
inputDiff?.addEventListener("change", e => {
|
||||
current.value = parseInt(e.currentTarget.value)
|
||||
rollDialog.render()
|
||||
})
|
||||
inputPtReve?.addEventListener("change", e => {
|
||||
current.ptreve = parseInt(e.currentTarget.value)
|
||||
rollDialog.render()
|
||||
})
|
||||
checkboxReserve?.addEventListener("change", e => {
|
||||
current.isReserve = e.currentTarget.checked
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
getExternalPartsFilter(partCode, rollData) {
|
||||
if (this.visible(rollData)) {
|
||||
const current = this.getCurrent(rollData)
|
||||
switch (partCode) {
|
||||
case PART_CARAC: return p => p.key == 'reve'
|
||||
case PART_COMP: return p => current.draconics?.includes(p.label)
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
}
|
16
module/roll/roll-part-surenc.mjs
Normal file
@@ -0,0 +1,16 @@
|
||||
import { RdDCarac } from "../rdd-carac.js"
|
||||
import { RollPartCheckbox } from "./roll-part-checkbox.mjs"
|
||||
|
||||
const SURENC = "surenc"
|
||||
|
||||
export class RollPartSurEnc extends RollPartCheckbox {
|
||||
|
||||
get code() { return SURENC }
|
||||
|
||||
visible(rollData) {
|
||||
return RdDCarac.isActionPhysique(rollData.current.carac.key) && rollData.active.actor.isSurenc()
|
||||
}
|
||||
getCheckboxIcon(rollData) { return '<i class="fa-solid fa-weight-hanging"></i>' }
|
||||
getCheckboxLabel(rollData) { return "Sur-enc." }
|
||||
getCheckboxValue(rollData) { return rollData.active.actor.computeMalusSurEncombrement() }
|
||||
}
|
67
module/roll/roll-part-tache.mjs
Normal file
@@ -0,0 +1,67 @@
|
||||
import { ITEM_TYPES } from "../constants.js"
|
||||
import { Grammar } from "../grammar.js"
|
||||
import { ROLL_MODE_TACHE } from "./roll-constants.mjs"
|
||||
import { PART_CARAC } from "./roll-part-carac.mjs"
|
||||
import { PART_COMP } from "./roll-part-comp.mjs"
|
||||
import { RollPartSelect } from "./roll-part-select.mjs"
|
||||
import { ROLLDIALOG_SECTION } from "./roll-part.mjs"
|
||||
|
||||
export const PART_TACHE = "tache"
|
||||
|
||||
export class RollPartTache extends RollPartSelect {
|
||||
|
||||
get code() { return PART_TACHE }
|
||||
get section() { return ROLLDIALOG_SECTION.CHOIX }
|
||||
|
||||
isValid(rollData) { return rollData.active.actor.isPersonnage() }
|
||||
visible(rollData) { return this.isRollMode(rollData, ROLL_MODE_TACHE) }
|
||||
|
||||
loadRefs(rollData) {
|
||||
const refs = this.getRefs(rollData)
|
||||
refs.taches = rollData.active.actor.itemTypes[ITEM_TYPES.tache]
|
||||
.filter(tache => tache.system.points_de_tache_courant < tache.system.points_de_tache)
|
||||
.map(tache => RollPartTache.$extractTache(tache, rollData.active.actor))
|
||||
if (refs.taches.length > 0) {
|
||||
this.$selectTache(rollData)
|
||||
}
|
||||
}
|
||||
choices(refs) { return refs.taches }
|
||||
|
||||
static $extractTache(tache, actor) {
|
||||
return {
|
||||
key: tache.id,
|
||||
label: tache.name,
|
||||
value: tache.system.difficulte,
|
||||
tache: tache,
|
||||
comp: actor.getCompetence(tache.system.competence)
|
||||
}
|
||||
}
|
||||
|
||||
$selectTache(rollData, key) {
|
||||
this.selectByKey(rollData, key, 0)
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const selectTache = rollDialog.element.querySelector(`roll-section[name="${this.code}"] select[name="select-tache"]`)
|
||||
|
||||
selectTache.addEventListener("change", e => {
|
||||
const selectOptions = e.currentTarget.options
|
||||
const index = selectOptions.selectedIndex
|
||||
this.$selectTache(rollDialog.rollData, selectOptions[index]?.value)
|
||||
rollDialog.setModeTitle()
|
||||
rollDialog.render()
|
||||
})
|
||||
}
|
||||
|
||||
getExternalPartsFilter(partCode, rollData) {
|
||||
if (this.visible(rollData)) {
|
||||
const current = this.getCurrent(rollData)
|
||||
switch (partCode) {
|
||||
case PART_CARAC: return p => Grammar.equalsInsensitive(p.key, current?.tache.system.carac)
|
||||
case PART_COMP: return p => p.label == current?.comp.name
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
}
|
31
module/roll/roll-part-tricher.mjs
Normal file
@@ -0,0 +1,31 @@
|
||||
import { ROLLDIALOG_SECTION, RollPart } from "./roll-part.mjs"
|
||||
|
||||
const PART_TRICHER = "tricher"
|
||||
|
||||
export class RollPartTricher extends RollPart {
|
||||
|
||||
get code() { return PART_TRICHER }
|
||||
get section() { return ROLLDIALOG_SECTION.CONDITIONS }
|
||||
|
||||
visible(rollData) { return game.user.isGM }
|
||||
|
||||
prepareContext(rollData) {
|
||||
const current = this.getCurrent(rollData)
|
||||
if (current.resultat == undefined) {
|
||||
current.resultat = -1
|
||||
}
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
rollData.current.resultat = this.getCurrent(rollData).resultat
|
||||
return []
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) {
|
||||
const input = rollDialog.element.querySelector(`roll-section[name="${this.code}"] input[name="${this.code}"]`)
|
||||
|
||||
input?.addEventListener("change", e => {
|
||||
this.getCurrent(rollDialog.rollData).resultat = parseInt(e.currentTarget.value)
|
||||
})
|
||||
}
|
||||
}
|
97
module/roll/roll-part.mjs
Normal file
@@ -0,0 +1,97 @@
|
||||
import { Misc } from "../misc.js"
|
||||
|
||||
export const ROLLDIALOG_SECTION = {
|
||||
ACTION: 'action',
|
||||
CARAC: 'carac',
|
||||
COMP: 'comp',
|
||||
CHOIX: 'choix',
|
||||
CONDITIONS: 'conditions',
|
||||
AJUSTEMENTS: 'ajustements',
|
||||
}
|
||||
export class RollPart {
|
||||
static settingKey(rollPart, key) { return `roll-part-${rollPart.code}.${key}` }
|
||||
|
||||
get code() { throw new Error(`Pas dse code définie pour ${this}`) }
|
||||
get name() { return this.code }
|
||||
/** la section de la fenêtre ou le paramêtre apparaît */
|
||||
get section() { return undefined }
|
||||
get priority() { return 0 /* TODO */ }
|
||||
/** le template handlebars pour affichage */
|
||||
get template() { return `systems/foundryvtt-reve-de-dragon/templates/roll/roll-part-${this.code}.hbs` }
|
||||
|
||||
initialize(rollData) {
|
||||
if (rollData.refs[this.code] == undefined) {
|
||||
rollData.refs[this.code] = {}
|
||||
}
|
||||
if (rollData.current[this.code] == undefined) {
|
||||
rollData.current[this.code] = {}
|
||||
}
|
||||
if (rollData.selected[this.code] == undefined) {
|
||||
rollData.selected[this.code] = {}
|
||||
}
|
||||
}
|
||||
|
||||
/** le conteneur de données du RollPart */
|
||||
getRefs(rollData) {
|
||||
return rollData.refs[this.code]
|
||||
}
|
||||
|
||||
/** les informations de sélection du paramètre */
|
||||
getCurrent(rollData) {
|
||||
return rollData.current[this.code]
|
||||
}
|
||||
setCurrent(rollData, current) {
|
||||
rollData.current[this.code] = current
|
||||
}
|
||||
|
||||
/** les informations minimales représentant la sélection dans le rollData permettant de restaurer la fenêtre */
|
||||
getSaved(rollData) {
|
||||
return rollData.selected[this.code] ?? {}
|
||||
}
|
||||
setSaved(rollData, saved) {
|
||||
rollData.selected[this.code] = saved
|
||||
}
|
||||
|
||||
restore(rollData) { }
|
||||
store(rollData, targetData) { }
|
||||
|
||||
/**
|
||||
* le texte à ajouter dans la barre de titre
|
||||
* @returns une chaîne vide si rien ne doit être affiché
|
||||
*/
|
||||
title() { return '' }
|
||||
isRollMode(rollData, mode) { return rollData.mode.current == mode }
|
||||
|
||||
isActive(rollData) { return this.isValid(rollData) && this.visible(rollData) }
|
||||
isValid(rollData) { return true }
|
||||
visible(rollData) { return true }
|
||||
|
||||
onReady() { }
|
||||
loadRefs(rollData) { }
|
||||
|
||||
prepareContext(rollData) { }
|
||||
|
||||
/** ---- cross roll-part filtering ---- */
|
||||
setFilter(rollData, filter) { }
|
||||
getSpecialComp(rollData) { return [] }
|
||||
setSpecialComp(comps) { }
|
||||
|
||||
getExternalPartsFilter(partCode, rollData) { return undefined }
|
||||
setExternalFilter(visibleRollParts, rollData) {
|
||||
const predicate = Misc.and(
|
||||
visibleRollParts.map(p => p.getExternalPartsFilter(this.code, rollData)).filter(f => f != undefined)
|
||||
)
|
||||
this.setFilter(rollData, predicate);
|
||||
}
|
||||
|
||||
toTemplateData() {
|
||||
return { code: this.code, name: this.name, template: this.template, section: this.section }
|
||||
}
|
||||
|
||||
getAjustements(rollData) {
|
||||
return []
|
||||
}
|
||||
|
||||
async _onRender(rollDialog, context, options) { }
|
||||
|
||||
}
|
@@ -24,11 +24,6 @@ export const referenceAjustements = {
|
||||
getLabel: (rollData, actor) => rollData.competence?.name,
|
||||
getValue: (rollData, actor) => rollData.competence?.system?.niveau,
|
||||
},
|
||||
meditation: {
|
||||
isUsed: (rollData, actor) => rollData.meditation,
|
||||
getLabel: (rollData, actor) => 'Méditation',
|
||||
getValue: (rollData, actor) => RdDItemMeditation.calculDifficulte(rollData)
|
||||
},
|
||||
diffLibre: {
|
||||
isUsed: (rollData, actor) => rollData.diffLibre != undefined,
|
||||
getLabel: (rollData, actor) => rollData.selectedSort?.name ?? rollData.attackerRoll ?? RdDPossession.isDefensePossession(rollData) ? 'Imposée' : 'Libre',
|
||||
@@ -41,99 +36,59 @@ export const referenceAjustements = {
|
||||
getLabel: (rollData, actor) => 'Conditions',
|
||||
getValue: (rollData, actor) => rollData.diffConditions
|
||||
},
|
||||
tactique: {
|
||||
isUsed: (rollData, actor) => rollData.tactique,
|
||||
getLabel: (rollData, actor) => RdDBonus.find(rollData.tactique).descr,
|
||||
getValue: (rollData, actor) => RdDBonus.find(rollData.tactique).attaque,
|
||||
},
|
||||
attaqueDefenseurSurpris: {
|
||||
isUsed: (rollData, actor) => rollData.surpriseDefenseur,
|
||||
getLabel: (rollData, actor) => RdDBonus.find(rollData.surpriseDefenseur).descr + (rollData.attackerRoll ? '' : ' défenseur'),
|
||||
getValue: (rollData, actor) => RdDBonus.find(rollData.surpriseDefenseur).attaque,
|
||||
},
|
||||
etat: {
|
||||
isUsed: (rollData, actor) => !RollDataAjustements.isIgnoreEtatGeneral(rollData),
|
||||
getLabel: (rollData, actor) => 'Etat général',
|
||||
getValue: (rollData, actor) => actor.getEtatGeneral({ ethylisme: rollData.forceAlcool != undefined })
|
||||
},
|
||||
malusArmure: {
|
||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac),
|
||||
isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac),
|
||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac?.label),
|
||||
isUsed: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac?.label),
|
||||
getLabel: (rollData, actor) => 'Malus armure',
|
||||
getValue: (rollData, actor) => actor.getMalusArmure()
|
||||
},
|
||||
encTotal: {
|
||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence),
|
||||
isUsed: (rollData, actor) => !rollData.oeuvre && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence) && rollData.use?.encTotal,
|
||||
isVisible: (rollData, actor) => RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac?.label) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence?.name),
|
||||
isUsed: (rollData, actor) => !rollData.oeuvre && RdDCarac.isAgiliteOuDerobee(rollData.selectedCarac?.label) && RdDItemCompetence.isMalusEncombrementTotal(rollData.competence?.name) && rollData.use?.encTotal,
|
||||
getLabel: (rollData, actor) => 'Encombrement total',
|
||||
getValue: (rollData, actor) => -actor.getEncTotal()
|
||||
},
|
||||
surenc: {
|
||||
isVisible: (rollData, actor) => RdDCarac.isActionPhysique(rollData.selectedCarac) && actor.isSurenc(),
|
||||
isUsed: (rollData, actor) => rollData.use.surenc && RdDCarac.isActionPhysique(rollData.selectedCarac),
|
||||
isVisible: (rollData, actor) => RdDCarac.isActionPhysique(rollData.selectedCarac?.label) && actor.isSurenc(),
|
||||
isUsed: (rollData, actor) => rollData.use.surenc && RdDCarac.isActionPhysique(rollData.selectedCarac?.label),
|
||||
getLabel: (rollData, actor) => 'Sur-encombrement',
|
||||
getValue: (rollData, actor) => actor.computeMalusSurEncombrement()
|
||||
},
|
||||
rituel: {
|
||||
isUsed: (rollData, actor) => actor.isPersonnage() && ReglesOptionnelles.isUsing("astrologie") && rollData.selectedSort?.system.isrituel,
|
||||
getLabel: (rollData, actor) => 'Astrologique',
|
||||
getValue: (rollData, actor) => actor.ajustementAstrologique()
|
||||
},
|
||||
astrologique: {
|
||||
isVisible: (rollData, actor) => actor.isPersonnage() && ReglesOptionnelles.isUsing("astrologie") && RdDCarac.isChance(rollData.selectedCarac),
|
||||
isUsed: (rollData, actor) => RdDCarac.isChance(rollData.selectedCarac) && rollData.use.astrologique,
|
||||
isVisible: (rollData, actor) => actor.isPersonnage() && ReglesOptionnelles.isUsing("astrologie") && RdDCarac.isChance(rollData.selectedCarac?.label),
|
||||
isUsed: (rollData, actor) => RdDCarac.isChance(rollData.selectedCarac?.label) && rollData.use.astrologique,
|
||||
getLabel: (rollData, actor) => 'Astrologique',
|
||||
getValue: (rollData, actor) => actor.ajustementAstrologique()
|
||||
},
|
||||
moral: {
|
||||
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac) && rollData.use?.moral,
|
||||
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isActionPhysique(rollData.selectedCarac?.label) && rollData.use?.moral,
|
||||
isUsed: (rollData, actor) => rollData.use.moral,
|
||||
getLabel: (rollData, actor) => 'Appel au moral',
|
||||
getValue: (rollData, actor) => 1
|
||||
},
|
||||
moralTotal: {
|
||||
isUsed: (rollData, actor) => RdDCarac.isVolonte(rollData.selectedCarac?.label),
|
||||
getLabel: (rollData, actor) => 'Moral',
|
||||
getValue: (rollData, actor) => actor.getMoralTotal()
|
||||
},
|
||||
coeur: {
|
||||
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isVolonte(rollData.selectedCarac),
|
||||
isVisible: (rollData, actor) => actor.isPersonnage() && RdDCarac.isVolonte(rollData.selectedCarac?.label),
|
||||
isUsed: (rollData, actor) => rollData.use.coeur != undefined,
|
||||
getLabel: (rollData, actor) => 'Ajustement de cœur',
|
||||
getValue: (rollData, actor) => -2 * (rollData.use.coeur?.coeur ?? 0)
|
||||
},
|
||||
moralTotal: {
|
||||
isUsed: (rollData, actor) => RdDCarac.isVolonte(rollData.selectedCarac),
|
||||
getLabel: (rollData, actor) => 'Moral',
|
||||
getValue: (rollData, actor) => actor.getMoralTotal()
|
||||
},
|
||||
facteurSign: {
|
||||
isUsed: (rollData, actor) => rollData.diviseurSignificative > 1,
|
||||
getLabel: (rollData, actor) => Misc.getFractionHtml(rollData.diviseurSignificative),
|
||||
getDescr: (rollData, actor) => rollData.diviseurSignificative > 1 ? `Facteur significative <span class="rdd-diviseur">×${Misc.getFractionHtml(rollData.diviseurSignificative)}</span>` : ''
|
||||
},
|
||||
isEcaille: {
|
||||
isVisible: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
|
||||
isUsed: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
|
||||
getLabel: (rollData, actor) => "Ecaille d'Efficacité: ",
|
||||
getValue: (rollData, actor) => rollData.arme?.system.magique ? Math.max(Number(rollData.arme?.system.ecaille_efficacite), 0) : 0,
|
||||
},
|
||||
finesse: {
|
||||
isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData),
|
||||
getDescr: (rollData, actor) => 'Attaque particulière en finesse',
|
||||
},
|
||||
armeParade: {
|
||||
isUsed: (rollData, actor) => RdDItemArme.needParadeSignificative(rollData.attackerRoll?.arme, rollData.arme),
|
||||
getDescr: (rollData, actor) => rollData.attackerRoll && rollData.arme ? `${RdDItemArme.getNomCategorieParade(rollData.attackerRoll?.arme)} vs ${RdDItemArme.getNomCategorieParade(rollData.arme)}` : ''
|
||||
},
|
||||
surprise: {
|
||||
isUsed: (rollData, actor) => actor.getSurprise(rollData.passeArme),
|
||||
getDescr: (rollData, actor) => RdDBonus.find(actor.getSurprise()).descr
|
||||
},
|
||||
bonusCase: {
|
||||
isUsed: (rollData, actor) => rollData.selectedSort && rollData.tmr.coord,
|
||||
getDescr: (rollData, actor) => rollData.selectedSort && rollData.tmr.coord ? `Bonus de case: ${RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.tmr.coord)}%` : ''
|
||||
},
|
||||
rencontreTMR: {
|
||||
isVisible: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
|
||||
isUsed: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
|
||||
getLabel: (rollData, actor) => rollData.rencontre?.name,
|
||||
getValue: (rollData, actor) => - (rollData.rencontre?.system.force ?? 0)
|
||||
|
||||
|
||||
|
||||
meditation: {
|
||||
isUsed: (rollData, actor) => rollData.meditation,
|
||||
getLabel: (rollData, actor) => 'Méditation',
|
||||
getValue: (rollData, actor) => RdDItemMeditation.calculDifficulte(rollData)
|
||||
},
|
||||
ethylismeAlcool: {
|
||||
isVisible: (rollData, actor) => rollData.nbDoses != undefined,
|
||||
@@ -153,12 +108,61 @@ export const referenceAjustements = {
|
||||
getLabel: (rollData, actor) => "Ethylisme - " + RdDUtility.getNomEthylisme(rollData.ethylisme),
|
||||
getValue: (rollData, actor) => rollData.ethylisme,
|
||||
},
|
||||
facteurSign: {
|
||||
isUsed: (rollData, actor) => rollData.diviseurSignificative > 1,
|
||||
getLabel: (rollData, actor) => Misc.getFractionOneN(rollData.diviseurSignificative),
|
||||
getDescr: (rollData, actor) => rollData.diviseurSignificative > 1 ? `Facteur significative <span class="rdd-diviseur">×${Misc.getFractionOneN(rollData.diviseurSignificative)}</span>` : ''
|
||||
},
|
||||
isEcaille: {
|
||||
isVisible: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
|
||||
isUsed: (rollData, actor) => rollData.arme?.system.magique && Number(rollData.arme?.system.ecaille_efficacite) > 0,
|
||||
getLabel: (rollData, actor) => "Ecaille d'Efficacité: ",
|
||||
getValue: (rollData, actor) => rollData.arme?.system.magique ? Math.max(Number(rollData.arme?.system.ecaille_efficacite), 0) : 0,
|
||||
},
|
||||
tactique: {
|
||||
isUsed: (rollData, actor) => rollData.tactique,
|
||||
getLabel: (rollData, actor) => RdDBonus.find(rollData.tactique).descr,
|
||||
getValue: (rollData, actor) => RdDBonus.find(rollData.tactique).attaque,
|
||||
},
|
||||
finesse: {
|
||||
isUsed: (rollData, actor) => RdDBonus.isDefenseAttaqueFinesse(rollData),
|
||||
getDescr: (rollData, actor) => 'Attaque particulière en finesse',
|
||||
},
|
||||
surprise: {
|
||||
isUsed: (rollData, actor) => actor.getSurprise(rollData.passeArme),
|
||||
getDescr: (rollData, actor) => RdDBonus.find(actor.getSurprise()).descr
|
||||
},
|
||||
attaqueDefenseurSurpris: {
|
||||
isUsed: (rollData, actor) => rollData.surpriseDefenseur,
|
||||
getLabel: (rollData, actor) => RdDBonus.find(rollData.surpriseDefenseur).descr + (rollData.attackerRoll ? '' : ' défenseur'),
|
||||
getValue: (rollData, actor) => RdDBonus.find(rollData.surpriseDefenseur).attaque,
|
||||
},
|
||||
armeParade: {
|
||||
isUsed: (rollData, actor) => RdDItemArme.needParadeSignificative(rollData.attackerRoll?.arme, rollData.arme),
|
||||
getDescr: (rollData, actor) => rollData.attackerRoll && rollData.arme ? `${RdDItemArme.getNomCategorieParade(rollData.attackerRoll?.arme)} vs ${RdDItemArme.getNomCategorieParade(rollData.arme)}` : ''
|
||||
},
|
||||
tailleempoignade: {
|
||||
isVisible: (rollData, actor) => rollData.isEmpoignade,
|
||||
isUsed: (rollData, actor) => rollData.isEmpoignade,
|
||||
getLabel: (rollData, actor) => "Malus de taille",
|
||||
getValue: (rollData, actor) => rollData.malusTaille,
|
||||
}
|
||||
},
|
||||
|
||||
rituel: {
|
||||
isUsed: (rollData, actor) => actor.isPersonnage() && ReglesOptionnelles.isUsing("astrologie") && rollData.selectedSort?.system.isrituel,
|
||||
getLabel: (rollData, actor) => 'Astrologique',
|
||||
getValue: (rollData, actor) => actor.ajustementAstrologique()
|
||||
},
|
||||
bonusCase: {
|
||||
isUsed: (rollData, actor) => rollData.selectedSort && rollData.tmr.coord,
|
||||
getDescr: (rollData, actor) => rollData.selectedSort && rollData.tmr.coord ? `Bonus de case: ${RdDItemSort.getCaseBonus(rollData.selectedSort, rollData.tmr.coord)}%` : ''
|
||||
},
|
||||
rencontreTMR: {
|
||||
isVisible: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
|
||||
isUsed: (rollData, actor) => rollData.tmr && rollData.rencontre?.name,
|
||||
getLabel: (rollData, actor) => rollData.rencontre?.name,
|
||||
getValue: (rollData, actor) => - (rollData.rencontre?.system.force ?? 0)
|
||||
},
|
||||
}
|
||||
|
||||
export class RollDataAjustements {
|
||||
@@ -196,8 +200,8 @@ export class RollDataAjustements {
|
||||
const selectedCarac = rollData.selectedCarac;
|
||||
return !selectedCarac ||
|
||||
rollData.ethylisme ||
|
||||
RdDCarac.isChance(selectedCarac) ||
|
||||
(RdDCarac.isReve(selectedCarac) && !rollData.competence);
|
||||
RdDCarac.isChance(selectedCarac?.label) ||
|
||||
(RdDCarac.isReve(selectedCarac?.label) && !rollData.competence);
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -2,8 +2,10 @@ import { SYSTEM_RDD } from "../constants.js"
|
||||
import { Misc } from "../misc.js"
|
||||
|
||||
export const EXPORT_CSV_SCRIPTARIUM = 'export-csv-scriptarium'
|
||||
export const ROLL_DIALOG_V2 = 'roll-drialog-v2'
|
||||
|
||||
const OPTIONS_AVANCEES = [
|
||||
{ group: 'Fenêtres', name: ROLL_DIALOG_V2, descr: "Utiliser les nouvelles fenêtres de jet", default: false },
|
||||
{ group: 'Menus', name: EXPORT_CSV_SCRIPTARIUM, descr: "Proposer le menu d'export csv Scriptarium", default: false },
|
||||
]
|
||||
|
||||
|
@@ -1,43 +1,47 @@
|
||||
import { SYSTEM_RDD } from "../constants.js";
|
||||
|
||||
export const STATUSES = {
|
||||
StatusStunned: 'stun',
|
||||
StatusBleeding: 'bleeding',
|
||||
StatusProne: 'prone',
|
||||
StatusGrappling: 'grappling',
|
||||
StatusGrappled: 'grappled',
|
||||
StatusRestrained: 'restrain',
|
||||
StatusStunned: 'stun',
|
||||
StatusProne: 'prone',
|
||||
StatusUnconscious: 'unconscious',
|
||||
StatusBlind: 'blind',
|
||||
StatusComma: 'comma',
|
||||
StatusBleeding: 'bleeding',
|
||||
StatusDead: 'dead',
|
||||
StatusDemiReve: 'demi-reve',
|
||||
}
|
||||
|
||||
const demiReveStatusEffect = { rdd: true, id: STATUSES.StatusDemiReve, name: 'EFFECT.StatusDemiReve', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd12.svg' };
|
||||
const rddStatusEffects = [
|
||||
{ rdd: true, id: STATUSES.StatusStunned, name: 'EFFECT.StatusStunned', img: 'icons/svg/stoned.svg', "duration.rounds": 1 },
|
||||
{ rdd: true, id: STATUSES.StatusBleeding, name: 'EFFECT.StatusBleeding', img: 'icons/svg/blood.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusProne, name: 'EFFECT.StatusProne', img: 'icons/svg/falling.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusGrappling, tint: '#33cc33', name: 'EFFECT.StatusGrappling', img: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.webp' },
|
||||
{ rdd: true, id: STATUSES.StatusGrappled, tint: '#ff9900', name: 'EFFECT.StatusGrappled', img: 'systems/foundryvtt-reve-de-dragon/icons/empoignade.webp' },
|
||||
|
||||
{ rdd: true, id: STATUSES.StatusRestrained, name: 'EFFECT.StatusRestrained', img: 'icons/svg/net.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusStunned, name: 'EFFECT.StatusStunned', img: 'icons/svg/stoned.svg', "duration.rounds": 1 },
|
||||
{ rdd: true, id: STATUSES.StatusProne, name: 'EFFECT.StatusProne', img: 'icons/svg/falling.svg' },
|
||||
|
||||
{ rdd: true, id: STATUSES.StatusUnconscious, name: 'EFFECT.StatusUnconscious', img: 'icons/svg/unconscious.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusBlind, name: 'EFFECT.StatusBlind', img: 'icons/svg/blind.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusComma, name: 'EFFECT.StatusComma', img: 'icons/svg/skull.svg' },
|
||||
|
||||
{ rdd: true, id: STATUSES.StatusBleeding, name: 'EFFECT.StatusBleeding', img: 'icons/svg/blood.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusDead, name: 'EFFECT.StatusDead', img: 'icons/svg/skull.svg' },
|
||||
{ rdd: true, id: STATUSES.StatusDemiReve, name: 'EFFECT.StatusDemiReve', img: 'systems/foundryvtt-reve-de-dragon/icons/heures/hd12.svg' }
|
||||
demiReveStatusEffect
|
||||
];
|
||||
const demiReveStatusEffect = rddStatusEffects.find(it => it.id == STATUSES.StatusDemiReve);
|
||||
|
||||
const statusDemiSurprise = new Set([STATUSES.StatusStunned, STATUSES.StatusProne, STATUSES.StatusRestrained])
|
||||
const statusSurpriseTotale = new Set([STATUSES.StatusUnconscious, STATUSES.StatusBlind, STATUSES.StatusComma])
|
||||
|
||||
export class StatusEffects extends FormApplication {
|
||||
|
||||
|
||||
static onReady() {
|
||||
const rddEffectIds = rddStatusEffects.map(it => it.id);
|
||||
rddStatusEffects.forEach(it => {
|
||||
it.statuses = new Set()
|
||||
it.statuses.add(it.id)
|
||||
it.statuses = new Set([it.id])
|
||||
})
|
||||
const defaultStatusEffectIds = CONFIG.statusEffects.map(it => it.id);
|
||||
game.settings.register(SYSTEM_RDD, "use-status-effects", {
|
||||
@@ -63,19 +67,31 @@ export class StatusEffects extends FormApplication {
|
||||
console.log('statusEffects', CONFIG.statusEffects);
|
||||
}
|
||||
|
||||
static valeurSurprise(effect, isCombat) {
|
||||
static niveauSurprise(effect, isCombat) {
|
||||
if (statusSurpriseTotale.intersects(effect.statuses)) {
|
||||
return 2
|
||||
}
|
||||
if (statusDemiSurprise.intersects(effect.statuses)) {
|
||||
return 1
|
||||
}
|
||||
if (isCombat && effect.statuses.find(e => e == STATUSES.StatusDemiReve)) {
|
||||
if (isCombat && StatusEffects.isDemiReve(effect)) {
|
||||
return 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
static typeSurprise(niveauSurprise) {
|
||||
switch (niveauSurprise) {
|
||||
case 0: return ''
|
||||
case 1: return 'demi'
|
||||
default: return 'totale'
|
||||
}
|
||||
}
|
||||
|
||||
static isDemiReve(effect) {
|
||||
return effect.statuses.has(STATUSES.StatusDemiReve)
|
||||
}
|
||||
|
||||
static _getUseStatusEffects() {
|
||||
return game.settings.get(SYSTEM_RDD, "use-status-effects")?.split(',') ?? [];
|
||||
}
|
||||
@@ -92,10 +108,10 @@ export class StatusEffects extends FormApplication {
|
||||
}
|
||||
|
||||
static prepareActiveEffect(effectId) {
|
||||
let status = rddStatusEffects.find(it => it.id == effectId)
|
||||
const status = rddStatusEffects.find(it => it.id == effectId)
|
||||
if (status) {
|
||||
status = foundry.utils.duplicate(status)
|
||||
status.statuses = [effectId]
|
||||
status.statuses = new Set([effectId])
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
@@ -304,7 +304,7 @@ export class TMRUtility {
|
||||
}
|
||||
|
||||
static typeTmrName(type) {
|
||||
return Misc.upperFirst(TMRType[Grammar.toLowerCaseNoAccent(type)].name);
|
||||
return type ? Misc.upperFirst(TMRType[Grammar.toLowerCaseNoAccent(type)].name) : ''
|
||||
}
|
||||
|
||||
static buildSelectionTypesTMR(typesTMR) {
|
||||
|
@@ -67,7 +67,9 @@
|
||||
<input class="derivee-value" type="number" name="system.compteurs.eau.value" value="{{system.compteurs.eau.value}}" data-dtype="number"/>
|
||||
</li>
|
||||
<li class="caracteristique flexrow list-item" data-tooltip="Niveau d'éthylisme">
|
||||
<label for="system.compteurs.ethylisme.value">{{system.compteurs.ethylisme.label}}</label>
|
||||
<label for="system.compteurs.ethylisme.value">{{system.compteurs.ethylisme.label}}
|
||||
{{#if system.compteurs.ethylisme.nb_doses}}({{system.compteurs.ethylisme.nb_doses}} doses){{/if}}
|
||||
</label>
|
||||
<select class="derivee-value" name="system.compteurs.ethylisme.value" data-dtype="Number">
|
||||
{{selectOptions (RDD_CONFIG 'niveauEthylisme') selected=system.compteurs.ethylisme.value valueAttr="value" nameAttr="value" labelAttr="label"}}
|
||||
</select>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<li class="caracteristique flexrow list-item">
|
||||
<span class="carac-label">Niveau</span>
|
||||
<label class="carac-value">{{numberFormat niveau decimals=0 sign=true}}
|
||||
<label class="carac-value">{{plusMoins niveau}}
|
||||
</label>
|
||||
<label class="carac-xp"/>
|
||||
</li>
|
||||
|
@@ -4,6 +4,6 @@
|
||||
{{#each list as |comp|}}
|
||||
<span class="item" data-item-id="{{comp._id}}"><a class="roll-competence">{{comp.name}}</a></span>{{~#unless (isLastIndex @index ../list)~}},{{/unless~}}
|
||||
{{/each}}
|
||||
{{numberFormat niveau decimals=0 sign=true}}
|
||||
{{plusMoins niveau}}
|
||||
{{/with}}
|
||||
{{/each}}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<div class="flexrow item" data-item-id="{{competence._id}}">
|
||||
<a class="roll-competence" name="Esquive">{{upperFirst name}}</a>
|
||||
<div class="flexrow">
|
||||
<div>{{numberFormat competence.system.niveau decimals=0 sign=true}}</div>
|
||||
<div>{{plusMoins competence.system.niveau}}</div>
|
||||
<div></div>
|
||||
<div></div>
|
||||
</div>
|
||||
|
@@ -14,7 +14,7 @@
|
||||
<span class="flex-grow-2">
|
||||
{{#if sort.system.caseTMRspeciale}}{{sort.system.caseTMRspeciale}}{{else}}{{upperFirst sort.system.caseTMR}}{{/if}}
|
||||
</span>
|
||||
<span class="flex-grow-1">R{{itemSort-spaceIfText sort.system.difficulte}} r{{itemSort-spaceIfText sort.system.ptreve}}</span>
|
||||
<span class="flex-grow-1">{{itemSort-diffReve sort}} {{itemSort-coutReve sort}}</span>
|
||||
{{>'systems/foundryvtt-reve-de-dragon/templates/actor/item-action-controls.hbs' item=sort options=@root.options}}
|
||||
</li>
|
||||
{{/each}}
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<ul class="item-list alterne-list">
|
||||
{{#each subacteurs.montures as |monture id|}}
|
||||
<li class="item flexrow list-item" data-subactor-id="{{monture.id}}" data-tooltip="{{monture.name}}">
|
||||
<img class="sheet-competence-img subacteur-open" src="{{monture.img}}"/>
|
||||
<img class="actor-img-small subacteur-open" src="{{monture.img}}"/>
|
||||
<span class="subacteur-label subacteur-open"><a>{{monture.name}}</a></span>
|
||||
<div class="flex-shrink">
|
||||
<a class="subacteur-delete" data-tooltip="Supprimer"><i class="fas fa-trash"></i></a>
|
||||
|
@@ -2,7 +2,7 @@
|
||||
<ul class="item-list alterne-list">
|
||||
{{#each subacteurs.suivants as |suivant id|}}
|
||||
<li class="item flexrow list-item" data-subactor-id="{{suivant.id}}" data-tooltip="{{suivant.name}}">
|
||||
<img class="sheet-competence-img subacteur-open" src="{{suivant.img}}"/>
|
||||
<img class="actor-img-small subacteur-open" src="{{suivant.img}}"/>
|
||||
<span class="subacteur-label subacteur-open">
|
||||
<a>{{suivant.name}}</a>
|
||||
</span>
|
||||
|
@@ -12,7 +12,7 @@
|
||||
|
||||
{{#each subacteurs.vehicules as |vehicule id|}}
|
||||
<li class="item flexrow list-item" data-subactor-id="{{vehicule.id}}">
|
||||
<img class="sheet-competence-img subacteur-open" src="{{vehicule.img}}" data-tooltip="{{vehicule.name}}"/>
|
||||
<img class="actor-img-small subacteur-open" src="{{vehicule.img}}" data-tooltip="{{vehicule.name}}"/>
|
||||
<span class="subacteur-label subacteur-open"><a>{{vehicule.name}}</a></span>
|
||||
<span>{{vehicule.system.categorie}}</span>
|
||||
<span>{{vehicule.system.etat.resistance.max}}</span>
|
||||
|
@@ -4,7 +4,7 @@
|
||||
<ol class="item-list alterne-list">
|
||||
{{#each resonances as |actor|}}
|
||||
<li class="item flexrow list-item" data-actor-id="{{actor.id}}">
|
||||
<img class="sheet-competence-img subacteur-open" src="{{actor.img}}" data-tooltip="{{actor.name}}"/>
|
||||
<img class="actor-img-small subacteur-open" src="{{actor.img}}" data-tooltip="{{actor.name}}"/>
|
||||
<span class="subacteur-label subacteur-open"><a>{{actor.name}}</a></span>
|
||||
|
||||
{{!-- {{>'systems/foundryvtt-reve-de-dragon/templates/actor/item-action-controls.hbs' item=oeuvre options=@root.options}} --}}
|
||||
|
@@ -4,6 +4,7 @@
|
||||
<span>{{rolled.caracValue}} à {{plusMoins rolled.finalLevel}}</span>
|
||||
{{#if ajustements}}
|
||||
{{/if}}
|
||||
{{log this}}
|
||||
{{#if rolled.factorHtml}}<span class="rdd-diviseur">×{{{rolled.factorHtml}}}</span>{{/if}}
|
||||
<span>= {{rolled.score}}%</span>
|
||||
{{#if rolled.factorHtml}}
|
||||
|
@@ -10,5 +10,5 @@
|
||||
La méditation de {{alias}} ne porte pas ses fruits, il ne distingue aucun signe Draconique.
|
||||
{{/if}}
|
||||
<br><span>{{alias}} s'est fatigué de 2 cases.</span>
|
||||
{{#if rolled.isEPart}}<br><span>Son échec {{#if rolled.isETotal}}total{{else}}particulier{{/if}} augmente de 1 la difficulté de la méditation!</span>{{/if~}}
|
||||
{{#if rolled.isEPart}}<br><span>Son échec {{#if rolled.isETotal}}total{{else}}particulier{{/if}} augmente la difficulté de la méditation de 1 !</span>{{/if~}}
|
||||
</p>
|
||||
|
8
templates/partial-description.hbs
Normal file
@@ -0,0 +1,8 @@
|
||||
{{#if (or description reference)}}
|
||||
<div class="poesie-extrait">
|
||||
{{{description}}}
|
||||
{{#if reference}}
|
||||
<p class="poesie-reference">{{reference}}</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
@@ -1,11 +1,11 @@
|
||||
<div class="table-ajustement">
|
||||
<span class="tooltip tooltip-dotted">
|
||||
<span>Ajustement Final:</span>
|
||||
<span class="roll-param-resolution">{{selectedCarac.value}} / {{plusMoins finalLevel}}</span>
|
||||
<span class="roll-part-resolution">{{selectedCarac.value}} / {{plusMoins finalLevel}}</span>
|
||||
<div class="tooltiptext ttt-ajustements">
|
||||
{{#each ajustements as |item key|}}
|
||||
{{#if item.used}}
|
||||
<div class="{{#if item.strong}}strong-text{{/if}}">
|
||||
<div>
|
||||
{{#if item.descr}}
|
||||
{{{item.descr}}}
|
||||
{{else}}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<div class="flexrow utilisation-coeur">
|
||||
<label class="">Ajustement de Cœur</label>
|
||||
<div class="select-suivant">
|
||||
<img class="sheet-competence-img selected-suivant-coeur" src="{{use.coeur.img}}" data-tooltip="{{use.coeur.name}}" />
|
||||
<img class="actor-img-small selected-suivant-coeur" src="{{use.coeur.img}}" data-tooltip="{{use.coeur.name}}" />
|
||||
<select name="select-suivant-coeur" class="select-suivant-coeur" data-dtype="String">
|
||||
<option value="">Ignorer</option>
|
||||
{{#each amoureux as |amour id|}}
|
||||
|
@@ -1,4 +1,4 @@
|
||||
<div class="flexrow">
|
||||
<div class="flexrow" >
|
||||
<label for="diffLibre">Difficulté choisie</label>
|
||||
<select name="diffLibre" data-dtype="number" {{#unless use.libre}}disabled{{/unless}}>
|
||||
{{#select diffLibre}}
|
||||
|
@@ -4,7 +4,7 @@
|
||||
{{rolled.roll}}
|
||||
</strong> sur {{rolled.score}}%
|
||||
{{#if (and rolled.caracValue rolled.finalLevel)}}
|
||||
({{#if (gt rolled.diviseurSignificative 1)}}1/{{rolled.diviseurSignificative}}{{/if}}
|
||||
({{#if (gt rolled.diviseurSignificative 1)}}{{fractionOneN rolled.diviseurSignificative}}{{/if}}
|
||||
de {{rolled.caracValue}} à {{plusMoins rolled.finalLevel}})
|
||||
{{/if}}
|
||||
<strong>{{rolled.quality}}</strong>
|
||||
|
23
templates/roll/roll-ajustements.hbs
Normal file
@@ -0,0 +1,23 @@
|
||||
<div class="table-ajustement">
|
||||
<span class="tooltip tooltip-dotted">
|
||||
<span class="roll-part-resolution">Ajustements: {{rollData.current.carac.value}} à {{plusMoins rollData.current.totaldiff}}</span>
|
||||
<div class="tooltiptext ttt-ajustements">
|
||||
{{#each rollData.ajustements as |ajust|}}
|
||||
{{#if ajust}}
|
||||
<div>
|
||||
{{#if ajust.descr}}
|
||||
{{{ajust.descr}}}
|
||||
{{else}}
|
||||
{{{ajust.label}}}{{#if ajust.isDiff}}: {{plusMoins ajust.diff}}{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</span>
|
||||
{{#if rollData.current.significative.used}}
|
||||
<br><span>
|
||||
Significative requise <span class="rdd-diviseur">×{{{rollData.current.significative.label}}}</span>!
|
||||
</span>
|
||||
{{/if}}
|
||||
</div>
|
6
templates/roll/roll-button.hbs
Normal file
@@ -0,0 +1,6 @@
|
||||
<button name="roll-dialog-button">Lancer
|
||||
{{rollData.current.carac.value}} à {{plusMoins rollData.current.totaldiff}}
|
||||
{{#if rollData.current.significative.used}}
|
||||
<span class="rdd-diviseur">×{{{rollData.current.significative.label}}}</span>
|
||||
{{/if}}
|
||||
</button>
|